ui: add components

This commit is contained in:
Yangshun Tay
2022-10-04 09:30:15 +08:00
parent db672a2beb
commit e93cc73d51
22 changed files with 1146 additions and 8 deletions

View File

@ -0,0 +1,41 @@
import { ComponentMeta } from '@storybook/react';
import { Badge, BadgeVariant } from '@tih/ui';
import React from 'react';
const badgeVariants: ReadonlyArray<BadgeVariant> = [
'primary',
'info',
'danger',
'success',
'warning',
];
export default {
title: 'Badge',
component: Badge,
argTypes: {
variant: {
options: badgeVariants,
control: { type: 'select' },
},
},
} as ComponentMeta<typeof Badge>;
export const Basic = {
args: {
label: 'Hello',
variant: 'primary',
},
};
export function Variants() {
return (
<div className="space-x-4">
<Badge label="Primary" variant="primary" />
<Badge label="Success" variant="success" />
<Badge label="Information" variant="info" />
<Badge label="Warning" variant="warning" />
<Badge label="Danger" variant="danger" />
</div>
);
}

View File

@ -45,7 +45,7 @@ export default {
control: 'boolean',
},
label: {
control: 'string',
control: 'text',
},
size: {
options: buttonSizes,

View File

@ -0,0 +1,56 @@
import { ComponentMeta } from '@storybook/react';
import { Button, Dialog } from '@tih/ui';
import React, { useState } from 'react';
export default {
title: 'Dialog',
component: Dialog,
argTypes: {
title: {
control: 'text',
},
},
} as ComponentMeta<typeof Dialog>;
export function Basic({ children, title }) {
const [isShown, setIsShown] = useState(false);
return (
<div>
<Button label="Open" variant="primary" onClick={() => setIsShown(true)} />
<Dialog
isShown={isShown}
primaryButton={
<Button
display="block"
label="OK"
variant="primary"
onClick={() => setIsShown(false)}
/>
}
secondaryButton={
<Button
display="block"
label="Cancel"
variant="tertiary"
onClick={() => setIsShown(false)}
/>
}
title={title}
onClose={() => setIsShown(false)}>
{children}
</Dialog>
</div>
);
}
Basic.args = {
title: 'Lorem ipsum, dolor sit amet',
children: (
<div>
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Eius aliquam
laudantium explicabo pariatur iste dolorem animi vitae error totam. At
sapiente aliquam accusamus facere veritatis.
</div>
),
};

View File

@ -0,0 +1,124 @@
import { ComponentMeta } from '@storybook/react';
import { DropdownMenu, DropdownMenuAlignment, DropdownMenuSize } from '@tih/ui';
import React, { useState } from 'react';
const DropdownMenuAlignments: ReadonlyArray<DropdownMenuAlignment> = [
'start',
'end',
];
const DropdownMenuSizes: ReadonlyArray<DropdownMenuSize> = [
'inherit',
'regular',
];
export default {
title: 'DropdownMenu',
component: DropdownMenu,
parameters: {
docs: {
inlineStories: false,
iframeHeight: 300,
},
},
argTypes: {
align: {
options: DropdownMenuAlignments,
control: { type: 'select' },
},
label: {
control: 'text',
},
size: {
options: DropdownMenuSizes,
control: { type: 'select' },
},
},
} as ComponentMeta<typeof DropdownMenu>;
export function Basic({ align, label, size }) {
const menuItems = [
{
label: 'Apple',
value: 'apple',
},
{
label: 'Banana',
value: 'banana',
},
{
label: 'Orange',
value: 'orange',
},
];
const [selectedValue, setSelectedValue] = useState('apple');
return (
<DropdownMenu align={align} label={label} size={size}>
{menuItems.map(({ label, value }) => (
<DropdownMenu.Item
key={value}
isSelected={value === selectedValue}
label={label}
onClick={() => {
setSelectedValue(value);
}}
/>
))}
</DropdownMenu>
);
}
Basic.args = {
align: 'start',
label: 'Select fruitzz',
size: 'regular',
};
export function Align() {
const menuItems = [
{
label: 'Apple',
value: 'apple',
},
{
label: 'Banana',
value: 'banana',
},
{
label: 'Orange',
value: 'orange',
},
];
const [selectedValue, setSelectedValue] = useState('apple');
return (
<div className="flex justify-between">
<DropdownMenu align="start" label="Select fruit" size="regular">
{menuItems.map(({ label, value }) => (
<DropdownMenu.Item
key={value}
isSelected={value === selectedValue}
label={label}
onClick={() => {
setSelectedValue(value);
}}
/>
))}
</DropdownMenu>
<DropdownMenu align="end" label="Select fruit" size="regular">
{menuItems.map(({ label, value }) => (
<DropdownMenu.Item
key={value}
isSelected={value === selectedValue}
label={label}
onClick={() => {
setSelectedValue(value);
}}
/>
))}
</DropdownMenu>
</div>
);
}

View File

@ -0,0 +1,88 @@
import { ComponentMeta } from '@storybook/react';
import { Select, SelectDisplay } from '@tih/ui';
import React, { useState } from 'react';
const SelectDisplays: ReadonlyArray<SelectDisplay> = ['inline', 'block'];
export default {
title: 'Select',
component: Select,
argTypes: {
display: {
options: SelectDisplays,
control: { type: 'select' },
},
isLabelHidden: {
control: 'boolean',
},
label: {
control: 'text',
},
name: {
control: 'text',
},
},
} as ComponentMeta<typeof Select>;
export function Basic({ display, isLabelHidden, label, name }) {
const [value, setValue] = useState('apple');
return (
<Select
display={display}
isLabelHidden={isLabelHidden}
label={label}
onChange={setValue}
name={name}
options={[
{
label: 'Apple',
value: 'apple',
},
{
label: 'Banana',
value: 'banana',
},
{
label: 'Orange',
value: 'orange',
},
]}
value={value}
/>
);
}
Basic.args = {
label: 'Select fruit',
display: 'inline',
isLabelHidden: false,
};
export function Display() {
const [value, setValue] = useState('apple');
return (
<div className="space-x-4">
<Select
label="Select a fruit"
onChange={setValue}
options={[
{
label: 'Apple',
value: 'apple',
},
{
label: 'Banana',
value: 'banana',
},
{
label: 'Orange',
value: 'orange',
},
]}
value={value}
/>
</div>
);
}

View File

@ -0,0 +1,49 @@
import { ComponentMeta } from '@storybook/react';
import { Button, SlideOut, SlideOutEnterFrom, SlideOutSize } from '@tih/ui';
import React, { useState } from 'react';
const slideOutEnterFrom: ReadonlyArray<SlideOutEnterFrom> = ['start', 'end'];
const slideOutSize: ReadonlyArray<SlideOutSize> = ['sm', 'md', 'lg', 'xl'];
export default {
title: 'SlideOut',
component: SlideOut,
argTypes: {
title: {
control: 'text',
},
enterFrom: {
options: slideOutEnterFrom,
control: { type: 'select' },
},
size: {
options: slideOutSize,
control: { type: 'select' },
},
},
} as ComponentMeta<typeof SlideOut>;
export function Basic({ children, enterFrom, size, title }) {
const [isShown, setIsShown] = useState(false);
return (
<div>
<Button label="Open" variant="primary" onClick={() => setIsShown(true)} />
<SlideOut
enterFrom={enterFrom}
isShown={isShown}
size={size}
title={title}
onClose={() => setIsShown(false)}>
{children}
</SlideOut>
</div>
);
}
Basic.args = {
title: 'Navigation',
children: <div className="p-4">Hello World</div>,
enterFrom: 'end',
size: 'md',
};

View File

@ -20,7 +20,7 @@ export default {
control: { type: 'select' },
},
label: {
control: 'string',
control: 'text',
},
size: {
options: spinnerSizes,

View File

@ -0,0 +1,43 @@
import { ComponentMeta } from '@storybook/react';
import { Tabs } from '@tih/ui';
import React, { useState } from 'react';
export default {
title: 'Tabs',
component: Tabs,
argTypes: {
label: {
control: 'text',
},
},
} as ComponentMeta<typeof Tabs>;
export function Basic({ label }) {
const [value, setValue] = useState('apple');
return (
<Tabs
label={label}
onChange={setValue}
tabs={[
{
label: 'Apple',
value: 'apple',
},
{
label: 'Banana',
value: 'banana',
},
{
label: 'Orange',
value: 'orange',
},
]}
value={value}
/>
);
}
Basic.args = {
label: 'Fruits Navigation',
};

View File

@ -0,0 +1,129 @@
import {
EnvelopeIcon,
KeyIcon,
QuestionMarkCircleIcon,
} from '@heroicons/react/24/solid';
import { ComponentMeta } from '@storybook/react';
import { TextInput } from '@tih/ui';
import React, { useState } from 'react';
export default {
title: 'TextInput',
component: TextInput,
argTypes: {
autoComplete: {
control: 'text',
},
errorMessage: {
control: 'text',
},
isDisabled: {
control: 'boolean',
},
isLabelHidden: {
control: 'boolean',
},
label: {
control: 'text',
},
name: {
control: 'text',
},
placeholder: {
control: 'text',
},
type: {
control: 'text',
},
},
} as ComponentMeta<typeof TextInput>;
export const Basic = {
args: {
label: 'Name',
placeholder: 'John Doe',
},
};
export function HiddenLabel() {
const [value, setValue] = useState('');
return (
<TextInput
isLabelHidden={true}
label="Name"
placeholder="John Doe"
type="text"
value={value}
onChange={setValue}
/>
);
}
export function Email() {
const [value, setValue] = useState('');
return (
<TextInput
label="Email"
placeholder="john.doe@email.com"
startIcon={EnvelopeIcon}
type="email"
value={value}
onChange={setValue}
/>
);
}
export function Icon() {
const [value, setValue] = useState('');
return (
<div className="space-y-4">
<TextInput
endIcon={QuestionMarkCircleIcon}
label="Account number"
placeholder="000-00-0000"
type="text"
value={value}
onChange={setValue}
/>
<TextInput
startIcon={QuestionMarkCircleIcon}
label="Account number"
placeholder="000-00-0000"
type="text"
value={value}
onChange={setValue}
/>
</div>
);
}
export function Disabled() {
return (
<TextInput
isDisabled={true}
label="Disabled input"
placeholder="John Doe"
type="text"
/>
);
}
export function Error() {
const [value, setValue] = useState('1234');
return (
<TextInput
label="Email"
errorMessage={
value.length < 6 ? 'Password must be at least 6 characters' : undefined
}
startIcon={KeyIcon}
type="password"
value={value}
onChange={setValue}
/>
);
}