Skip to content

Commit 216df36

Browse files
authoredNov 28, 2024··
feat(Table): 縦線を引くための bordetType を追加、ほか (#5144)
1 parent 1f5e553 commit 216df36

20 files changed

+869
-860
lines changed
 

‎packages/smarthr-ui/src/components/Table/BulkActionRow.tsx

+4-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { ComponentPropsWithRef, FC, PropsWithChildren, useMemo } from 'react'
1+
import React, { ComponentPropsWithRef, FC, PropsWithChildren } from 'react'
22
import { tv } from 'tailwind-variants'
33

44
import { useTableHeadCellCount } from './useTableHeadCellCount'
@@ -20,17 +20,11 @@ export const BulkActionRow: FC<PropsWithChildren<ComponentPropsWithRef<'tr'>>> =
2020
}) => {
2121
const { countHeadCellRef, count } = useTableHeadCellCount<HTMLTableRowElement>()
2222

23-
const { wrapperStyle, cellStyle } = useMemo(() => {
24-
const { wrapper, cell } = bulkActionRow()
25-
return {
26-
wrapperStyle: wrapper({ className }),
27-
cellStyle: cell(),
28-
}
29-
}, [className])
23+
const { wrapper, cell } = bulkActionRow()
3024

3125
return (
32-
<tr {...props} ref={countHeadCellRef} className={wrapperStyle}>
33-
<td colSpan={count} className={cellStyle}>
26+
<tr {...props} ref={countHeadCellRef} className={wrapper({ className })}>
27+
<td colSpan={count} className={cell()}>
3428
{children}
3529
</td>
3630
</tr>

‎packages/smarthr-ui/src/components/Table/EmptyTableBody.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,13 @@ const emptyTableBodyCell = tv({
6868
X3L: 'shr-px-4',
6969
} as { [key in Gap]: string },
7070
},
71+
defaultVariants: {
72+
paddingBlock: 4,
73+
paddingInline: 4,
74+
},
7175
})
7276

