Browse Source

Implement Storybook controls

Implement Storybook controls for some categories.
master
TheoryOfNekomata 1 year ago
parent
commit
8204f15aad
11 changed files with 283 additions and 88 deletions
  1. +3
    -1
      categories/web/action/react/.eslintrc
  2. +19
    -4
      categories/web/action/react/src/components/ActionButton/ActionButton.stories.tsx
  3. +55
    -34
      categories/web/action/react/src/components/ActionButton/index.tsx
  4. +11
    -1
      categories/web/blob/react/src/components/FileSelectBox/FileSelectBox.stories.tsx
  5. +29
    -2
      categories/web/choice/react/src/components/ComboBox/ComboBox.stories.tsx
  6. +23
    -2
      categories/web/choice/react/src/components/DropdownSelect/DropdownSelect.stories.tsx
  7. +28
    -4
      categories/web/choice/react/src/components/MenuSelect/MenuSelect.stories.tsx
  8. +4
    -1
      categories/web/navigation/react/.eslintrc
  9. +16
    -3
      categories/web/navigation/react/src/components/LinkButton/LinkButton.stories.tsx
  10. +62
    -36
      categories/web/navigation/react/src/components/LinkButton/index.tsx
  11. +33
    -0
      storybook/react/tailwind.config.ts

+ 3
- 1
categories/web/action/react/.eslintrc View File

@@ -6,7 +6,9 @@
"react/button-has-type": "off", "react/button-has-type": "off",
"import/no-extraneous-dependencies": "off", "import/no-extraneous-dependencies": "off",
"no-tabs": "off", "no-tabs": "off",
"indent": "off"
"indent": "off",
"react/jsx-indent": "off",
"react/jsx-indent-props": "off"
}, },
"extends": [ "extends": [
"lxsmnsyc/typescript/react" "lxsmnsyc/typescript/react"


+ 19
- 4
categories/web/action/react/src/components/ActionButton/ActionButton.stories.tsx View File

@@ -18,6 +18,18 @@ const meta: Meta<typeof Component> = {
control: { type: 'select' }, control: { type: 'select' },
options: Button.AVAILABLE_SIZES, options: Button.AVAILABLE_SIZES,
}, },
subtext: {
control: { type: 'text' },
},
badge: {
control: { type: 'text' },
},
icon: {
control: { type: 'text' },
},
children: {
control: { type: 'text' },
},
onClick: { onClick: {
table: { table: {
disable: true, disable: true,
@@ -25,15 +37,18 @@ const meta: Meta<typeof Component> = {
action: 'clicked', action: 'clicked',
}, },
}, },
args: Component.defaultProps ?? {},
args: {
...(Component.defaultProps ?? {}),
subtext: 'Subtext',
badge: '1',
children: 'Button',
},
}; };


export const ActionButton = (args: Omit<Props, 'ref'>) => ( export const ActionButton = (args: Omit<Props, 'ref'>) => (
<Component <Component
{...args} {...args}
>
Button
</Component>
/>
); );


export default meta; export default meta;

+ 55
- 34
categories/web/action/react/src/components/ActionButton/index.tsx View File

@@ -44,9 +44,13 @@ export interface ActionButtonProps extends Omit<React.HTMLProps<ActionButtonDeri
*/ */
compact?: boolean; compact?: boolean;
/** /**
* Should the children's height be variable?
* Graphical representation of the component.
*/ */
variableChildrenHeight?: boolean;
icon?: React.ReactNode;
/**
* Should the graphical representation of the component be placed after the children?
*/
iconAfterChildren?: boolean;
} }


