瀏覽代碼

Implement Storybook controls

Implement Storybook controls for some categories.
master
TheoryOfNekomata 1 年之前
父節點
當前提交
8204f15aad
共有 11 個文件被更改,包括 283 次插入88 次删除
  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 查看文件

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


+ 19
- 4
categories/web/action/react/src/components/ActionButton/ActionButton.stories.tsx 查看文件

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

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

export default meta;

+ 55
- 34
categories/web/action/react/src/components/ActionButton/index.tsx 查看文件

@@ -44,9 +44,13 @@ export interface ActionButtonProps extends Omit<React.HTMLProps<ActionButtonDeri
*/
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,
className,
block = false as const,
variableChildrenHeight = false as const,
icon,
iconAfterChildren = false as const,
...etcProps
},
forwardedRef,
@@ -106,37 +111,52 @@ export const ActionButton = React.forwardRef<ActionButtonDerivedElement, ActionB
>
<span
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>
{badge && (
<>
@@ -177,5 +197,6 @@ ActionButton.defaultProps = {
menuItem: false as const,
size: 'medium' 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 查看文件

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

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


+ 29
- 2
categories/web/choice/react/src/components/ComboBox/ComboBox.stories.tsx 查看文件

@@ -5,6 +5,21 @@ import { ComboBox as Component, ComboBoxProps as Props } from '.';
const meta: Meta<typeof Component> = {
component: Component,
argTypes: {
label: {
control: { type: 'text' },
},
hint: {
control: { type: 'text' },
},
indicator: {
control: { type: 'text' },
},
children: {
control: { type: 'text' },
},
length: {
control: { type: 'number' },
},
onChange: {
table: {
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
{...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;

+ 23
- 2
categories/web/choice/react/src/components/DropdownSelect/DropdownSelect.stories.tsx 查看文件

@@ -5,6 +5,15 @@ import { DropdownSelect as Component, DropdownSelectProps as Props } from '.';
const meta: Meta<typeof Component> = {
component: Component,
argTypes: {
label: {
control: { type: 'text' },
},
hint: {
control: { type: 'text' },
},
children: {
control: { type: 'text' },
},
onChange: {
table: {
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
{...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;

+ 28
- 4
categories/web/choice/react/src/components/MenuSelect/MenuSelect.stories.tsx 查看文件

@@ -1,10 +1,22 @@
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> = {
component: Component,
argTypes: {
label: {
control: { type: 'text' },
},
hint: {
control: { type: 'text' },
},
indicator: {
control: { type: 'text' },
},
children: {
control: { type: 'text' },
},
onChange: {
table: {
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
{...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;

+ 4
- 1
categories/web/navigation/react/.eslintrc 查看文件

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


+ 16
- 3
categories/web/navigation/react/src/components/LinkButton/LinkButton.stories.tsx 查看文件

@@ -18,6 +18,21 @@ const meta: Meta<typeof Component> = {
control: { type: 'select' },
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: {
table: {
disable: true,
@@ -31,9 +46,7 @@ const meta: Meta<typeof Component> = {
export const LinkButton = (args: Omit<LinkButtonProps, 'ref'>) => (
<Component
{...args}
>
Button
</Component>
/>
);

export default meta;

+ 62
- 36
categories/web/navigation/react/src/components/LinkButton/index.tsx 查看文件

@@ -10,7 +10,7 @@ export type LinkButtonDerivedElement = HTMLAnchorElement;
/**
* 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?
*/
@@ -48,9 +48,17 @@ export interface LinkButtonProps<T = any> extends Omit<React.HTMLProps<LinkButto
*/
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,
href,
style,
variableChildrenHeight = false as const,
icon,
iconAfterChildren = false as const,
...etcProps
},
forwardedRef,
@@ -115,38 +124,53 @@ export const LinkButton = React.forwardRef<LinkButtonDerivedElement, LinkButtonP
style={style}
>
<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>
{badge && (
<>
@@ -189,5 +213,7 @@ LinkButton.defaultProps = {
subtext: undefined,
block: false,
disabled: false,
variableChildrenHeight: false as const,
icon: undefined,
iconAfterChildren: false as const,
href: undefined,
};

+ 33
- 0
storybook/react/tailwind.config.ts 查看文件

@@ -39,6 +39,39 @@ const config: Config = {
'inherit': 'inherit',
'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: [],
};


Loading…
取消
儲存