73-
export const EmptyTableBody: React.FC<Props & ElementProps> = ({
74-
children,
75-
padding = 4,
76-
...props
77-
}) => {
77+
export const EmptyTableBody: React.FC<Props & ElementProps> = ({ children, padding, ...props }) => {
7878
const { countHeadCellRef, count } = useTableHeadCellCount<HTMLTableSectionElement>()
7979

8080
const tdStyles = useMemo(() => {

‎packages/smarthr-ui/src/components/Table/Table.stories.tsx

-643
This file was deleted.

‎packages/smarthr-ui/src/components/Table/Table.tsx

+16-14
Original file line numberDiff line numberDiff line change
@@ -7,40 +7,42 @@ type ElementProps = Omit<ComponentProps<'table'>, keyof Props>
77
const table = tv({
88
base: [
99
'smarthr-ui-Table',
10-
'shr-w-full',
11-
/* Headがfixed=trueの場合、separate以外だとHeadとBodyの間に隙間が生まれるため、明示的に指定しています */
12-
'shr-broder-separate',
13-
'shr-border-spacing-0',
14-
'shr-bg-column',
10+
'shr-border-collapse shr-w-full',
1511
'[&_tbody]:shr-bg-white',
1612
'[&_th]:contrast-more:shr-border-shorthand [&_th]:shr-bg-head [&_th]:contrast-more:shr-border-high-contrast',
1713
'[&_td]:contrast-more:shr-border-shorthand [&_td]:contrast-more:shr-border-high-contrast',
1814
'contrast-more:shr-border-shorthand contrast-more:shr-border-high-contrast',
1915
],
2016
variants: {
17+
borderType: {
18+
horizontal: 'shr-table-border-horizontal',
19+
both: 'shr-table-border-vertical shr-table-border-horizontal',
20+
},
2121
layout: {
2222
auto: '',
2323
fixed: 'shr-table-fixed',
2424
},
2525
fixedHead: {
26-
true: [
27-
'[&_thead]:shr-sticky [&_thead]:shr-start-0 [&_thead]:shr-top-0',
28-
/* zIndexの値はセマンティックトークンとして管理しているため、明示的に値を指定しないと重なり順が崩れるため設定しています */
29-
'[&_thead]:shr-z-fixed-menu',
30-
],
26+
true: '[&_thead]:shr-sticky [&_thead]:shr-start-0 [&_thead]:shr-top-0 [&_thead]:shr-z-1',
3127
},
3228
},
29+
defaultVariants: {
30+
borderType: 'horizontal',
31+
layout: 'auto',
32+
fixedHead: false,
33+
},
3334
})
3435

3536
export const Table: FC<Props & ElementProps> = ({
36-
fixedHead = false,
37-
layout = 'auto',
37+
borderType,
38+
fixedHead,
39+
layout,
3840
className,
3941
...props
4042
}) => {
4143
const styles = useMemo(
42-
() => table({ fixedHead, layout, className }),
43-
[className, fixedHead, layout],
44+
() => table({ borderType, fixedHead, layout, className }),
45+
[borderType, className, fixedHead, layout],
4446
)
4547
return <table {...props} className={styles} />
4648
}

‎packages/smarthr-ui/src/components/Table/Td.tsx

+23-5
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,17 @@ export type Props = PropsWithChildren<
1515
type ElementProps = Omit<ComponentPropsWithoutRef<'td'>, keyof Props>
1616

1717
export const Td: FC<Props & ElementProps> = ({
18-
align = 'left',
19-
nullable = false,
18+
align,
19+
vAlign,
20+
nullable,
2021
fixed = false,
2122
contentWidth,
2223
className,
2324
style,
2425
...props
2526
}) => {
2627
const styleProps = useMemo(() => {
27-
const tdStyles = td({ align, nullable, fixed, className })
28+
const tdStyles = td({ align, vAlign, nullable, fixed, className })
2829
const reelShadowStyles = fixed ? reelShadowStyle({ direction: 'right' }) : ''
2930
return {
3031
className: `${tdStyles} ${reelShadowStyles}`.trim(),
@@ -33,21 +34,33 @@ export const Td: FC<Props & ElementProps> = ({
3334
...getWidthStyle(contentWidth),
3435
},
3536
}
36-
}, [align, className, contentWidth, fixed, nullable, style])
37+
}, [align, className, contentWidth, fixed, nullable, style, vAlign])
3738

3839
return <td {...props} {...styleProps} />
3940
}
4041

4142
const td = tv({
4243
base: [
4344
'smarthr-ui-Td',
44-
'shr-border-t-shorthand shr-h-[calc(1em_*_theme(lineHeight.normal))] shr-px-1 shr-py-0.5 shr-align-middle shr-text-base shr-leading-normal shr-text-black',
45+
'shr-border-solid shr-border-0 shr-px-1 shr-py-0.5 shr-align-middle shr-text-base shr-leading-normal shr-text-black shr-h-[calc(1em_*_theme(lineHeight.normal))]',
46+
[
47+
'[.shr-table-border-horizontal_&]:shr-border-t',
48+
'[.shr-table-border-horizontal_&]:shr-border-t-default',
49+
],
50+
[
51+
'[.shr-table-border-vertical_&+&]:shr-border-l',
52+
'[.shr-table-border-vertical_&+&]:shr-border-l-default',
53+
],
4554
],
4655
variants: {
4756
align: {
4857
left: '',
4958
right: 'shr-text-right',
5059
},
60+
vAlign: {
61+
middle: '',
62+
baseline: 'shr-align-baseline',
63+
},
5164
nullable: {
5265
true: "empty:after:shr-content-['-----']",
5366
},
@@ -58,6 +71,11 @@ const td = tv({
5871
],
5972
},
6073
},
74+
defaultVariants: {
75+
align: 'left',
76+
vAlign: 'middle',
77+
nullable: false,
78+
},
6179
})
6280

6381
const convertContentWidth = (contentWidth?: CellContentWidth) => {

‎packages/smarthr-ui/src/components/Table/TdCheckbox.tsx

+16-27
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,39 @@
1-
import React, { ReactNode, forwardRef, useMemo } from 'react'
1+
import React, { ComponentProps, PropsWithChildren, forwardRef } from 'react'
22
import { tv } from 'tailwind-variants'
33

44
import { CheckBox, Props as CheckBoxProps } from '../CheckBox'
5-
import { Center } from '../Layout'
65
import { VisuallyHiddenText } from '../VisuallyHiddenText'
76

87
import { Td } from './Td'
98

10-
type Props = {
9+
type Props = PropsWithChildren<{
1110
/** 値を特定するための行 id */
1211
'aria-labelledby': string
13-
/** aria-labelledby では特定できない場合に補足するための不可視ラベル */
14-
children?: ReactNode
15-
}
12+
}> &
13+
Pick<ComponentProps<typeof Td>, 'vAlign'>
1614

1715
const tdCheckbox = tv({
1816
slots: {
19-
inner: 'shr-absolute shr-inset-0 [&:not(:has([disabled]))]:shr-cursor-pointer',
20-
wrapper: 'shr-relative shr-w-[theme(fontSize.base)] [&]:shr-p-0.75',
21-
checkbox: '[&]:shr-block',
17+
inner: [
18+
'shr-flex shr-justify-center shr-py-0.75 shr-px-1',
19+
'[&:not(:has([disabled]))]:shr-cursor-pointer',
20+
],
21+
wrapper: 'shr-p-0 shr-w-[theme(fontSize.base)]',
22+
checkbox: ['shr-leading-[0]', '[&>span]:shr-translate-y-[unset]'],
2223
},
2324
})
2425

2526
export const TdCheckbox = forwardRef<HTMLInputElement, Omit<CheckBoxProps, keyof Props> & Props>(
26-
({ 'aria-labelledby': ariaLabelledby, children, className, ...others }, ref) => {
27-
const { wrapperStyle, innerStyle, checkboxStyle } = useMemo(() => {
28-
const { wrapper, inner, checkbox } = tdCheckbox()
29-
return {
30-
wrapperStyle: wrapper({ className }),
31-
innerStyle: inner(),
32-
checkboxStyle: checkbox(),
33-
}
34-
}, [className])
27+
({ vAlign, 'aria-labelledby': ariaLabelledby, children, className, ...others }, ref) => {
28+
const { wrapper, inner, checkbox } = tdCheckbox()
3529

3630
return (
3731
// Td に必要な属性やイベントは不要
38-
<Td className={wrapperStyle}>
39-
<Center as="label" verticalCentering className={innerStyle}>
40-
<CheckBox
41-
{...others}
42-
ref={ref}
43-
aria-labelledby={ariaLabelledby}
44-
className={checkboxStyle}
45-
/>
32+
<Td vAlign={vAlign} className={wrapper({ className })}>
33+
<label className={inner()}>
34+
<CheckBox {...others} ref={ref} aria-labelledby={ariaLabelledby} className={checkbox()} />
4635
{children && <VisuallyHiddenText>{children}</VisuallyHiddenText>}
47-
</Center>
36+
</label>
4837
</Td>
4938
)
5039
},

‎packages/smarthr-ui/src/components/Table/Th.tsx

+18-4
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,11 @@ const SORT_DIRECTION_LABEL = {
4242
const thWrapper = tv({
4343
base: [
4444
'smarthr-ui-Th',
45-
'shr-px-1 shr-py-0.75 shr-text-left shr-align-middle shr-text-sm shr-font-bold shr-leading-tight shr-text-black',
45+
'shr-border-solid shr-border-0 shr-px-1 shr-py-0.75 shr-text-left shr-align-middle shr-text-sm shr-font-bold shr-leading-tight shr-text-black',
46+
[
47+
'[.shr-table-border-vertical_&+&]:shr-border-l',
48+
'[.shr-table-border-vertical_&+&]:shr-border-l-default',
49+
],
4650
'aria-[sort]:shr-cursor-pointer',
4751
'hover:aria-[sort]:shr-bg-head-darken',
4852
'[&:has(:focus-visible)]:aria-[sort]:shr-focus-indicator',
@@ -55,6 +59,11 @@ const thWrapper = tv({
5559
left: '',
5660
right: 'shr-text-right',
5761
},
62+
vAlign: {
63+
middle: '',
64+
baseline: 'shr-align-baseline',
65+
bottom: 'shr-align-bottom',
66+
},
5867
fixed: {
5968
true: [
6069
/* これ以降の記述はTableReel内で'fixed'を利用した際に追従させるために必要 */
@@ -63,6 +72,10 @@ const thWrapper = tv({
6372
],
6473
},
6574
},
75+
defaultVariants: {
76+
align: 'left',
77+
vAlign: 'middle',
78+
},
6679
})
6780

6881
const convertContentWidth = (contentWidth?: CellContentWidth) => {
@@ -79,15 +92,16 @@ export const Th: FC<Props & ElementProps> = ({
7992
sort,
8093
onSort,
8194
decorators,
82-
align = 'left',
95+
align,
96+
vAlign,
8397
fixed = false,
8498
contentWidth,
8599
className,
86100
style,
87101
...props
88102
}) => {
89103
const styleProps = useMemo(() => {
90-
const thWrapperStyle = thWrapper({ className, align, fixed })
104+
const thWrapperStyle = thWrapper({ className, align, vAlign, fixed })
91105
const reelShadowStyles = fixed ? reelShadowStyle({ showShadow: false, direction: 'right' }) : ''
92106
return {
93107
className: `${thWrapperStyle} ${reelShadowStyles}`.trim(),
@@ -96,7 +110,7 @@ export const Th: FC<Props & ElementProps> = ({
96110
width: convertContentWidth(contentWidth),
97111
},
98112
}
99-
}, [align, className, contentWidth, fixed, style])
113+
}, [align, className, contentWidth, fixed, style, vAlign])
100114

101115
const sortLabel = useMemo(
102116
() =>

‎packages/smarthr-ui/src/components/Table/ThCheckbox.tsx

+17-21
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import React, { forwardRef, useMemo } from 'react'
1+
import React, { ComponentProps, forwardRef, useMemo } from 'react'
22
import { tv } from 'tailwind-variants'
33

44
import { Balloon } from '../Balloon'
55
import { CheckBox, Props as CheckBoxProps } from '../CheckBox'
6-
import { Center } from '../Layout'
76

87
import { Th } from './Th'
98

@@ -13,16 +12,20 @@ type Props = {
1312
decorators?: DecoratorsType<'checkAllInvisibleLabel'> & {
1413
checkColumnName?: (text: string) => string
1514
}
16-
}
15+
} & Pick<ComponentProps<typeof Th>, 'vAlign'>
1716

1817
const CHECK_ALL_INVISIBLE_LABEL = 'すべての項目を選択/解除'
1918
const CHECK_COLUMN_NAME = '選択'
2019

2120
const thCheckbox = tv({
2221
slots: {
23-
inner: 'shr-absolute shr-inset-0 [&:not(:has([disabled]))]:shr-cursor-pointer shr-group/label',
24-
wrapper: 'shr-relative shr-w-[theme(fontSize.base)] [&]:shr-px-0.75',
25-
checkbox: '[&]:shr-block',
22+
inner: [
23+
'shr-group/label',
24+
'shr-relative shr-flex shr-justify-center shr-py-0.75 shr-px-1',
25+
'[&:not(:has([disabled]))]:shr-cursor-pointer',
26+
],
27+
wrapper: 'shr-p-0 shr-w-[theme(fontSize.base)]',
28+
checkbox: ['shr-leading-[0]', '[&>span]:shr-translate-y-[unset]'],
2629
balloon: [
2730
// 位置はセルの真ん中(50%)+checkboxの幅の半分(8px)+outlineの幅(4px)+Balloonの矢印の幅(5px), sr-onlyで隠す
2831
'shr-absolute shr-left-[calc(50%+(theme(fontSize.base)/2)+4px+5px)] shr-sr-only',
@@ -33,16 +36,8 @@ const thCheckbox = tv({
3336
})
3437

3538
export const ThCheckbox = forwardRef<HTMLInputElement, CheckBoxProps & Props>(
36-
({ decorators, className, ...others }, ref) => {
37-
const { wrapperStyle, innerStyle, balloonStyle, checkboxStyle } = useMemo(() => {
38-
const { wrapper, inner, balloon, checkbox } = thCheckbox()
39-
return {
40-
wrapperStyle: wrapper({ className }),
41-
innerStyle: inner(),
42-
checkboxStyle: checkbox(),
43-
balloonStyle: balloon(),
44-
}
45-
}, [className])
39+
({ vAlign, decorators, className, ...others }, ref) => {
40+
const { wrapper, inner, balloon, checkbox } = thCheckbox()
4641

4742
const checkAllInvisibleLabel = useMemo(() => {
4843
if (decorators && decorators.checkAllInvisibleLabel) {
@@ -62,13 +57,14 @@ export const ThCheckbox = forwardRef<HTMLInputElement, CheckBoxProps & Props>(
6257

6358
return (
6459
// Th に必要な属性やイベントは不要
65-
<Th className={wrapperStyle} aria-label={checkColumnName}>
66-
<Center as="label" verticalCentering className={innerStyle}>
67-
<Balloon as="span" horizontal="left" vertical="middle" className={balloonStyle}>
60+
<Th vAlign={vAlign} className={wrapper({ className })} aria-label={checkColumnName}>
61+
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
62+
<label className={inner()}>
63+
<Balloon as="span" horizontal="left" vertical="middle" className={balloon()}>
6864
<span className="shr-p-0.5 shr-block">{checkAllInvisibleLabel}</span>
6965
</Balloon>
70-
<CheckBox {...others} ref={ref} className={checkboxStyle} />
71-
</Center>
66+
<CheckBox {...others} ref={ref} className={checkbox()} />
67+
</label>
7268
</Th>
7369
)
7470
},

‎packages/smarthr-ui/src/components/Table/VRTTable.stories.tsx

-130
This file was deleted.

‎packages/smarthr-ui/src/components/Table/WakuWakuButton.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import React from 'react'
22

33
import { Button } from '../Button'
44

5-
type Props = Omit<React.ComponentProps<typeof Button>, 'variant' | 'size'>
5+
type Props = Omit<
6+
React.ComponentProps<typeof Button>,
7+
'variant' | 'size' | 'prefix' | 'suffix' | 'disabledDetail' | 'wide' | 'square' | 'loading'
8+
>
69

710
export const WakuWakuButton: React.FC<Props> = (props) => (
811
<Button {...props} variant="text" size="s" className="shr-text-link-darken" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React from 'react'
2+
3+
import { BulkActionRow } from '../BulkActionRow'
4+
import { Table } from '../Table'
5+
6+
import type { Meta, StoryObj } from '@storybook/react'
7+
8+
export default {
9+
title: 'Data Display(データ表示)/Table/BulkActionRow',
10+
component: BulkActionRow,
11+
render: (args) => (
12+
<Table>
13+
<thead>
14+
<BulkActionRow {...args}>一括操作領域</BulkActionRow>
15+
</thead>
16+
</Table>
17+
),
18+
args: {},
19+
parameters: {
20+
chromatic: { disableSnapshot: true },
21+
},
22+
} satisfies Meta<typeof BulkActionRow>
23+
24+
export const Playground: StoryObj<typeof BulkActionRow> = {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import React from 'react'
2+
3+
import { Stack } from '../../Layout'
4+
import { EmptyTableBody } from '../EmptyTableBody'
5+
import { Table } from '../Table'
6+
import { Th } from '../Th'
7+
8+
import type { Meta, StoryFn, StoryObj } from '@storybook/react'
9+
10+
const Template: StoryFn<typeof EmptyTableBody> = ({ children, ...args }) => (
11+
<Table>
12+
<thead>
13+
<tr>
14+
<Th>表頭1</Th>
15+
<Th>表頭2</Th>
16+
<Th>表頭3</Th>
17+
</tr>
18+
</thead>
19+
<EmptyTableBody {...args}>
20+
{children ?? (
21+
<>
22+
<p>該当するオブジェクトはありません。</p>
23+
<p>別の条件を試してください。</p>
24+
</>
25+
)}
26+
</EmptyTableBody>
27+
</Table>
28+
)
29+
30+
export default {
31+
title: 'Data Display(データ表示)/Table/EmptyTableBody',
32+
component: EmptyTableBody,
33+
render: Template,
34+
args: {},
35+
parameters: {
36+
chromatic: { disableSnapshot: true },
37+
},
38+
} satisfies Meta<typeof EmptyTableBody>
39+
40+
export const Playground: StoryObj<typeof EmptyTableBody> = {}
41+
42+
export const Padding: StoryObj<typeof EmptyTableBody> = {
43+
render: (args) => (
44+
<Stack>
45+
{[undefined, 0, 0.25, 0.5, 0.75, 1, 1.25, 1.5, 2, 2.5, 3, 3.5, 4, 8].map((padding) => (
46+
<Template {...args} padding={padding as any} key={padding}>
47+
<p>padding: {padding}</p>
48+
</Template>
49+
))}
50+
</Stack>
51+
),
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import React from 'react'
2+
3+
import { Stack } from '../../Layout'
4+
import { BulkActionRow } from '../BulkActionRow'
5+
import { EmptyTableBody } from '../EmptyTableBody'
6+
import { Table } from '../Table'
7+
import { TableReel } from '../TableReel'
8+
import { Td } from '../Td'
9+
import { TdCheckbox } from '../TdCheckbox'
10+
import { Th } from '../Th'
11+
import { ThCheckbox } from '../ThCheckbox'
12+
import { WakuWakuButton } from '../WakuWakuButton'
13+
14+
import type { Meta, StoryFn, StoryObj } from '@storybook/react'
15+
16+
const Template: StoryFn<typeof Table> = (args) => (
17+
<Table {...args}>
18+
<thead>
19+
<tr>
20+
<Th>オブジェクト名</Th>
21+
<Th>オブジェクトの情報1</Th>
22+
<Th>オブジェクトの情報2</Th>
23+
</tr>
24+
</thead>
25+
<tbody>
26+
<tr>
27+
<Td>オブジェクト1</Td>
28+
<Td>情報1</Td>
29+
<Td>2024-11-26</Td>
30+
</tr>
31+
</tbody>
32+
</Table>
33+
)
34+
35+
export default {
36+
title: 'Data Display(データ表示)/Table',
37+
component: Table,
38+
subcomponents: {
39+
Th,
40+
Td,
41+
ThCheckbox,
42+
TdCheckbox,
43+
BulkActionRow,
44+
EmptyTableBody,
45+
WakuWakuButton,
46+
TableReel,
47+
},
48+
render: Template,
49+
args: {},
50+
parameters: {
51+
chromatic: { disableSnapshot: true },
52+
},
53+
} as Meta<typeof Table>
54+
55+
export const Playground: StoryObj<typeof Table> = {}
56+
57+
export const BorderType: StoryObj<typeof Table> = {
58+
name: 'borderType',
59+
render: (args) => (
60+
<Stack>
61+
<Template {...args} />
62+
<Template {...args} borderType="horizontal" />
63+
<Template {...args} borderType="both" />
64+
</Stack>
65+
),
66+
}
67+
68+
export const Layout: StoryObj<typeof Table> = {
69+
name: 'layout',
70+
render: (args) => (
71+
<Stack>
72+
<Template {...args} />
73+
<Template {...args} layout="auto" />
74+
<Template {...args} layout="fixed" />
75+
</Stack>
76+
),
77+
}
78+
79+
export const FixedHead: StoryObj<typeof Table> = {
80+
name: 'fixedHead',
81+
render: (args) => (
82+
<Table {...args}>
83+
<thead>
84+
<tr>
85+
<Th>オブジェクト名</Th>
86+
<Th>オブジェクトの情報1</Th>
87+
<Th>オブジェクトの情報2</Th>
88+
</tr>
89+
</thead>
90+
<tbody>
91+
{[...Array(50)].map((_, i) => (
92+
<tr key={i}>
93+
<Td>オブジェクト{i + 1}</Td>
94+
<Td>情報{i + 1}</Td>
95+
<Td>2024-11-26</Td>
96+
</tr>
97+
))}
98+
</tbody>
99+
</Table>
100+
),
101+
args: { fixedHead: true },
102+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import React from 'react'
2+
3+
import { Text } from '../../Text'
4+
import { Table } from '../Table'
5+
import { TableReel } from '../TableReel'
6+
import { Td } from '../Td'
7+
import { Th } from '../Th'
8+
9+
import type { Meta, StoryFn, StoryObj } from '@storybook/react'
10+
11+
const Template: StoryFn<typeof TableReel> = (args) => (
12+
<TableReel {...args} className="shr-w-[50vw]">
13+
<Table>
14+
<thead>
15+
<tr>
16+
{[...Array(10)].map((_, i) => (
17+
<Th key={i}>
18+
<Text whiteSpace="nowrap">表頭{i + 1}</Text>
19+
</Th>
20+
))}
21+
</tr>
22+
</thead>
23+
<tbody>
24+
<tr>
25+
{[...Array(10)].map((_, i) => (
26+
<Td key={i}>
27+
<Text whiteSpace="nowrap">表データ{i + 1}</Text>
28+
</Td>
29+
))}
30+
</tr>
31+
</tbody>
32+
</Table>
33+
</TableReel>
34+
)
35+
36+
export default {
37+
title: 'Data Display(データ表示)/Table/TableReel',
38+
component: TableReel,
39+
render: Template,
40+
args: {},
41+
parameters: {
42+
chromatic: { disableSnapshot: true },
43+
},
44+
} satisfies Meta<typeof TableReel>
45+
46+
export const Playground: StoryObj<typeof TableReel> = {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import React from 'react'
2+
3+
import { Chip } from '../../Chip'
4+
import { Text } from '../../Text'
5+
import { Table } from '../Table'
6+
import { TableReel } from '../TableReel'
7+
import { Td } from '../Td'
8+
9+
import type { Meta, StoryFn, StoryObj } from '@storybook/react'
10+
11+
const Template: StoryFn<typeof Td> = (args) => (
12+
<Table>
13+
<tbody>
14+
<tr>
15+
<Td {...args} />
16+
</tr>
17+
</tbody>
18+
</Table>
19+
)
20+
21+
export default {
22+
title: 'Data Display(データ表示)/Table/Td',
23+
component: Td,
24+
render: Template,
25+
argTypes: {
26+
fixed: { description: 'TableReel を組み合わせると機能します。' },
27+
},
28+
args: {
29+
children: '表データ',
30+
},
31+
parameters: {
32+
chromatic: { disableSnapshot: true },
33+
},
34+
tags: ['skip-test-runner'],
35+
} satisfies Meta<typeof Td>
36+
37+
export const Playground: StoryObj<typeof Td> = {}
38+
39+
export const Align: StoryObj<typeof Td> = {
40+
name: 'align',
41+
render: (args) => (
42+
<Table borderType="both">
43+
<tbody>
44+
<tr>
45+
<Td {...args}>align: undefined</Td>
46+
<Td {...args} align="left">
47+
align: left
48+
</Td>
49+
<Td {...args} align="right">
50+
align: right
51+
</Td>
52+
</tr>
53+
</tbody>
54+
</Table>
55+
),
56+
}
57+
58+
export const VAlign: StoryObj<typeof Td> = {
59+
name: 'vAlign',
60+
render: (args) => (
61+
<Table>
62+
<tbody>
63+
<tr className="shr-h-[4em]">
64+
<Td {...args}>vAlign: undefined</Td>
65+
<Td {...args} vAlign="middle">
66+
vAlign: <Chip>middle</Chip>
67+
</Td>
68+
<Td {...args} vAlign="baseline">
69+
vAlign: <Chip>baseline</Chip>
70+
</Td>
71+
</tr>
72+
</tbody>
73+
</Table>
74+
),
75+
}
76+
77+
export const Nullable: StoryObj<typeof Td> = {
78+
name: 'nullable',
79+
args: { nullable: true, children: undefined },
80+
}
81+
82+
export const Fixed: StoryObj<typeof Td> = {
83+
name: 'fixed',
84+
render: (args) => (
85+
<TableReel className="shr-w-[50vw]">
86+
<Table>
87+
<tbody>
88+
<tr>
89+
{[...Array(20)].map((_, i) => (
90+
<Td {...args} key={i}>
91+
<Text whiteSpace="nowrap">表データ{i + 1}</Text>
92+
</Td>
93+
))}
94+
<Td {...args} fixed>
95+
<Text whiteSpace="nowrap">fixed: true</Text>
96+
</Td>
97+
</tr>
98+
</tbody>
99+
</Table>
100+
</TableReel>
101+
),
102+
}
103+
104+
export const ContentWidth: StoryObj<typeof Td> = {
105+
name: 'contentWidth',
106+
render: (args) => (
107+
<Table>
108+
<tbody>
109+
<tr>
110+
<Td {...args} contentWidth={5}>
111+
表データ1
112+
</Td>
113+
<Td {...args} contentWidth="100px">
114+
表データ2
115+
</Td>
116+
<Td contentWidth={{ base: 10, min: 5, max: 20 }}>表データ3</Td>
117+
<Td>表データ4</Td>
118+
<Td>表データ5</Td>
119+
</tr>
120+
</tbody>
121+
</Table>
122+
),
123+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import React from 'react'
2+
3+
import { Table } from '../Table'
4+
import { Td } from '../Td'
5+
import { TdCheckbox } from '../TdCheckbox'
6+
7+
import type { Meta, StoryFn, StoryObj } from '@storybook/react'
8+
9+
const Template: StoryFn<typeof TdCheckbox> = (args) => (
10+
<Table>
11+
<tbody>
12+
<tr>
13+
<TdCheckbox {...args} />
14+
</tr>
15+
</tbody>
16+
</Table>
17+
)
18+
19+
export default {
20+
title: 'Data Display(データ表示)/Table/TdCheckbox',
21+
component: TdCheckbox,
22+
render: Template,
23+
argTypes: {
24+
checked: { control: 'boolean' },
25+
},
26+
args: {},
27+
parameters: {
28+
chromatic: { disableSnapshot: true },
29+
},
30+
tags: ['skip-test-runner'],
31+
} satisfies Meta<typeof TdCheckbox>
32+
33+
export const Playground: StoryObj<typeof TdCheckbox> = {}
34+
35+
export const AriaLabelledBy: StoryObj<typeof TdCheckbox> = {
36+
name: 'aria-labelledby',
37+
render: (args) => (
38+
<Table>
39+
<tbody>
40+
<tr>
41+
<TdCheckbox {...args} aria-labelledby="label-name" vAlign="baseline" />
42+
<Td id="label-name">ラベル名</Td>
43+
</tr>
44+
</tbody>
45+
</Table>
46+
),
47+
}
48+
49+
export const Checked: StoryObj<typeof TdCheckbox> = {
50+
name: 'checked',
51+
args: {
52+
checked: true,
53+
},
54+
}
55+
56+
export const Mixed: StoryObj<typeof TdCheckbox> = {
57+
name: 'mixed',
58+
args: {
59+
checked: true,
60+
mixed: true,
61+
},
62+
}
63+
64+
export const Error: StoryObj<typeof TdCheckbox> = {
65+
name: 'error',
66+
args: {
67+
error: true,
68+
},
69+
}
70+
71+
export const VAlign: StoryObj<typeof TdCheckbox> = {
72+
name: 'vAlign',
73+
render: (args) => (
74+
<Table>
75+
<tbody>
76+
<tr className="shr-h-[4em]">
77+
<TdCheckbox {...args} />
78+
<TdCheckbox {...args} vAlign="middle" />
79+
<TdCheckbox {...args} vAlign="baseline" />
80+
</tr>
81+
</tbody>
82+
</Table>
83+
),
84+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import { action } from '@storybook/addon-actions'
2+
import React from 'react'
3+
4+
import { Chip } from '../../Chip'
5+
import { Stack } from '../../Layout'
6+
import { Text } from '../../Text'
7+
import { Table } from '../Table'
8+
import { TableReel } from '../TableReel'
9+
import { Th } from '../Th'
10+
11+
import type { Meta, StoryFn, StoryObj } from '@storybook/react'
12+
13+
const Template: StoryFn<typeof Th> = (args) => (
14+
<Table>
15+
<thead>
16+
<tr>
17+
<Th {...args}>表頭</Th>
18+
</tr>
19+
</thead>
20+
</Table>
21+
)
22+
23+
export default {
24+
title: 'Data Display(データ表示)/Table/Th',
25+
component: Th,
26+
render: Template,
27+
argTypes: {
28+
fixed: { description: 'TableReel を組み合わせると機能します。' },
29+
decorators: { control: false },
30+
},
31+
args: {},
32+
parameters: {
33+
chromatic: { disableSnapshot: true },
34+
},
35+
tags: ['skip-test-runner'],
36+
} satisfies Meta<typeof Th>
37+
38+
export const Playground: StoryObj<typeof Th> = {}
39+
40+
export const Sort: StoryObj<typeof Th> = {
41+
name: 'sort',
42+
render: (args) => (
43+
<Stack>
44+
<Template {...args} />
45+
<Template {...args} sort="asc" />
46+
<Template {...args} sort="desc" />
47+
<Template {...args} sort="none" />
48+
</Stack>
49+
),
50+
}
51+
52+
export const OnSort: StoryObj<typeof Th> = {
53+
name: 'onSort',
54+
render: (args) => <Template {...args} sort="desc" onSort={action('sort')} />,
55+
}
56+
57+
export const ContentWidth: StoryObj<typeof Th> = {
58+
name: 'contentWidth',
59+
render: (args) => (
60+
<Table>
61+
<thead>
62+
<tr>
63+
<Th {...args} contentWidth={5}>
64+
表頭1
65+
</Th>
66+
<Th {...args} contentWidth="100px">
67+
表頭2
68+
</Th>
69+
<Th>表頭3</Th>
70+
<Th>表頭4</Th>
71+
<Th>表頭5</Th>
72+
</tr>
73+
</thead>
74+
</Table>
75+
),
76+
}
77+
78+
export const Align: StoryObj<typeof Th> = {
79+
name: 'align',
80+
render: (args) => (
81+
<Table borderType="both">
82+
<thead>
83+
<tr>
84+
<Th {...args}>align: undefined</Th>
85+
<Th {...args} align="left">
86+
align: left
87+
</Th>
88+
<Th {...args} align="right">
89+
align: right
90+
</Th>
91+
</tr>
92+
</thead>
93+
</Table>
94+
),
95+
}
96+
97+
export const VAlign: StoryObj<typeof Th> = {
98+
name: 'vAlign',
99+
render: (args) => (
100+
<Table>
101+
<thead>
102+
<tr className="shr-h-[4em]">
103+
<Th {...args}>vAlign: undefined</Th>
104+
<Th {...args} vAlign="middle">
105+
vAlign: <Chip>middle</Chip>
106+
</Th>
107+
<Th {...args} vAlign="baseline">
108+
vAlign: <Chip>baseline</Chip>
109+
</Th>
110+
<Th {...args} vAlign="bottom">
111+
vAlign: <Chip>bottom</Chip>
112+
</Th>
113+
</tr>
114+
</thead>
115+
</Table>
116+
),
117+
}
118+
119+
export const Fixed: StoryObj<typeof Th> = {
120+
name: 'fixed',
121+
render: (args) => (
122+
<TableReel className="shr-w-[50vw]">
123+
<Table>
124+
<thead>
125+
<tr>
126+
{[...Array(20)].map((_, i) => (
127+
<Th {...args} key={i}>
128+
<Text whiteSpace="nowrap">表頭{i + 1}</Text>
129+
</Th>
130+
))}
131+
<Th {...args} fixed>
132+
<Text whiteSpace="nowrap">fixed: true</Text>
133+
</Th>
134+
</tr>
135+
</thead>
136+
</Table>
137+
</TableReel>
138+
),
139+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import React from 'react'
2+
3+
import { Table } from '../Table'
4+
import { ThCheckbox } from '../ThCheckbox'
5+
6+
import type { Meta, StoryFn, StoryObj } from '@storybook/react'
7+
8+
const Template: StoryFn<typeof ThCheckbox> = (args) => (
9+
<Table>
10+
<thead>
11+
<tr>
12+
<ThCheckbox {...args} />
13+
</tr>
14+
</thead>
15+
</Table>
16+
)
17+
18+
export default {
19+
title: 'Data Display(データ表示)/Table/ThCheckbox',
20+
component: ThCheckbox,
21+
render: Template,
22+
argTypes: {
23+
checked: { control: 'boolean' },
24+
decorators: { control: false },
25+
},
26+
args: {},
27+
parameters: {
28+
chromatic: { disableSnapshot: true },
29+
},
30+
tags: ['skip-test-runner'],
31+
} satisfies Meta<typeof ThCheckbox>
32+
33+
export const Playground: StoryObj<typeof ThCheckbox> = {}
34+
35+
export const Checked: StoryObj<typeof ThCheckbox> = {
36+
name: 'checked',
37+
args: {
38+
checked: true,
39+
},
40+
}
41+
42+
export const Mixed: StoryObj<typeof ThCheckbox> = {
43+
name: 'mixed',
44+
args: {
45+
checked: true,
46+
mixed: true,
47+
},
48+
}
49+
50+
export const Error: StoryObj<typeof ThCheckbox> = {
51+
name: 'error',
52+
args: {
53+
error: true,
54+
},
55+
}
56+
57+
export const VAlign: StoryObj<typeof ThCheckbox> = {
58+
name: 'vAlign',
59+
render: (args) => (
60+
<Table>
61+
<thead>
62+
<tr className="shr-h-[4em]">
63+
<ThCheckbox {...args} />
64+
<ThCheckbox {...args} vAlign="middle" />
65+
<ThCheckbox {...args} vAlign="baseline" />
66+
<ThCheckbox {...args} vAlign="bottom" />
67+
</tr>
68+
</thead>
69+
</Table>
70+
),
71+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import React from 'react'
2+
3+
import { Button } from '../../Button'
4+
import { Cluster, Stack } from '../../Layout'
5+
import { Text } from '../../Text'
6+
import { BulkActionRow } from '../BulkActionRow'
7+
import { Table } from '../Table'
8+
import { TableReel } from '../TableReel'
9+
import { Td } from '../Td'
10+
import { TdCheckbox } from '../TdCheckbox'
11+
import { Th } from '../Th'
12+
import { ThCheckbox } from '../ThCheckbox'
13+
import { WakuWakuButton } from '../WakuWakuButton'
14+
15+
import type { Meta, StoryObj } from '@storybook/react'
16+
17+
export default {
18+
title: 'Data Display(データ表示)/Table/VRT',
19+
render: (args) => (
20+
<Stack>
21+
{[undefined, true].map((fixed) =>
22+
[undefined, 'both'].map((borderType) => {
23+
const Wrapper = fixed ? TableReel : React.Fragment
24+
const wrapperProps = fixed ? { className: 'shr-w-[50vw]' } : {}
25+
return (
26+
<Wrapper {...wrapperProps} key={String(fixed)}>
27+
<Table {...args} borderType={borderType as any}>
28+
<thead>
29+
<tr>
30+
<ThCheckbox name="thead_checkbox" mixed checked />
31+
{[...Array(10)].map((_, i) => (
32+
<Th
33+
align={i === 2 ? 'right' : undefined}
34+
sort={i === 0 ? 'asc' : i === 1 ? 'desc' : i === 2 ? 'none' : undefined}
35+
key={i}
36+
>
37+
表頭{i + 1}
38+
</Th>
39+
))}
40+
<Th fixed={fixed}>操作</Th>
41+
</tr>
42+
<BulkActionRow>
43+
<Cluster inline align="center" className="shr-sticky shr-left-1">
44+
<p>n件のオブジェクトが選択されています。</p>
45+
<WakuWakuButton>一覧のオブジェクト9,999件すべてを選択</WakuWakuButton>
46+
</Cluster>
47+
</BulkActionRow>
48+
</thead>
49+
<tbody>
50+
{[...Array(10)].map((_, i) => (
51+
<tr key={i}>
52+
<TdCheckbox
53+
checked={i % 2 === 0}
54+
aria-labelledby={`td_${fixed}_${borderType}_${i + 1}_1`}
55+
name="tbody_checkbox"
56+
/>
57+
{[...Array(10)].map((__, j) => (
58+
<Td
59+
align={j === 2 ? 'right' : undefined}
60+
id={`td_${fixed}_${borderType}_${i + 1}_${j + 1}`}
61+
key={j}
62+
>
63+
<Text whiteSpace="nowrap">
64+
表データ{i + 1}-{j + 1}
65+
</Text>
66+
</Td>
67+
))}
68+
<Td fixed={fixed}>
69+
<Button size="s">操作</Button>
70+
</Td>
71+
</tr>
72+
))}
73+
</tbody>
74+
</Table>
75+
</Wrapper>
76+
)
77+
}),
78+
)}
79+
</Stack>
80+
),
81+
parameters: {
82+
chromatic: { disableSnapshot: false },
83+
},
84+
tags: ['!autodocs'],
85+
} satisfies Meta<typeof Table>
86+
87+
export const VRT = {}
88+
89+
export const VRTForcedColors: StoryObj = {
90+
...VRT,
91+
parameters: {
92+
chromatic: { forcedColors: 'active' },
93+
},
94+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import React from 'react'
2+
3+
import { Cluster } from '../../Layout'
4+
import { BulkActionRow } from '../BulkActionRow'
5+
import { Table } from '../Table'
6+
import { WakuWakuButton } from '../WakuWakuButton'
7+
8+
import type { Meta, StoryObj } from '@storybook/react'
9+
10+
export default {
11+
title: 'Data Display(データ表示)/Table/WakuWakuButton',
12+
component: WakuWakuButton,
13+
render: (args) => (
14+
<Table>
15+
<thead>
16+
<BulkActionRow>
17+
<Cluster align="center">
18+
<p>n件のオブジェクトが選択されています。</p>
19+
<WakuWakuButton {...args}>一覧のオブジェクト9,999件すべてを選択</WakuWakuButton>
20+
</Cluster>
21+
</BulkActionRow>
22+
</thead>
23+
</Table>
24+
),
25+
args: {},
26+
parameters: {
27+
chromatic: { disableSnapshot: true },
28+
},
29+
} satisfies Meta<typeof WakuWakuButton>
30+
31+
export const Playground: StoryObj<typeof WakuWakuButton> = {}

0 commit comments

Comments
 (0)
Please sign in to comment.