/** /**
@@ -66,7 +70,8 @@ export const ActionButton = React.forwardRef<ActionButtonDerivedElement, ActionB
compact = false as const, compact = false as const,
className, className,
block = false as const, block = false as const,
variableChildrenHeight = false as const,
icon,
iconAfterChildren = false as const,
...etcProps ...etcProps
}, },
forwardedRef, forwardedRef,
@@ -106,37 +111,52 @@ export const ActionButton = React.forwardRef<ActionButtonDerivedElement, ActionB
> >
<span <span
className={clsx( className={clsx(
'flex-auto min-w-0',
{
'text-left': compact || menuItem,
'text-center': !(compact || menuItem),
},
)}
'flex-auto min-w-0 flex items-center gap-2',
iconAfterChildren ? 'flex-row-reverse' : 'flex-row',
)}
> >
<span
className={clsx(
'block uppercase font-bold w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded',
{
'h-[1.1em]': !variableChildrenHeight,
},
)}
data-testid="children"
>
{children}
</span>
{subtext && (
<>
<span className="sr-only">
{' - '}
</span>
<span
className="block h-[1.3em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded font-bold text-xs"
data-testid="subtext"
>
{subtext}
</span>
</>
)}
{icon && (
<span
data-testid="icon"
>
{icon}
</span>
)}
{(children || subtext) && (
<span
className={clsx(
'min-w-0 flex-auto',
{
'text-left': compact || menuItem,
'text-center': !(compact || menuItem),
},
)}
>
{children && (
<span
className={clsx(
'block uppercase font-bold w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded h-[1.1em]',
)}
data-testid="children"
>
{children}
</span>
)}
{subtext && (
<>
<span className="sr-only">
{' - '}
</span>
<span
className="block h-[1.3em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded font-bold text-xs"
data-testid="subtext"
>
{subtext}
</span>
</>
)}
</span>
)}
</span> </span>
{badge && ( {badge && (
<> <>
@@ -177,5 +197,6 @@ ActionButton.defaultProps = {
menuItem: false as const, menuItem: false as const,
size: 'medium' as const, size: 'medium' as const,
compact: false as const, compact: false as const,
variableChildrenHeight: false as const,
icon: undefined,
iconAfterChildren: false as const,
}; };

+ 11
- 1
categories/web/blob/react/src/components/FileSelectBox/FileSelectBox.stories.tsx View File

@@ -10,6 +10,12 @@ const meta: Meta<typeof Component> = {
disable: true, disable: true,
} }
}, },
label: {
control: { type: 'text' },
},
hint: {
control: { type: 'text' },
},
onChange: { onChange: {
table: { table: {
disable: true, disable: true,
@@ -17,7 +23,11 @@ const meta: Meta<typeof Component> = {
action: 'changed', action: 'changed',
}, },
}, },
args: Component.defaultProps ?? {},
args: {
...(Component.defaultProps ?? {}),
label: 'ファイル選択',
hint: 'ファイルを選択してください。',
},
}; };


export const FileSelectBox = (args: Omit<Props, 'ref'>) => ( export const FileSelectBox = (args: Omit<Props, 'ref'>) => (


+ 29
- 2
categories/web/choice/react/src/components/ComboBox/ComboBox.stories.tsx View File

@@ -5,6 +5,21 @@ import { ComboBox as Component, ComboBoxProps as Props } from '.';
const meta: Meta<typeof Component> = { const meta: Meta<typeof Component> = {
component: Component, component: Component,
argTypes: { argTypes: {
label: {
control: { type: 'text' },
},
hint: {
control: { type: 'text' },
},
indicator: {
control: { type: 'text' },
},
children: {
control: { type: 'text' },
},
length: {
control: { type: 'number' },
},
onChange: { onChange: {
table: { table: {
disable: true, disable: true,
@@ -18,10 +33,22 @@ const meta: Meta<typeof Component> = {
}, },
}; };


export const ComboBox = (args: Omit<Props, 'ref'>) => (
export const ComboBox = ({ children = '', ...args }: Omit<Props, 'ref'>) => (
<Component <Component
{...args} {...args}
/>
>
{(children ? children.toString() : '').split('\n').filter(s => s.length > 0).map((s, i) => {
const [label, value = label] = s.split(':').map(s => s.trim()) as string[];
return (
<option
key={`${s}:${i}`}
value={value}
>
{label}
</option>
);
})}
</Component>
); );


export default meta; export default meta;

+ 23
- 2
categories/web/choice/react/src/components/DropdownSelect/DropdownSelect.stories.tsx View File

@@ -5,6 +5,15 @@ import { DropdownSelect as Component, DropdownSelectProps as Props } from '.';
const meta: Meta<typeof Component> = { const meta: Meta<typeof Component> = {
component: Component, component: Component,
argTypes: { argTypes: {
label: {
control: { type: 'text' },
},
hint: {
control: { type: 'text' },
},
children: {
control: { type: 'text' },
},
onChange: { onChange: {
table: { table: {
disable: true, disable: true,
@@ -17,10 +26,22 @@ const meta: Meta<typeof Component> = {
}, },
}; };


export const DropdownSelect = (args: Omit<Props, 'ref'>) => (
export const DropdownSelect = ({ children = '', ...args }: Omit<Props, 'ref'>) => (
<Component <Component
{...args} {...args}
/>
>
{(children ? children.toString() : '').split('\n').filter(s => s.length > 0).map((s, i) => {
const [label, value = label] = s.split(':').map(s => s.trim()) as string[];
return (
<option
key={`${s}:${i}`}
value={value}
>
{label}
</option>
);
})}
</Component>
); );


export default meta; export default meta;

+ 28
- 4
categories/web/choice/react/src/components/MenuSelect/MenuSelect.stories.tsx View File

@@ -1,10 +1,22 @@
import * as React from 'react'; import * as React from 'react';
import type { Meta } from '@storybook/react';
import { MenuSelect as Component, MenuSelectProps as Props } from '.';
import type {Meta} from '@storybook/react';
import {MenuSelect as Component, MenuSelectProps as Props} from '.';


const meta: Meta<typeof Component> = { const meta: Meta<typeof Component> = {
component: Component, component: Component,
argTypes: { argTypes: {
label: {
control: { type: 'text' },
},
hint: {
control: { type: 'text' },
},
indicator: {
control: { type: 'text' },
},
children: {
control: { type: 'text' },
},
onChange: { onChange: {
table: { table: {
disable: true, disable: true,
@@ -17,10 +29,22 @@ const meta: Meta<typeof Component> = {
}, },
}; };


export const MenuSelect = (args: Omit<Props, 'ref'>) => (
export const MenuSelect = ({ children = '', ...args }: Omit<Props, 'ref'>) => (
<Component <Component
{...args} {...args}
/>
>
{(children ? children.toString() : '').split('\n').filter(s => s.length > 0).map((s, i) => {
const [label, value = label] = s.split(':').map(s => s.trim()) as string[];
return (
<option
key={`${s}:${i}`}
value={value}
>
{label}
</option>
);
})}
</Component>
); );


export default meta; export default meta;

+ 4
- 1
categories/web/navigation/react/.eslintrc View File

@@ -2,7 +2,10 @@
"root": true, "root": true,
"rules": { "rules": {
"react/jsx-props-no-spreading": "off", "react/jsx-props-no-spreading": "off",
"no-tabs": "off"
"no-tabs": "off",
"indent": "off",
"react/jsx-indent": "off",
"react/jsx-indent-props": "off"
}, },
"extends": [ "extends": [
"lxsmnsyc/typescript/react" "lxsmnsyc/typescript/react"


+ 16
- 3
categories/web/navigation/react/src/components/LinkButton/LinkButton.stories.tsx View File

@@ -18,6 +18,21 @@ const meta: Meta<typeof Component> = {
control: { type: 'select' }, control: { type: 'select' },
options: Button.AVAILABLE_SIZES, options: Button.AVAILABLE_SIZES,
}, },
subtext: {
control: { type: 'text' },
},
badge: {
control: { type: 'text' },
},
icon: {
control: { type: 'text' },
},
children: {
control: { type: 'text' },
},
href: {
control: { type: 'text' },
},
onClick: { onClick: {
table: { table: {
disable: true, disable: true,
@@ -31,9 +46,7 @@ const meta: Meta<typeof Component> = {
export const LinkButton = (args: Omit<LinkButtonProps, 'ref'>) => ( export const LinkButton = (args: Omit<LinkButtonProps, 'ref'>) => (
<Component <Component
{...args} {...args}
>
Button
</Component>
/>
); );


export default meta; export default meta;

+ 62
- 36
categories/web/navigation/react/src/components/LinkButton/index.tsx View File

@@ -10,7 +10,7 @@ export type LinkButtonDerivedElement = HTMLAnchorElement;
/** /**
* Props of the {@link LinkButton} component. * Props of the {@link LinkButton} component.
*/ */
export interface LinkButtonProps<T = any> extends Omit<React.HTMLProps<LinkButtonDerivedElement>, 'size'> {
export interface LinkButtonProps<T = any> extends Omit<React.HTMLProps<LinkButtonDerivedElement>, 'href' | 'size'> {
/** /**
* Should the component occupy the whole width of its parent? * Should the component occupy the whole width of its parent?
*/ */
@@ -48,9 +48,17 @@ export interface LinkButtonProps<T = any> extends Omit<React.HTMLProps<LinkButto
*/ */
disabled?: boolean; disabled?: boolean;
/** /**
* Should the children's height be variable?
* Graphical representation of the component.
*/ */
variableChildrenHeight?: boolean;
icon?: React.ReactNode;
/**
* Should the graphical representation of the component be placed after the children?
*/
iconAfterChildren?: boolean;
/**
* URL to navigate to.
*/
href?: string | unknown;
} }


/** /**
@@ -71,7 +79,8 @@ export const LinkButton = React.forwardRef<LinkButtonDerivedElement, LinkButtonP
disabled = false, disabled = false,
href, href,
style, style,
variableChildrenHeight = false as const,
icon,
iconAfterChildren = false as const,
...etcProps ...etcProps
}, },
forwardedRef, forwardedRef,
@@ -115,38 +124,53 @@ export const LinkButton = React.forwardRef<LinkButtonDerivedElement, LinkButtonP
style={style} style={style}
> >
<span <span
className={clsx(
'flex-auto min-w-0',
{
'text-left': compact || menuItem,
'text-center': !(compact || menuItem),
},
)}
className={clsx(
'flex-auto min-w-0 flex items-center gap-2',
iconAfterChildren ? 'flex-row-reverse' : 'flex-row',
)}
> >
<span
className={clsx(
'block uppercase font-bold w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded',
{
'h-[1.1em]': !variableChildrenHeight,
},
)}
data-testid="children"
>
{children}
</span>
{subtext && (
<>
<span className="sr-only">
{' - '}
</span>
<span
className="block h-[1.3em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded font-bold text-xs"
data-testid="subtext"
>
{subtext}
</span>
</>
)}
{icon && (
<span
data-testid="icon"
>
{icon}
</span>
)}
{(children || subtext) && (
<span
className={clsx(
'min-w-0 flex-auto',
{
'text-left': compact || menuItem,
'text-center': !(compact || menuItem),
},
)}
>
{children && (
<span
className={clsx(
'block uppercase font-bold w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded h-[1.1em]',
)}
data-testid="children"
>
{children}
</span>
)}
{subtext && (
<>
<span className="sr-only">
{' - '}
</span>
<span
className="block h-[1.3em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded font-bold text-xs"
data-testid="subtext"
>
{subtext}
</span>
</>
)}
</span>
)}
</span> </span>
{badge && ( {badge && (
<> <>
@@ -189,5 +213,7 @@ LinkButton.defaultProps = {
subtext: undefined, subtext: undefined,
block: false, block: false,
disabled: false, disabled: false,
variableChildrenHeight: false as const,
icon: undefined,
iconAfterChildren: false as const,
href: undefined,
}; };

+ 33
- 0
storybook/react/tailwind.config.ts View File

@@ -39,6 +39,39 @@ const config: Config = {
'inherit': 'inherit', 'inherit': 'inherit',
'transparent': 'transparent', 'transparent': 'transparent',
}, },
extend: {
fontSize: {
'lg': '1.125em',
'xl': '1.25em',
'2xl': '1.5em',
'3xl': '1.75em',
'4xl': '2em',
'5xl': '3em',
'6xl': '4em',
'xxs': '0.625rem',
},
borderRadius: {
inherit: 'inherit',
},
minWidth: {
6: '1.5rem',
10: '2.5rem',
12: '3rem',
16: '4rem',
48: '12rem',
64: '16rem',
},
minHeight: {
6: '1.5rem',
10: '2.5rem',
12: '3rem',
16: '4rem',
64: '16rem',
},
strokeWidth: {
3: '3',
},
},
}, },
plugins: [], plugins: [],
}; };


Loading…
Cancel
Save