@instructure/ui-table 11.6.0 → 11.6.1-snapshot-129
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +43 -308
- package/es/Table/{Body → v1/Body}/index.js +2 -2
- package/es/Table/{Cell → v1/Cell}/index.js +2 -2
- package/es/Table/{ColHeader → v1/ColHeader}/index.js +1 -1
- package/es/Table/{Head → v1/Head}/index.js +2 -2
- package/es/Table/{Row → v1/Row}/index.js +2 -2
- package/es/Table/{RowHeader → v1/RowHeader}/index.js +2 -2
- package/es/Table/{index.js → v1/index.js} +2 -2
- package/es/Table/v2/Body/index.js +73 -0
- package/es/Table/v2/Body/props.js +26 -0
- package/es/Table/v2/Body/styles.js +45 -0
- package/es/Table/v2/Cell/index.js +68 -0
- package/es/Table/v2/Cell/props.js +26 -0
- package/es/Table/v2/Cell/styles.js +54 -0
- package/es/Table/v2/ColHeader/index.js +117 -0
- package/es/Table/v2/ColHeader/props.js +26 -0
- package/es/Table/v2/ColHeader/styles.js +93 -0
- package/es/Table/v2/Head/index.js +173 -0
- package/es/Table/v2/Head/props.js +26 -0
- package/es/Table/v2/Head/styles.js +45 -0
- package/es/Table/v2/Row/index.js +82 -0
- package/es/Table/v2/Row/props.js +26 -0
- package/es/Table/v2/Row/styles.js +67 -0
- package/es/Table/v2/RowHeader/index.js +68 -0
- package/es/Table/v2/RowHeader/props.js +26 -0
- package/es/Table/v2/RowHeader/styles.js +54 -0
- package/es/Table/v2/TableContext.js +46 -0
- package/es/Table/v2/index.js +135 -0
- package/es/Table/v2/props.js +26 -0
- package/es/Table/v2/styles.js +58 -0
- package/es/exports/a.js +31 -0
- package/es/exports/b.js +31 -0
- package/lib/Table/{Body → v1/Body}/index.js +4 -4
- package/lib/Table/{Cell → v1/Cell}/index.js +4 -4
- package/lib/Table/{ColHeader → v1/ColHeader}/index.js +4 -4
- package/lib/Table/{Head → v1/Head}/index.js +5 -5
- package/lib/Table/{Row → v1/Row}/index.js +4 -4
- package/lib/Table/{RowHeader → v1/RowHeader}/index.js +4 -4
- package/lib/Table/{index.js → v1/index.js} +4 -4
- package/lib/Table/v2/Body/index.js +79 -0
- package/lib/Table/v2/Body/props.js +31 -0
- package/lib/Table/v2/Body/styles.js +51 -0
- package/lib/Table/v2/Cell/index.js +74 -0
- package/lib/Table/v2/Cell/props.js +31 -0
- package/lib/Table/v2/Cell/styles.js +60 -0
- package/lib/Table/v2/ColHeader/index.js +122 -0
- package/lib/Table/v2/ColHeader/props.js +31 -0
- package/lib/Table/v2/ColHeader/styles.js +99 -0
- package/lib/Table/v2/Head/index.js +179 -0
- package/lib/Table/v2/Head/props.js +31 -0
- package/lib/Table/v2/Head/styles.js +51 -0
- package/lib/Table/v2/Row/index.js +88 -0
- package/lib/Table/v2/Row/props.js +31 -0
- package/lib/Table/v2/Row/styles.js +73 -0
- package/lib/Table/v2/RowHeader/index.js +74 -0
- package/lib/Table/v2/RowHeader/props.js +31 -0
- package/lib/Table/v2/RowHeader/styles.js +60 -0
- package/lib/Table/v2/TableContext.js +51 -0
- package/lib/Table/v2/index.js +140 -0
- package/lib/Table/v2/props.js +31 -0
- package/lib/Table/v2/styles.js +64 -0
- package/lib/{index.js → exports/a.js} +9 -9
- package/lib/exports/b.js +61 -0
- package/package.json +43 -21
- package/src/Table/{Body → v1/Body}/index.tsx +2 -2
- package/src/Table/{Cell → v1/Cell}/index.tsx +2 -2
- package/src/Table/{ColHeader → v1/ColHeader}/index.tsx +1 -1
- package/src/Table/{Head → v1/Head}/index.tsx +3 -3
- package/src/Table/{README.md → v1/README.md} +1 -1
- package/src/Table/{Row → v1/Row}/index.tsx +2 -2
- package/src/Table/{RowHeader → v1/RowHeader}/index.tsx +2 -2
- package/src/Table/{index.tsx → v1/index.tsx} +2 -2
- package/src/Table/v2/Body/index.tsx +91 -0
- package/src/Table/v2/Body/props.ts +50 -0
- package/src/Table/v2/Body/styles.ts +51 -0
- package/src/Table/v2/Cell/index.tsx +83 -0
- package/src/Table/v2/Cell/props.ts +54 -0
- package/src/Table/v2/Cell/styles.ts +60 -0
- package/src/Table/v2/ColHeader/index.tsx +118 -0
- package/src/Table/v2/ColHeader/props.ts +93 -0
- package/src/Table/v2/ColHeader/styles.ts +95 -0
- package/src/Table/v2/Head/index.tsx +200 -0
- package/src/Table/v2/Head/props.ts +64 -0
- package/src/Table/v2/Head/styles.ts +51 -0
- package/src/Table/v2/README.md +1155 -0
- package/src/Table/v2/Row/index.tsx +105 -0
- package/src/Table/v2/Row/props.ts +67 -0
- package/src/Table/v2/Row/styles.ts +78 -0
- package/src/Table/v2/RowHeader/index.tsx +84 -0
- package/src/Table/v2/RowHeader/props.ts +48 -0
- package/src/Table/v2/RowHeader/styles.ts +60 -0
- package/src/Table/v2/TableContext.ts +66 -0
- package/src/Table/v2/index.tsx +160 -0
- package/src/Table/v2/props.ts +98 -0
- package/src/Table/v2/styles.ts +63 -0
- package/src/exports/a.ts +39 -0
- package/src/exports/b.ts +39 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/types/Table/v1/Body/index.d.ts.map +1 -0
- package/types/Table/v1/Body/props.d.ts.map +1 -0
- package/types/Table/v1/Body/styles.d.ts.map +1 -0
- package/types/Table/v1/Body/theme.d.ts.map +1 -0
- package/types/Table/v1/Cell/index.d.ts.map +1 -0
- package/types/Table/v1/Cell/props.d.ts.map +1 -0
- package/types/Table/v1/Cell/styles.d.ts.map +1 -0
- package/types/Table/v1/Cell/theme.d.ts.map +1 -0
- package/types/Table/v1/ColHeader/index.d.ts.map +1 -0
- package/types/Table/v1/ColHeader/props.d.ts.map +1 -0
- package/types/Table/v1/ColHeader/styles.d.ts.map +1 -0
- package/types/Table/v1/ColHeader/theme.d.ts.map +1 -0
- package/types/Table/v1/Head/index.d.ts.map +1 -0
- package/types/Table/v1/Head/props.d.ts.map +1 -0
- package/types/Table/v1/Head/styles.d.ts.map +1 -0
- package/types/Table/v1/Head/theme.d.ts.map +1 -0
- package/types/Table/v1/Row/index.d.ts.map +1 -0
- package/types/Table/v1/Row/props.d.ts.map +1 -0
- package/types/Table/v1/Row/styles.d.ts.map +1 -0
- package/types/Table/v1/Row/theme.d.ts.map +1 -0
- package/types/Table/v1/RowHeader/index.d.ts.map +1 -0
- package/types/Table/v1/RowHeader/props.d.ts.map +1 -0
- package/types/Table/v1/RowHeader/styles.d.ts.map +1 -0
- package/types/Table/v1/RowHeader/theme.d.ts.map +1 -0
- package/types/Table/v1/TableContext.d.ts.map +1 -0
- package/types/Table/v1/index.d.ts.map +1 -0
- package/types/Table/v1/props.d.ts.map +1 -0
- package/types/Table/v1/styles.d.ts.map +1 -0
- package/types/Table/v1/theme.d.ts.map +1 -0
- package/types/Table/v2/Body/index.d.ts +24 -0
- package/types/Table/v2/Body/index.d.ts.map +1 -0
- package/types/Table/v2/Body/props.d.ts +20 -0
- package/types/Table/v2/Body/props.d.ts.map +1 -0
- package/types/Table/v2/Body/styles.d.ts +13 -0
- package/types/Table/v2/Body/styles.d.ts.map +1 -0
- package/types/Table/v2/Cell/index.d.ts +29 -0
- package/types/Table/v2/Cell/index.d.ts.map +1 -0
- package/types/Table/v2/Cell/props.d.ts +23 -0
- package/types/Table/v2/Cell/props.d.ts.map +1 -0
- package/types/Table/v2/Cell/styles.d.ts +14 -0
- package/types/Table/v2/Cell/styles.d.ts.map +1 -0
- package/types/Table/v2/ColHeader/index.d.ts +37 -0
- package/types/Table/v2/ColHeader/index.d.ts.map +1 -0
- package/types/Table/v2/ColHeader/props.d.ts +47 -0
- package/types/Table/v2/ColHeader/props.d.ts.map +1 -0
- package/types/Table/v2/ColHeader/styles.d.ts +15 -0
- package/types/Table/v2/ColHeader/styles.d.ts.map +1 -0
- package/types/Table/v2/Head/index.d.ts +38 -0
- package/types/Table/v2/Head/index.d.ts.map +1 -0
- package/types/Table/v2/Head/props.d.ts +34 -0
- package/types/Table/v2/Head/props.d.ts.map +1 -0
- package/types/Table/v2/Head/styles.d.ts +13 -0
- package/types/Table/v2/Head/styles.d.ts.map +1 -0
- package/types/Table/v2/Row/index.d.ts +27 -0
- package/types/Table/v2/Row/index.d.ts.map +1 -0
- package/types/Table/v2/Row/props.d.ts +29 -0
- package/types/Table/v2/Row/props.d.ts.map +1 -0
- package/types/Table/v2/Row/styles.d.ts +19 -0
- package/types/Table/v2/Row/styles.d.ts.map +1 -0
- package/types/Table/v2/RowHeader/index.d.ts +28 -0
- package/types/Table/v2/RowHeader/index.d.ts.map +1 -0
- package/types/Table/v2/RowHeader/props.d.ts +17 -0
- package/types/Table/v2/RowHeader/props.d.ts.map +1 -0
- package/types/Table/v2/RowHeader/styles.d.ts +14 -0
- package/types/Table/v2/RowHeader/styles.d.ts.map +1 -0
- package/types/Table/v2/TableContext.d.ts +36 -0
- package/types/Table/v2/TableContext.d.ts.map +1 -0
- package/types/Table/v2/index.d.ts +45 -0
- package/types/Table/v2/index.d.ts.map +1 -0
- package/types/Table/v2/props.d.ts +53 -0
- package/types/Table/v2/props.d.ts.map +1 -0
- package/types/Table/v2/styles.d.ts +15 -0
- package/types/Table/v2/styles.d.ts.map +1 -0
- package/types/exports/a.d.ts +16 -0
- package/types/exports/a.d.ts.map +1 -0
- package/types/exports/b.d.ts +16 -0
- package/types/exports/b.d.ts.map +1 -0
- package/es/index.js +0 -31
- package/src/index.ts +0 -39
- package/types/Table/Body/index.d.ts.map +0 -1
- package/types/Table/Body/props.d.ts.map +0 -1
- package/types/Table/Body/styles.d.ts.map +0 -1
- package/types/Table/Body/theme.d.ts.map +0 -1
- package/types/Table/Cell/index.d.ts.map +0 -1
- package/types/Table/Cell/props.d.ts.map +0 -1
- package/types/Table/Cell/styles.d.ts.map +0 -1
- package/types/Table/Cell/theme.d.ts.map +0 -1
- package/types/Table/ColHeader/index.d.ts.map +0 -1
- package/types/Table/ColHeader/props.d.ts.map +0 -1
- package/types/Table/ColHeader/styles.d.ts.map +0 -1
- package/types/Table/ColHeader/theme.d.ts.map +0 -1
- package/types/Table/Head/index.d.ts.map +0 -1
- package/types/Table/Head/props.d.ts.map +0 -1
- package/types/Table/Head/styles.d.ts.map +0 -1
- package/types/Table/Head/theme.d.ts.map +0 -1
- package/types/Table/Row/index.d.ts.map +0 -1
- package/types/Table/Row/props.d.ts.map +0 -1
- package/types/Table/Row/styles.d.ts.map +0 -1
- package/types/Table/Row/theme.d.ts.map +0 -1
- package/types/Table/RowHeader/index.d.ts.map +0 -1
- package/types/Table/RowHeader/props.d.ts.map +0 -1
- package/types/Table/RowHeader/styles.d.ts.map +0 -1
- package/types/Table/RowHeader/theme.d.ts.map +0 -1
- package/types/Table/TableContext.d.ts.map +0 -1
- package/types/Table/index.d.ts.map +0 -1
- package/types/Table/props.d.ts.map +0 -1
- package/types/Table/styles.d.ts.map +0 -1
- package/types/Table/theme.d.ts.map +0 -1
- package/types/index.d.ts +0 -16
- package/types/index.d.ts.map +0 -1
- /package/es/Table/{Body → v1/Body}/props.js +0 -0
- /package/es/Table/{Body → v1/Body}/styles.js +0 -0
- /package/es/Table/{Body → v1/Body}/theme.js +0 -0
- /package/es/Table/{Cell → v1/Cell}/props.js +0 -0
- /package/es/Table/{Cell → v1/Cell}/styles.js +0 -0
- /package/es/Table/{Cell → v1/Cell}/theme.js +0 -0
- /package/es/Table/{ColHeader → v1/ColHeader}/props.js +0 -0
- /package/es/Table/{ColHeader → v1/ColHeader}/styles.js +0 -0
- /package/es/Table/{ColHeader → v1/ColHeader}/theme.js +0 -0
- /package/es/Table/{Head → v1/Head}/props.js +0 -0
- /package/es/Table/{Head → v1/Head}/styles.js +0 -0
- /package/es/Table/{Head → v1/Head}/theme.js +0 -0
- /package/es/Table/{Row → v1/Row}/props.js +0 -0
- /package/es/Table/{Row → v1/Row}/styles.js +0 -0
- /package/es/Table/{Row → v1/Row}/theme.js +0 -0
- /package/es/Table/{RowHeader → v1/RowHeader}/props.js +0 -0
- /package/es/Table/{RowHeader → v1/RowHeader}/styles.js +0 -0
- /package/es/Table/{RowHeader → v1/RowHeader}/theme.js +0 -0
- /package/es/Table/{TableContext.js → v1/TableContext.js} +0 -0
- /package/es/Table/{props.js → v1/props.js} +0 -0
- /package/es/Table/{styles.js → v1/styles.js} +0 -0
- /package/es/Table/{theme.js → v1/theme.js} +0 -0
- /package/lib/Table/{Body → v1/Body}/props.js +0 -0
- /package/lib/Table/{Body → v1/Body}/styles.js +0 -0
- /package/lib/Table/{Body → v1/Body}/theme.js +0 -0
- /package/lib/Table/{Cell → v1/Cell}/props.js +0 -0
- /package/lib/Table/{Cell → v1/Cell}/styles.js +0 -0
- /package/lib/Table/{Cell → v1/Cell}/theme.js +0 -0
- /package/lib/Table/{ColHeader → v1/ColHeader}/props.js +0 -0
- /package/lib/Table/{ColHeader → v1/ColHeader}/styles.js +0 -0
- /package/lib/Table/{ColHeader → v1/ColHeader}/theme.js +0 -0
- /package/lib/Table/{Head → v1/Head}/props.js +0 -0
- /package/lib/Table/{Head → v1/Head}/styles.js +0 -0
- /package/lib/Table/{Head → v1/Head}/theme.js +0 -0
- /package/lib/Table/{Row → v1/Row}/props.js +0 -0
- /package/lib/Table/{Row → v1/Row}/styles.js +0 -0
- /package/lib/Table/{Row → v1/Row}/theme.js +0 -0
- /package/lib/Table/{RowHeader → v1/RowHeader}/props.js +0 -0
- /package/lib/Table/{RowHeader → v1/RowHeader}/styles.js +0 -0
- /package/lib/Table/{RowHeader → v1/RowHeader}/theme.js +0 -0
- /package/lib/Table/{TableContext.js → v1/TableContext.js} +0 -0
- /package/lib/Table/{props.js → v1/props.js} +0 -0
- /package/lib/Table/{styles.js → v1/styles.js} +0 -0
- /package/lib/Table/{theme.js → v1/theme.js} +0 -0
- /package/src/Table/{Body → v1/Body}/props.ts +0 -0
- /package/src/Table/{Body → v1/Body}/styles.ts +0 -0
- /package/src/Table/{Body → v1/Body}/theme.ts +0 -0
- /package/src/Table/{Cell → v1/Cell}/props.ts +0 -0
- /package/src/Table/{Cell → v1/Cell}/styles.ts +0 -0
- /package/src/Table/{Cell → v1/Cell}/theme.ts +0 -0
- /package/src/Table/{ColHeader → v1/ColHeader}/props.ts +0 -0
- /package/src/Table/{ColHeader → v1/ColHeader}/styles.ts +0 -0
- /package/src/Table/{ColHeader → v1/ColHeader}/theme.ts +0 -0
- /package/src/Table/{Head → v1/Head}/props.ts +0 -0
- /package/src/Table/{Head → v1/Head}/styles.ts +0 -0
- /package/src/Table/{Head → v1/Head}/theme.ts +0 -0
- /package/src/Table/{Row → v1/Row}/props.ts +0 -0
- /package/src/Table/{Row → v1/Row}/styles.ts +0 -0
- /package/src/Table/{Row → v1/Row}/theme.ts +0 -0
- /package/src/Table/{RowHeader → v1/RowHeader}/props.ts +0 -0
- /package/src/Table/{RowHeader → v1/RowHeader}/styles.ts +0 -0
- /package/src/Table/{RowHeader → v1/RowHeader}/theme.ts +0 -0
- /package/src/Table/{TableContext.ts → v1/TableContext.ts} +0 -0
- /package/src/Table/{props.ts → v1/props.ts} +0 -0
- /package/src/Table/{styles.ts → v1/styles.ts} +0 -0
- /package/src/Table/{theme.ts → v1/theme.ts} +0 -0
- /package/types/Table/{Body → v1/Body}/index.d.ts +0 -0
- /package/types/Table/{Body → v1/Body}/props.d.ts +0 -0
- /package/types/Table/{Body → v1/Body}/styles.d.ts +0 -0
- /package/types/Table/{Body → v1/Body}/theme.d.ts +0 -0
- /package/types/Table/{Cell → v1/Cell}/index.d.ts +0 -0
- /package/types/Table/{Cell → v1/Cell}/props.d.ts +0 -0
- /package/types/Table/{Cell → v1/Cell}/styles.d.ts +0 -0
- /package/types/Table/{Cell → v1/Cell}/theme.d.ts +0 -0
- /package/types/Table/{ColHeader → v1/ColHeader}/index.d.ts +0 -0
- /package/types/Table/{ColHeader → v1/ColHeader}/props.d.ts +0 -0
- /package/types/Table/{ColHeader → v1/ColHeader}/styles.d.ts +0 -0
- /package/types/Table/{ColHeader → v1/ColHeader}/theme.d.ts +0 -0
- /package/types/Table/{Head → v1/Head}/index.d.ts +0 -0
- /package/types/Table/{Head → v1/Head}/props.d.ts +0 -0
- /package/types/Table/{Head → v1/Head}/styles.d.ts +0 -0
- /package/types/Table/{Head → v1/Head}/theme.d.ts +0 -0
- /package/types/Table/{Row → v1/Row}/index.d.ts +0 -0
- /package/types/Table/{Row → v1/Row}/props.d.ts +0 -0
- /package/types/Table/{Row → v1/Row}/styles.d.ts +0 -0
- /package/types/Table/{Row → v1/Row}/theme.d.ts +0 -0
- /package/types/Table/{RowHeader → v1/RowHeader}/index.d.ts +0 -0
- /package/types/Table/{RowHeader → v1/RowHeader}/props.d.ts +0 -0
- /package/types/Table/{RowHeader → v1/RowHeader}/styles.d.ts +0 -0
- /package/types/Table/{RowHeader → v1/RowHeader}/theme.d.ts +0 -0
- /package/types/Table/{TableContext.d.ts → v1/TableContext.d.ts} +0 -0
- /package/types/Table/{index.d.ts → v1/index.d.ts} +0 -0
- /package/types/Table/{props.d.ts → v1/props.d.ts} +0 -0
- /package/types/Table/{styles.d.ts → v1/styles.d.ts} +0 -0
- /package/types/Table/{theme.d.ts → v1/theme.d.ts} +0 -0
|
@@ -0,0 +1,1155 @@
|
|
|
1
|
+
---
|
|
2
|
+
describes: Table
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
### Table layout
|
|
6
|
+
|
|
7
|
+
In stacked layout, column header is rendered in each cell, but not in row header.
|
|
8
|
+
|
|
9
|
+
> If you are using [TruncateText](TruncateText) (or CSS ellipsis) in your Table, set the
|
|
10
|
+
> layout to `fixed` or `stacked`, or the text truncation will not work. To force long strings to break and not
|
|
11
|
+
> exceed the bounds of the table cell, use `fixed` or `stacked`, together with the [Text](Text) component:
|
|
12
|
+
> `<Text wrap="break-word">[long string]</Text>`.
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
---
|
|
16
|
+
type: example
|
|
17
|
+
---
|
|
18
|
+
const Example = () => {
|
|
19
|
+
const [layout, setLayout] = useState('auto')
|
|
20
|
+
const [hover, setHover] = useState(false)
|
|
21
|
+
|
|
22
|
+
const handleChange = (field, value) => {
|
|
23
|
+
if (field === 'layout') {
|
|
24
|
+
setLayout(value)
|
|
25
|
+
} else if (field === 'hover') {
|
|
26
|
+
setHover(value)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const renderOptions = () => (
|
|
31
|
+
<Flex alignItems="start">
|
|
32
|
+
<Flex.Item margin="small">
|
|
33
|
+
<RadioInputGroup
|
|
34
|
+
name="layout"
|
|
35
|
+
description="layout"
|
|
36
|
+
value={layout}
|
|
37
|
+
onChange={(e, value) => handleChange('layout', value)}
|
|
38
|
+
>
|
|
39
|
+
<RadioInput label="auto" value="auto" />
|
|
40
|
+
<RadioInput label="fixed" value="fixed" />
|
|
41
|
+
<RadioInput label="stacked" value="stacked" />
|
|
42
|
+
</RadioInputGroup>
|
|
43
|
+
</Flex.Item>
|
|
44
|
+
<Flex.Item margin="small">
|
|
45
|
+
<Checkbox
|
|
46
|
+
label="hover"
|
|
47
|
+
checked={hover}
|
|
48
|
+
onChange={(e, value) => handleChange('hover', !hover)}
|
|
49
|
+
/>
|
|
50
|
+
</Flex.Item>
|
|
51
|
+
</Flex>
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<div>
|
|
56
|
+
{renderOptions()}
|
|
57
|
+
<Table caption="Top rated movies" layout={layout} hover={hover}>
|
|
58
|
+
<Table.Head>
|
|
59
|
+
<Table.Row>
|
|
60
|
+
<Table.ColHeader id="Rank">Rank</Table.ColHeader>
|
|
61
|
+
<Table.ColHeader id="Title">Title</Table.ColHeader>
|
|
62
|
+
<Table.ColHeader id="Year">Year</Table.ColHeader>
|
|
63
|
+
<Table.ColHeader id="Rating">Rating</Table.ColHeader>
|
|
64
|
+
</Table.Row>
|
|
65
|
+
</Table.Head>
|
|
66
|
+
<Table.Body>
|
|
67
|
+
<Table.Row>
|
|
68
|
+
<Table.RowHeader>1</Table.RowHeader>
|
|
69
|
+
<Table.Cell>The Shawshank Redemption</Table.Cell>
|
|
70
|
+
<Table.Cell>1994</Table.Cell>
|
|
71
|
+
<Table.Cell>9.3</Table.Cell>
|
|
72
|
+
</Table.Row>
|
|
73
|
+
<Table.Row>
|
|
74
|
+
<Table.RowHeader>2</Table.RowHeader>
|
|
75
|
+
<Table.Cell>The Godfather</Table.Cell>
|
|
76
|
+
<Table.Cell>1972</Table.Cell>
|
|
77
|
+
<Table.Cell>9.2</Table.Cell>
|
|
78
|
+
</Table.Row>
|
|
79
|
+
<Table.Row>
|
|
80
|
+
<Table.RowHeader>3</Table.RowHeader>
|
|
81
|
+
<Table.Cell>The Godfather: Part II</Table.Cell>
|
|
82
|
+
<Table.Cell>1974</Table.Cell>
|
|
83
|
+
<Table.Cell>9.0</Table.Cell>
|
|
84
|
+
</Table.Row>
|
|
85
|
+
</Table.Body>
|
|
86
|
+
</Table>
|
|
87
|
+
</div>
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
render(<Example />)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Column width and alignment
|
|
95
|
+
|
|
96
|
+
Each column (`ColHeader`) can have a custom width, and each cell (`ColHeader`, `RowHeader` or `Cell`)
|
|
97
|
+
can be aligned differently.
|
|
98
|
+
|
|
99
|
+
```js
|
|
100
|
+
---
|
|
101
|
+
type: example
|
|
102
|
+
---
|
|
103
|
+
const Example = ({ headers, rows }) => {
|
|
104
|
+
return (
|
|
105
|
+
<Responsive
|
|
106
|
+
query={{
|
|
107
|
+
small: { maxWidth: '40rem' },
|
|
108
|
+
large: { minWidth: '41rem' }
|
|
109
|
+
}}
|
|
110
|
+
props={{
|
|
111
|
+
small: { layout: 'stacked' },
|
|
112
|
+
large: { layout: 'fixed' }
|
|
113
|
+
}}
|
|
114
|
+
>
|
|
115
|
+
{({ layout }) => (
|
|
116
|
+
<div>
|
|
117
|
+
<Table caption="Top rated movies" layout={layout}>
|
|
118
|
+
<Table.Head>
|
|
119
|
+
<Table.Row>
|
|
120
|
+
{(headers || []).map(({ id, text, width, textAlign }) => (
|
|
121
|
+
<Table.ColHeader
|
|
122
|
+
key={id}
|
|
123
|
+
id={id}
|
|
124
|
+
width={width}
|
|
125
|
+
textAlign={textAlign}
|
|
126
|
+
>
|
|
127
|
+
{text}
|
|
128
|
+
</Table.ColHeader>
|
|
129
|
+
))}
|
|
130
|
+
</Table.Row>
|
|
131
|
+
</Table.Head>
|
|
132
|
+
<Table.Body>
|
|
133
|
+
{rows.map((row) => (
|
|
134
|
+
<Table.Row key={row.id}>
|
|
135
|
+
{headers.map(({ id, renderCell, textAlign }) => (
|
|
136
|
+
<Table.Cell
|
|
137
|
+
key={id}
|
|
138
|
+
textAlign={layout === 'stacked' ? 'start' : textAlign}
|
|
139
|
+
>
|
|
140
|
+
{renderCell ? renderCell(row[id], layout) : row[id]}
|
|
141
|
+
</Table.Cell>
|
|
142
|
+
))}
|
|
143
|
+
</Table.Row>
|
|
144
|
+
))}
|
|
145
|
+
</Table.Body>
|
|
146
|
+
</Table>
|
|
147
|
+
</div>
|
|
148
|
+
)}
|
|
149
|
+
</Responsive>
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const renderSummary = (summary, layout) =>
|
|
154
|
+
layout === 'stacked' ? (
|
|
155
|
+
summary
|
|
156
|
+
) : (
|
|
157
|
+
<TruncateText truncate="word" ellipsis="...">
|
|
158
|
+
{summary}
|
|
159
|
+
</TruncateText>
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
render(
|
|
163
|
+
<Example
|
|
164
|
+
headers={[
|
|
165
|
+
{
|
|
166
|
+
id: 'Title',
|
|
167
|
+
text: 'Title',
|
|
168
|
+
width: '25%',
|
|
169
|
+
textAlign: 'start'
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
id: 'Year',
|
|
173
|
+
text: 'Year',
|
|
174
|
+
width: '15%',
|
|
175
|
+
textAlign: 'start'
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
id: 'Summary',
|
|
179
|
+
text: 'Summary',
|
|
180
|
+
width: '40%',
|
|
181
|
+
renderCell: renderSummary,
|
|
182
|
+
textAlign: 'start'
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
id: 'BoxOffice',
|
|
186
|
+
text: 'Box Office',
|
|
187
|
+
width: '20%',
|
|
188
|
+
textAlign: 'end'
|
|
189
|
+
}
|
|
190
|
+
]}
|
|
191
|
+
rows={[
|
|
192
|
+
{
|
|
193
|
+
id: '1',
|
|
194
|
+
Title: 'The Shawshank Redemption',
|
|
195
|
+
Year: 1994,
|
|
196
|
+
Summary:
|
|
197
|
+
'Two imprisoned men bond over a number of years, finding solace and eventual redemption through acts of common decency.',
|
|
198
|
+
BoxOffice: '$28,341,469'
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
id: '2',
|
|
202
|
+
Title: 'The Godfather',
|
|
203
|
+
Year: 1972,
|
|
204
|
+
Summary:
|
|
205
|
+
'The aging patriarch of an organized crime dynasty transfers control of his clandestine empire to his reluctant son.',
|
|
206
|
+
BoxOffice: '$133,698,921'
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
id: '3',
|
|
210
|
+
Title: 'The Godfather: Part II',
|
|
211
|
+
Year: 1974,
|
|
212
|
+
Summary:
|
|
213
|
+
'The early life and career of Vito Corleone in 1920s New York City is portrayed, while his son, Michael, expands and tightens his grip on the family crime syndicate.',
|
|
214
|
+
BoxOffice: '$47,542,841'
|
|
215
|
+
}
|
|
216
|
+
]}
|
|
217
|
+
/>
|
|
218
|
+
)
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### A sortable table using our Responsive component
|
|
222
|
+
|
|
223
|
+
Resize the window to see how column headers transition into a `Select` for sorting table content when the traditional Table Header is no longer clickable. The Table layout itself switches from the horizontal view to the stacked view allowing content to be viewed without horizontal scrolling. See [Responsive](Responsive) for more examples.
|
|
224
|
+
|
|
225
|
+
By default, the options in the `Select` for sorting in stacked layout are generated from the `id` property of the `Table.ColHeader` components. If you want to display custom strings, use the `stackedSortByLabel` property.
|
|
226
|
+
|
|
227
|
+
```js
|
|
228
|
+
---
|
|
229
|
+
type: example
|
|
230
|
+
---
|
|
231
|
+
const SortableTable = ({ caption, headers, rows }) => {
|
|
232
|
+
const initialColWidth = {}
|
|
233
|
+
headers.forEach((header) => {
|
|
234
|
+
initialColWidth[header.id] = 'start'
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
const [sortBy, setSortBy] = useState(headers && headers[0] && headers[0].id)
|
|
238
|
+
const [ascending, setAscending] = useState(true)
|
|
239
|
+
const [colTextAligns, setColTextAligns] = useState(initialColWidth)
|
|
240
|
+
|
|
241
|
+
const sortedRows = useMemo(() => {
|
|
242
|
+
if (!sortBy) return rows
|
|
243
|
+
|
|
244
|
+
const sorted = [...rows].sort((a, b) => {
|
|
245
|
+
return a[sortBy] > b[sortBy] ? 1 : a[sortBy] < b[sortBy] ? -1 : 0
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
return ascending ? sorted : sorted.reverse()
|
|
249
|
+
}, [sortBy, ascending, rows])
|
|
250
|
+
|
|
251
|
+
const handleSort = (event, { id }) => {
|
|
252
|
+
if (id === sortBy) {
|
|
253
|
+
setAscending(!ascending)
|
|
254
|
+
} else {
|
|
255
|
+
setSortBy(id)
|
|
256
|
+
setAscending(true)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const handleColTextAlignChange = (id, value) => {
|
|
261
|
+
setColTextAligns((prevState) => ({
|
|
262
|
+
...prevState,
|
|
263
|
+
[id]: value
|
|
264
|
+
}))
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const renderHeaderRow = (direction) => (
|
|
268
|
+
<Table.Row>
|
|
269
|
+
{(headers || []).map(({ id, text, width }) => (
|
|
270
|
+
<Table.ColHeader
|
|
271
|
+
key={id}
|
|
272
|
+
id={id}
|
|
273
|
+
width={width}
|
|
274
|
+
{...(direction && {
|
|
275
|
+
textAlign: colTextAligns[id],
|
|
276
|
+
stackedSortByLabel: text,
|
|
277
|
+
onRequestSort: handleSort,
|
|
278
|
+
sortDirection: id === sortBy ? direction : 'none'
|
|
279
|
+
})}
|
|
280
|
+
>
|
|
281
|
+
{id === sortBy ? (
|
|
282
|
+
text
|
|
283
|
+
) : (
|
|
284
|
+
<>
|
|
285
|
+
<span aria-hidden="true">{text}</span>
|
|
286
|
+
<ScreenReaderContent>sort by {text}</ScreenReaderContent>
|
|
287
|
+
</>
|
|
288
|
+
)}
|
|
289
|
+
</Table.ColHeader>
|
|
290
|
+
))}
|
|
291
|
+
</Table.Row>
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
const renderOptions = () => (
|
|
295
|
+
<ToggleGroup
|
|
296
|
+
size="small"
|
|
297
|
+
toggleLabel="Set text-align for columns"
|
|
298
|
+
summary="Set text-align for columns"
|
|
299
|
+
background="default"
|
|
300
|
+
>
|
|
301
|
+
<Table caption="Set text-align for columns">
|
|
302
|
+
<Table.Head>{renderHeaderRow()}</Table.Head>
|
|
303
|
+
<Table.Body>
|
|
304
|
+
<Table.Row>
|
|
305
|
+
{Object.entries(colTextAligns).map(([headerId, textAlign]) => (
|
|
306
|
+
<Table.Cell key={headerId}>
|
|
307
|
+
<RadioInputGroup
|
|
308
|
+
description={
|
|
309
|
+
<ScreenReaderContent>
|
|
310
|
+
Set text-align for column: {headerId}
|
|
311
|
+
</ScreenReaderContent>
|
|
312
|
+
}
|
|
313
|
+
name={`columnTextAlign_${headerId}`}
|
|
314
|
+
value={textAlign}
|
|
315
|
+
margin="0 0 small"
|
|
316
|
+
size="small"
|
|
317
|
+
onChange={(e, value) =>
|
|
318
|
+
handleColTextAlignChange(headerId, value)
|
|
319
|
+
}
|
|
320
|
+
>
|
|
321
|
+
<RadioInput label="start" value="start" />
|
|
322
|
+
<RadioInput label="center" value="center" />
|
|
323
|
+
<RadioInput label="end" value="end" />
|
|
324
|
+
</RadioInputGroup>
|
|
325
|
+
</Table.Cell>
|
|
326
|
+
))}
|
|
327
|
+
</Table.Row>
|
|
328
|
+
</Table.Body>
|
|
329
|
+
</Table>
|
|
330
|
+
</ToggleGroup>
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
const direction = ascending ? 'ascending' : 'descending'
|
|
334
|
+
|
|
335
|
+
return (
|
|
336
|
+
<Responsive
|
|
337
|
+
query={{
|
|
338
|
+
small: { maxWidth: '40rem' },
|
|
339
|
+
large: { minWidth: '41rem' }
|
|
340
|
+
}}
|
|
341
|
+
props={{
|
|
342
|
+
small: { layout: 'stacked' },
|
|
343
|
+
large: { layout: 'auto' }
|
|
344
|
+
}}
|
|
345
|
+
>
|
|
346
|
+
{(props) => (
|
|
347
|
+
<div>
|
|
348
|
+
{props.layout !== 'stacked' && (
|
|
349
|
+
<View display="block" margin="0 0 medium">
|
|
350
|
+
{renderOptions()}
|
|
351
|
+
</View>
|
|
352
|
+
)}
|
|
353
|
+
|
|
354
|
+
<Table
|
|
355
|
+
caption={`${caption}: sorted by ${sortBy} in ${direction} order`}
|
|
356
|
+
{...props}
|
|
357
|
+
>
|
|
358
|
+
<Table.Head renderSortLabel="Sort by">
|
|
359
|
+
{renderHeaderRow(direction)}
|
|
360
|
+
</Table.Head>
|
|
361
|
+
<Table.Body>
|
|
362
|
+
{sortedRows.map((row) => (
|
|
363
|
+
<Table.Row key={row.id}>
|
|
364
|
+
{headers.map(({ id, renderCell }) => (
|
|
365
|
+
<Table.Cell key={id} textAlign={colTextAligns[id]}>
|
|
366
|
+
{renderCell ? renderCell(row[id]) : row[id]}
|
|
367
|
+
</Table.Cell>
|
|
368
|
+
))}
|
|
369
|
+
</Table.Row>
|
|
370
|
+
))}
|
|
371
|
+
</Table.Body>
|
|
372
|
+
</Table>
|
|
373
|
+
<Alert
|
|
374
|
+
liveRegion={() => document.getElementById('flash-messages')}
|
|
375
|
+
liveRegionPoliteness="polite"
|
|
376
|
+
screenReaderOnly
|
|
377
|
+
>
|
|
378
|
+
{`Sorted by ${sortBy} in ${direction} order`}
|
|
379
|
+
</Alert>
|
|
380
|
+
</div>
|
|
381
|
+
)}
|
|
382
|
+
</Responsive>
|
|
383
|
+
)
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
render(
|
|
387
|
+
<SortableTable
|
|
388
|
+
caption="Top rated movies"
|
|
389
|
+
headers={[
|
|
390
|
+
{
|
|
391
|
+
id: 'rank',
|
|
392
|
+
text: 'Rank',
|
|
393
|
+
width: '15%'
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
id: 'title',
|
|
397
|
+
text: 'Title',
|
|
398
|
+
width: '55%'
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
id: 'year',
|
|
402
|
+
text: 'Year',
|
|
403
|
+
width: '15%'
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
id: 'rating',
|
|
407
|
+
text: 'Rating',
|
|
408
|
+
width: '15%',
|
|
409
|
+
renderCell: (rating) => rating.toFixed(1)
|
|
410
|
+
}
|
|
411
|
+
]}
|
|
412
|
+
rows={[
|
|
413
|
+
{
|
|
414
|
+
id: '1',
|
|
415
|
+
rank: 1,
|
|
416
|
+
title: 'The Shawshank Redemption',
|
|
417
|
+
year: 1994,
|
|
418
|
+
rating: 9.3
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
id: '2',
|
|
422
|
+
rank: 2,
|
|
423
|
+
title: 'The Godfather',
|
|
424
|
+
year: 1972,
|
|
425
|
+
rating: 9.2
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
id: '3',
|
|
429
|
+
rank: 3,
|
|
430
|
+
title: 'The Godfather: Part II',
|
|
431
|
+
year: 1974,
|
|
432
|
+
rating: 9.0
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
id: '4',
|
|
436
|
+
rank: 4,
|
|
437
|
+
title: 'The Dark Knight',
|
|
438
|
+
year: 2008,
|
|
439
|
+
rating: 9.0
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
id: '5',
|
|
443
|
+
rank: 5,
|
|
444
|
+
title: '12 Angry Men',
|
|
445
|
+
year: 1957,
|
|
446
|
+
rating: 8.9
|
|
447
|
+
}
|
|
448
|
+
]}
|
|
449
|
+
/>
|
|
450
|
+
)
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
### A sortable table with selection and pagination
|
|
454
|
+
|
|
455
|
+
The composition order is important. `SelectableTable` -> `PaginatedTable` -> `SortableTable`, so
|
|
456
|
+
that selection does not re-paginate or re-sort the table, and pagination does not re-sort the table.
|
|
457
|
+
|
|
458
|
+
```js
|
|
459
|
+
---
|
|
460
|
+
type: example
|
|
461
|
+
---
|
|
462
|
+
const SelectableTable = ({
|
|
463
|
+
caption,
|
|
464
|
+
headers,
|
|
465
|
+
rows,
|
|
466
|
+
onSort,
|
|
467
|
+
sortBy,
|
|
468
|
+
ascending,
|
|
469
|
+
rowIds
|
|
470
|
+
}) => {
|
|
471
|
+
const [selected, setSelected] = useState(new Set())
|
|
472
|
+
|
|
473
|
+
const handleSelectAll = (allSelected) => {
|
|
474
|
+
setSelected(allSelected ? new Set() : new Set(rowIds))
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
const handleSelectRow = (rowSelected, rowId) => {
|
|
478
|
+
const copy = new Set(selected)
|
|
479
|
+
if (rowSelected) {
|
|
480
|
+
copy.delete(rowId)
|
|
481
|
+
} else {
|
|
482
|
+
copy.add(rowId)
|
|
483
|
+
}
|
|
484
|
+
setSelected(copy)
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
const allSelected =
|
|
488
|
+
selected.size > 0 && rowIds.every((id) => selected.has(id))
|
|
489
|
+
const someSelected = selected.size > 0 && !allSelected
|
|
490
|
+
const direction = ascending ? 'ascending' : 'descending'
|
|
491
|
+
|
|
492
|
+
return (
|
|
493
|
+
<Responsive
|
|
494
|
+
query={{
|
|
495
|
+
small: { maxWidth: '40rem' },
|
|
496
|
+
large: { minWidth: '41rem' }
|
|
497
|
+
}}
|
|
498
|
+
props={{
|
|
499
|
+
small: { layout: 'stacked' },
|
|
500
|
+
large: { layout: 'auto' }
|
|
501
|
+
}}
|
|
502
|
+
>
|
|
503
|
+
{(props) => (
|
|
504
|
+
<div>
|
|
505
|
+
<View as="div" padding="small" background="primary-inverse">
|
|
506
|
+
{`${selected.size} of ${rowIds.length} selected`}
|
|
507
|
+
</View>
|
|
508
|
+
<Table
|
|
509
|
+
caption={`${caption}: sorted by ${sortBy} in ${direction} order`}
|
|
510
|
+
{...props}
|
|
511
|
+
>
|
|
512
|
+
<Table.Head
|
|
513
|
+
renderSortLabel={
|
|
514
|
+
<ScreenReaderContent>Sort by</ScreenReaderContent>
|
|
515
|
+
}
|
|
516
|
+
>
|
|
517
|
+
<Table.Row>
|
|
518
|
+
<Table.ColHeader id="select" aria-label="Select">
|
|
519
|
+
<Checkbox
|
|
520
|
+
label={
|
|
521
|
+
<ScreenReaderContent>Select all rows</ScreenReaderContent>
|
|
522
|
+
}
|
|
523
|
+
onChange={() => handleSelectAll(allSelected)}
|
|
524
|
+
checked={allSelected}
|
|
525
|
+
indeterminate={someSelected}
|
|
526
|
+
/>
|
|
527
|
+
</Table.ColHeader>
|
|
528
|
+
{(headers || []).map(({ id, text, width }) => (
|
|
529
|
+
<Table.ColHeader
|
|
530
|
+
key={id}
|
|
531
|
+
id={id}
|
|
532
|
+
width={width}
|
|
533
|
+
onRequestSort={onSort}
|
|
534
|
+
sortDirection={id === sortBy ? direction : 'none'}
|
|
535
|
+
>
|
|
536
|
+
{id === sortBy ? (
|
|
537
|
+
text
|
|
538
|
+
) : (
|
|
539
|
+
<>
|
|
540
|
+
<span aria-hidden="true">{text}</span>
|
|
541
|
+
<ScreenReaderContent>
|
|
542
|
+
sort by {text}
|
|
543
|
+
</ScreenReaderContent>
|
|
544
|
+
</>
|
|
545
|
+
)}
|
|
546
|
+
</Table.ColHeader>
|
|
547
|
+
))}
|
|
548
|
+
</Table.Row>
|
|
549
|
+
</Table.Head>
|
|
550
|
+
<Table.Body>
|
|
551
|
+
{(rows || []).map((row) => {
|
|
552
|
+
const rowSelected = selected.has(row.id)
|
|
553
|
+
|
|
554
|
+
return (
|
|
555
|
+
<Table.Row key={row.id}>
|
|
556
|
+
<Table.RowHeader>
|
|
557
|
+
<Checkbox
|
|
558
|
+
label={
|
|
559
|
+
<ScreenReaderContent>
|
|
560
|
+
Select row
|
|
561
|
+
</ScreenReaderContent>
|
|
562
|
+
}
|
|
563
|
+
onChange={() => handleSelectRow(rowSelected, row.id)}
|
|
564
|
+
checked={rowSelected}
|
|
565
|
+
/>
|
|
566
|
+
</Table.RowHeader>
|
|
567
|
+
{(headers || []).map(({ id, renderCell }) => (
|
|
568
|
+
<Table.Cell key={id}>
|
|
569
|
+
{renderCell ? renderCell(row[id]) : row[id]}
|
|
570
|
+
</Table.Cell>
|
|
571
|
+
))}
|
|
572
|
+
</Table.Row>
|
|
573
|
+
)
|
|
574
|
+
})}
|
|
575
|
+
</Table.Body>
|
|
576
|
+
</Table>
|
|
577
|
+
<Alert
|
|
578
|
+
liveRegion={() => document.getElementById('flash-messages')}
|
|
579
|
+
liveRegionPoliteness="polite"
|
|
580
|
+
screenReaderOnly
|
|
581
|
+
>
|
|
582
|
+
{`${selected.size} of ${rowIds.length} selected`}
|
|
583
|
+
</Alert>
|
|
584
|
+
</div>
|
|
585
|
+
)}
|
|
586
|
+
</Responsive>
|
|
587
|
+
)
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
const PaginatedTable = ({
|
|
591
|
+
caption,
|
|
592
|
+
headers,
|
|
593
|
+
rows,
|
|
594
|
+
onSort,
|
|
595
|
+
sortBy,
|
|
596
|
+
ascending,
|
|
597
|
+
perPage
|
|
598
|
+
}) => {
|
|
599
|
+
const [page, setPage] = useState(0)
|
|
600
|
+
|
|
601
|
+
const handleClick = (page) => {
|
|
602
|
+
setPage(page)
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
const handleSort = (event, options) => {
|
|
606
|
+
setPage(0)
|
|
607
|
+
onSort(event, options)
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
const startIndex = page * perPage
|
|
611
|
+
const slicedRows = rows.slice(startIndex, startIndex + perPage)
|
|
612
|
+
const pageCount = perPage && Math.ceil(rows.length / perPage)
|
|
613
|
+
|
|
614
|
+
return (
|
|
615
|
+
<div>
|
|
616
|
+
<SelectableTable
|
|
617
|
+
caption={caption}
|
|
618
|
+
headers={headers}
|
|
619
|
+
rows={slicedRows}
|
|
620
|
+
onSort={handleSort}
|
|
621
|
+
sortBy={sortBy}
|
|
622
|
+
ascending={ascending}
|
|
623
|
+
rowIds={rows.map((row) => row.id)}
|
|
624
|
+
/>
|
|
625
|
+
{pageCount > 1 && (
|
|
626
|
+
<Pagination
|
|
627
|
+
variant="compact"
|
|
628
|
+
labelNext="Next Page"
|
|
629
|
+
labelPrev="Previous Page"
|
|
630
|
+
margin="large"
|
|
631
|
+
>
|
|
632
|
+
{Array.from(Array(pageCount), (item, index) => (
|
|
633
|
+
<Pagination.Page
|
|
634
|
+
key={index}
|
|
635
|
+
onClick={() => handleClick(index)}
|
|
636
|
+
current={index === page}
|
|
637
|
+
>
|
|
638
|
+
{index + 1}
|
|
639
|
+
</Pagination.Page>
|
|
640
|
+
))}
|
|
641
|
+
</Pagination>
|
|
642
|
+
)}
|
|
643
|
+
<Alert
|
|
644
|
+
liveRegion={() => document.getElementById('flash-messages')}
|
|
645
|
+
liveRegionPoliteness="polite"
|
|
646
|
+
screenReaderOnly
|
|
647
|
+
>
|
|
648
|
+
{`Table page ${page + 1} of ${pageCount}`}
|
|
649
|
+
</Alert>
|
|
650
|
+
</div>
|
|
651
|
+
)
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
const SortableTable = ({ caption, headers, rows, perPage }) => {
|
|
655
|
+
const [sortBy, setSortBy] = useState(headers && headers[0] && headers[0].id)
|
|
656
|
+
const [ascending, setAscending] = useState(true)
|
|
657
|
+
|
|
658
|
+
const sortedRows = useMemo(() => {
|
|
659
|
+
if (!sortBy) return rows
|
|
660
|
+
|
|
661
|
+
const sorted = [...rows].sort((a, b) => {
|
|
662
|
+
return a[sortBy] > b[sortBy] ? 1 : a[sortBy] < b[sortBy] ? -1 : 0
|
|
663
|
+
})
|
|
664
|
+
|
|
665
|
+
return ascending ? sorted : sorted.reverse()
|
|
666
|
+
}, [sortBy, ascending, rows])
|
|
667
|
+
|
|
668
|
+
const handleSort = (event, { id }) => {
|
|
669
|
+
if (id === sortBy) {
|
|
670
|
+
setAscending(!ascending)
|
|
671
|
+
} else {
|
|
672
|
+
setSortBy(id)
|
|
673
|
+
setAscending(true)
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
return (
|
|
678
|
+
<div>
|
|
679
|
+
<PaginatedTable
|
|
680
|
+
caption={caption}
|
|
681
|
+
headers={headers}
|
|
682
|
+
rows={sortedRows}
|
|
683
|
+
onSort={handleSort}
|
|
684
|
+
sortBy={sortBy}
|
|
685
|
+
ascending={ascending}
|
|
686
|
+
perPage={perPage}
|
|
687
|
+
/>
|
|
688
|
+
<Alert
|
|
689
|
+
liveRegion={() => document.getElementById('flash-messages')}
|
|
690
|
+
liveRegionPoliteness="polite"
|
|
691
|
+
screenReaderOnly
|
|
692
|
+
>
|
|
693
|
+
{`Sorted by ${sortBy} in ${
|
|
694
|
+
ascending ? 'ascending' : 'descending'
|
|
695
|
+
} order`}
|
|
696
|
+
</Alert>
|
|
697
|
+
</div>
|
|
698
|
+
)
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
const renderRating = (rating) => (
|
|
702
|
+
<Rating label="Rating" valueNow={rating} valueMax={10} iconCount={5} />
|
|
703
|
+
)
|
|
704
|
+
|
|
705
|
+
render(
|
|
706
|
+
<SortableTable
|
|
707
|
+
caption="Top rated movies"
|
|
708
|
+
headers={[
|
|
709
|
+
{
|
|
710
|
+
id: 'Rank',
|
|
711
|
+
text: 'Rank'
|
|
712
|
+
},
|
|
713
|
+
{
|
|
714
|
+
id: 'Title',
|
|
715
|
+
text: 'Title',
|
|
716
|
+
width: '40%'
|
|
717
|
+
},
|
|
718
|
+
{
|
|
719
|
+
id: 'Year',
|
|
720
|
+
text: 'Year'
|
|
721
|
+
},
|
|
722
|
+
{
|
|
723
|
+
id: 'Rating',
|
|
724
|
+
text: 'Rating',
|
|
725
|
+
renderCell: renderRating
|
|
726
|
+
}
|
|
727
|
+
]}
|
|
728
|
+
rows={[
|
|
729
|
+
{
|
|
730
|
+
id: '1',
|
|
731
|
+
Rank: 1,
|
|
732
|
+
Title: 'The Shawshank Redemption',
|
|
733
|
+
Year: 1994,
|
|
734
|
+
Rating: 9.3
|
|
735
|
+
},
|
|
736
|
+
{
|
|
737
|
+
id: '2',
|
|
738
|
+
Rank: 2,
|
|
739
|
+
Title: 'The Godfather',
|
|
740
|
+
Year: 1972,
|
|
741
|
+
Rating: 9.2
|
|
742
|
+
},
|
|
743
|
+
{
|
|
744
|
+
id: '3',
|
|
745
|
+
Rank: 3,
|
|
746
|
+
Title: 'The Godfather: Part II',
|
|
747
|
+
Year: 1974,
|
|
748
|
+
Rating: 9.0
|
|
749
|
+
},
|
|
750
|
+
{
|
|
751
|
+
id: '4',
|
|
752
|
+
Rank: 4,
|
|
753
|
+
Title: 'The Dark Knight',
|
|
754
|
+
Year: 2008,
|
|
755
|
+
Rating: 9.0
|
|
756
|
+
},
|
|
757
|
+
{
|
|
758
|
+
id: '5',
|
|
759
|
+
Rank: 5,
|
|
760
|
+
Title: '12 Angry Men',
|
|
761
|
+
Year: 1957,
|
|
762
|
+
Rating: 8.9
|
|
763
|
+
}
|
|
764
|
+
]}
|
|
765
|
+
perPage={3}
|
|
766
|
+
/>
|
|
767
|
+
)
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
### Using Custom Components as Children
|
|
771
|
+
|
|
772
|
+
In some cases you might want to use custom components in a `Table`, e.g. a HOC for `Table.Row` or `Table.Cell`. This is generally not recommended, but sometimes it could be beneficial for codesplitting or writing cleaner code for larger and more complex Tables.
|
|
773
|
+
|
|
774
|
+
> Do not replace `Table.Body` and `Table.Head` with custom components
|
|
775
|
+
|
|
776
|
+
Wrapper HOCs are simple, just return the original component:
|
|
777
|
+
|
|
778
|
+
```js
|
|
779
|
+
---
|
|
780
|
+
type: example
|
|
781
|
+
---
|
|
782
|
+
const CustomTableCell = ({ children, ...props }) => (
|
|
783
|
+
<Table.Cell {...props}>{children}</Table.Cell>
|
|
784
|
+
)
|
|
785
|
+
|
|
786
|
+
const CustomTableRow = ({ children, ...props }) => (
|
|
787
|
+
<Table.Row {...props}>
|
|
788
|
+
<Table.RowHeader>1</Table.RowHeader>
|
|
789
|
+
<Table.Cell>The Shawshank Redemption</Table.Cell>
|
|
790
|
+
<Table.Cell>1994</Table.Cell>
|
|
791
|
+
<CustomTableCell>9.3</CustomTableCell>
|
|
792
|
+
</Table.Row>
|
|
793
|
+
)
|
|
794
|
+
|
|
795
|
+
const Example = () => {
|
|
796
|
+
const [layout, setLayout] = useState('auto')
|
|
797
|
+
const [hover, setHover] = useState(false)
|
|
798
|
+
|
|
799
|
+
const handleChange = (field, value) => {
|
|
800
|
+
if (field === 'layout') {
|
|
801
|
+
setLayout(value)
|
|
802
|
+
} else if (field === 'hover') {
|
|
803
|
+
setHover(!hover)
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
const renderOptions = () => (
|
|
808
|
+
<Flex alignItems="start">
|
|
809
|
+
<Flex.Item margin="small">
|
|
810
|
+
<RadioInputGroup
|
|
811
|
+
name="layout2"
|
|
812
|
+
description="layout2"
|
|
813
|
+
value={layout}
|
|
814
|
+
onChange={(e, value) => handleChange('layout', value)}
|
|
815
|
+
>
|
|
816
|
+
<RadioInput label="auto" value="auto" />
|
|
817
|
+
<RadioInput label="fixed" value="fixed" />
|
|
818
|
+
<RadioInput label="stacked" value="stacked" />
|
|
819
|
+
</RadioInputGroup>
|
|
820
|
+
</Flex.Item>
|
|
821
|
+
<Flex.Item margin="small">
|
|
822
|
+
<Checkbox
|
|
823
|
+
label="hover"
|
|
824
|
+
checked={hover}
|
|
825
|
+
onChange={(e, value) => handleChange('hover', !hover)}
|
|
826
|
+
/>
|
|
827
|
+
</Flex.Item>
|
|
828
|
+
</Flex>
|
|
829
|
+
)
|
|
830
|
+
|
|
831
|
+
return (
|
|
832
|
+
<div>
|
|
833
|
+
{renderOptions()}
|
|
834
|
+
<Table caption="Top rated movies" layout={layout} hover={hover}>
|
|
835
|
+
<Table.Head>
|
|
836
|
+
<Table.Row>
|
|
837
|
+
<Table.ColHeader id="Rank">Rank</Table.ColHeader>
|
|
838
|
+
<Table.ColHeader id="Title">Title</Table.ColHeader>
|
|
839
|
+
<Table.ColHeader id="Year">Year</Table.ColHeader>
|
|
840
|
+
<Table.ColHeader id="Rating">Rating</Table.ColHeader>
|
|
841
|
+
</Table.Row>
|
|
842
|
+
</Table.Head>
|
|
843
|
+
<Table.Body>
|
|
844
|
+
<CustomTableRow />
|
|
845
|
+
<Table.Row>
|
|
846
|
+
<Table.RowHeader>2</Table.RowHeader>
|
|
847
|
+
<Table.Cell>The Godfather</Table.Cell>
|
|
848
|
+
<Table.Cell>1972</Table.Cell>
|
|
849
|
+
<Table.Cell>9.2</Table.Cell>
|
|
850
|
+
</Table.Row>
|
|
851
|
+
<Table.Row>
|
|
852
|
+
<Table.RowHeader>3</Table.RowHeader>
|
|
853
|
+
<Table.Cell>The Godfather: Part II</Table.Cell>
|
|
854
|
+
<Table.Cell>1974</Table.Cell>
|
|
855
|
+
<Table.Cell>9.0</Table.Cell>
|
|
856
|
+
</Table.Row>
|
|
857
|
+
</Table.Body>
|
|
858
|
+
</Table>
|
|
859
|
+
</div>
|
|
860
|
+
)
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
render(<Example />)
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
#### Fully custom components
|
|
867
|
+
|
|
868
|
+
If you want to use fully custom components you have to pay attention to the following:
|
|
869
|
+
|
|
870
|
+
- Render them as the appropriate HTML Table tags (`tr`, `th`, ...)
|
|
871
|
+
- Read the `hover` prop from [TableContext](TableContext) to customize hover behaviour
|
|
872
|
+
- A11y: Row header cells must have the `scope='row'` HTML attribute
|
|
873
|
+
- A11y: Column header cells must have the `scope='col'` and `aria-sort` (if sortable) HTML attribute
|
|
874
|
+
|
|
875
|
+
Basic fully custom table:
|
|
876
|
+
|
|
877
|
+
```js
|
|
878
|
+
---
|
|
879
|
+
type: example
|
|
880
|
+
---
|
|
881
|
+
const CustomTableCell = ({ children, ...props }) => (
|
|
882
|
+
<td {...props}>{children}</td>
|
|
883
|
+
)
|
|
884
|
+
|
|
885
|
+
const CustomTableRow = ({ children, ...props }) => {
|
|
886
|
+
const { hover } = useContext(TableContext)
|
|
887
|
+
const [isHovered, setIsHovered] = useState(false)
|
|
888
|
+
|
|
889
|
+
const rowStyle =
|
|
890
|
+
hover && isHovered
|
|
891
|
+
? { backgroundColor: 'SeaGreen' }
|
|
892
|
+
: { backgroundColor: 'white' }
|
|
893
|
+
|
|
894
|
+
return (
|
|
895
|
+
<tr
|
|
896
|
+
style={rowStyle}
|
|
897
|
+
onMouseOver={() => setIsHovered(true)}
|
|
898
|
+
onMouseOut={() => setIsHovered(false)}
|
|
899
|
+
>
|
|
900
|
+
{children}
|
|
901
|
+
</tr>
|
|
902
|
+
)
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
const Example = () => {
|
|
906
|
+
const [layout, setLayout] = useState('auto')
|
|
907
|
+
const [hover, setHover] = useState(false)
|
|
908
|
+
|
|
909
|
+
const handleChange = (field, value) => {
|
|
910
|
+
if (field === 'layout') {
|
|
911
|
+
setLayout(value)
|
|
912
|
+
} else if (field === 'hover') {
|
|
913
|
+
setHover(!hover)
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
const renderOptions = () => (
|
|
918
|
+
<Flex alignItems="start">
|
|
919
|
+
<Flex.Item margin="small">
|
|
920
|
+
<RadioInputGroup
|
|
921
|
+
name="Layout"
|
|
922
|
+
description="Layout"
|
|
923
|
+
value={layout}
|
|
924
|
+
onChange={(e, value) => handleChange('layout', value)}
|
|
925
|
+
>
|
|
926
|
+
<RadioInput label="auto" value="auto" />
|
|
927
|
+
<RadioInput label="fixed" value="fixed" />
|
|
928
|
+
</RadioInputGroup>
|
|
929
|
+
</Flex.Item>
|
|
930
|
+
<Flex.Item margin="small">
|
|
931
|
+
<Checkbox
|
|
932
|
+
label="hover"
|
|
933
|
+
checked={hover}
|
|
934
|
+
onChange={(e, value) => handleChange('hover', !hover)}
|
|
935
|
+
/>
|
|
936
|
+
</Flex.Item>
|
|
937
|
+
</Flex>
|
|
938
|
+
)
|
|
939
|
+
|
|
940
|
+
return (
|
|
941
|
+
<div>
|
|
942
|
+
{renderOptions()}
|
|
943
|
+
<Table caption="Top rated movies" layout={layout} hover={hover}>
|
|
944
|
+
<Table.Head>
|
|
945
|
+
<CustomTableRow>
|
|
946
|
+
<CustomTableCell scope="col">Rank</CustomTableCell>
|
|
947
|
+
<CustomTableCell scope="col">Title</CustomTableCell>
|
|
948
|
+
<CustomTableCell scope="col">Year</CustomTableCell>
|
|
949
|
+
<CustomTableCell scope="col">Rating</CustomTableCell>
|
|
950
|
+
</CustomTableRow>
|
|
951
|
+
</Table.Head>
|
|
952
|
+
<Table.Body>
|
|
953
|
+
<CustomTableRow>
|
|
954
|
+
<CustomTableCell scope="row">1</CustomTableCell>
|
|
955
|
+
<CustomTableCell>The Godfather</CustomTableCell>
|
|
956
|
+
<CustomTableCell>1972</CustomTableCell>
|
|
957
|
+
<CustomTableCell>9.2</CustomTableCell>
|
|
958
|
+
</CustomTableRow>
|
|
959
|
+
<CustomTableRow>
|
|
960
|
+
<CustomTableCell scope="row">2</CustomTableCell>
|
|
961
|
+
<CustomTableCell>The Godfather: Part II</CustomTableCell>
|
|
962
|
+
<CustomTableCell>1974</CustomTableCell>
|
|
963
|
+
<CustomTableCell>9.0</CustomTableCell>
|
|
964
|
+
</CustomTableRow>
|
|
965
|
+
</Table.Body>
|
|
966
|
+
</Table>
|
|
967
|
+
</div>
|
|
968
|
+
)
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
render(<Example />)
|
|
972
|
+
```
|
|
973
|
+
|
|
974
|
+
#### Fully custom components with `stacked` layout
|
|
975
|
+
|
|
976
|
+
This layout for small screens displays the table as a list. To accomplish this the headers are passed down to cells (in [TableContext](TableContext)), so they can display what column they are rendering.
|
|
977
|
+
In this layout for accessibility not render HTML table tags, just plain DOM elements (e.g. `div`) and use the appropriate ARIA role to signify that it's actually a `Table` (e.g. [`cell`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/cell_role), [`row`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/row_role), [`rowheader`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/rowheader_role)).
|
|
978
|
+
Also you need the following props on the components:
|
|
979
|
+
|
|
980
|
+
##### Table rows
|
|
981
|
+
|
|
982
|
+
- It should read the `headers` array from [TableContext](TableContext) and pass its nth element to its nth child (if they have such prop).
|
|
983
|
+
|
|
984
|
+
##### The children of the first row in `Table.Head` (`Table.ColHeader` by default)
|
|
985
|
+
|
|
986
|
+
- If the table is sortable the Table needs `id`, `onRequestSort`, `sortDirection` and `stackedSortByLabel` props to render a `Select` to choose how to sort the `Table` (see the props of `Table.ColHeader` for types)
|
|
987
|
+
|
|
988
|
+
##### Table cells
|
|
989
|
+
|
|
990
|
+
- It needs to have an optional `header` prop and should display its value so the user knows which column the cell's value belongs to (you can read whether the table is using `stacked` layout from [TableContext](TableContext).
|
|
991
|
+
|
|
992
|
+
Custom table with `stacked` layout support:
|
|
993
|
+
|
|
994
|
+
```js
|
|
995
|
+
---
|
|
996
|
+
type: example
|
|
997
|
+
---
|
|
998
|
+
const CustomTableCell = ({ children, header }) => {
|
|
999
|
+
const { isStacked } = useContext(TableContext)
|
|
1000
|
+
if (isStacked) {
|
|
1001
|
+
let headerTxt
|
|
1002
|
+
if (typeof header === 'function') {
|
|
1003
|
+
headerTxt = React.createElement(header)
|
|
1004
|
+
} else {
|
|
1005
|
+
headerTxt = header
|
|
1006
|
+
}
|
|
1007
|
+
return (
|
|
1008
|
+
<div role="cell">
|
|
1009
|
+
{headerTxt && headerTxt}
|
|
1010
|
+
{headerTxt && ': '}
|
|
1011
|
+
{children}
|
|
1012
|
+
</div>
|
|
1013
|
+
)
|
|
1014
|
+
}
|
|
1015
|
+
return <td>{children}</td>
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
const CustomTableRow = ({ children }) => {
|
|
1019
|
+
const { hover, headers, isStacked } = useContext(TableContext)
|
|
1020
|
+
const [isHovered, setIsHovered] = useState(false)
|
|
1021
|
+
|
|
1022
|
+
const Tag = isStacked ? 'div' : 'tr'
|
|
1023
|
+
const rowStyle =
|
|
1024
|
+
hover && isHovered
|
|
1025
|
+
? { backgroundColor: 'SeaGreen' }
|
|
1026
|
+
: { backgroundColor: 'white' }
|
|
1027
|
+
|
|
1028
|
+
return (
|
|
1029
|
+
<Tag
|
|
1030
|
+
style={rowStyle}
|
|
1031
|
+
role={isStacked ? 'row' : undefined}
|
|
1032
|
+
onMouseOver={() => setIsHovered(true)}
|
|
1033
|
+
onMouseOut={() => setIsHovered(false)}
|
|
1034
|
+
>
|
|
1035
|
+
{React.Children.toArray(children)
|
|
1036
|
+
.filter(React.isValidElement)
|
|
1037
|
+
.map((child, index) => {
|
|
1038
|
+
return React.cloneElement(child, {
|
|
1039
|
+
key: child.props.name,
|
|
1040
|
+
// used by `CustomTableCell` to render its column title in `stacked` layout
|
|
1041
|
+
header: headers && headers[index]
|
|
1042
|
+
})
|
|
1043
|
+
})}
|
|
1044
|
+
</Tag>
|
|
1045
|
+
)
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
const Example = () => {
|
|
1049
|
+
const [layout, setLayout] = useState('auto')
|
|
1050
|
+
const [hover, setHover] = useState(false)
|
|
1051
|
+
|
|
1052
|
+
const handleChange = (field, value) => {
|
|
1053
|
+
if (field === 'layout') {
|
|
1054
|
+
setLayout(value)
|
|
1055
|
+
} else if (field === 'hover') {
|
|
1056
|
+
setHover(!hover)
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
const renderOptions = () => (
|
|
1061
|
+
<Flex alignItems="start">
|
|
1062
|
+
<Flex.Item margin="small">
|
|
1063
|
+
<RadioInputGroup
|
|
1064
|
+
name="customStackedLayout"
|
|
1065
|
+
description="Layout"
|
|
1066
|
+
value={layout}
|
|
1067
|
+
onChange={(e, value) => handleChange('layout', value)}
|
|
1068
|
+
>
|
|
1069
|
+
<RadioInput label="auto" value="auto" />
|
|
1070
|
+
<RadioInput label="fixed" value="fixed" />
|
|
1071
|
+
<RadioInput label="stacked" value="stacked" />
|
|
1072
|
+
</RadioInputGroup>
|
|
1073
|
+
</Flex.Item>
|
|
1074
|
+
<Flex.Item margin="small">
|
|
1075
|
+
<Checkbox
|
|
1076
|
+
label="hover"
|
|
1077
|
+
checked={hover}
|
|
1078
|
+
onChange={(e, value) => handleChange('hover', !hover)}
|
|
1079
|
+
/>
|
|
1080
|
+
</Flex.Item>
|
|
1081
|
+
</Flex>
|
|
1082
|
+
)
|
|
1083
|
+
|
|
1084
|
+
return (
|
|
1085
|
+
<div>
|
|
1086
|
+
{renderOptions()}
|
|
1087
|
+
<Table caption="Top rated movies" layout={layout} hover={hover}>
|
|
1088
|
+
<Table.Head>
|
|
1089
|
+
<CustomTableRow>
|
|
1090
|
+
<CustomTableCell scope="col">Rank</CustomTableCell>
|
|
1091
|
+
<CustomTableCell scope="col">Title</CustomTableCell>
|
|
1092
|
+
<CustomTableCell scope="col">Year</CustomTableCell>
|
|
1093
|
+
<CustomTableCell scope="col">Rating</CustomTableCell>
|
|
1094
|
+
</CustomTableRow>
|
|
1095
|
+
</Table.Head>
|
|
1096
|
+
<Table.Body>
|
|
1097
|
+
<CustomTableRow>
|
|
1098
|
+
<CustomTableCell scope="row">1</CustomTableCell>
|
|
1099
|
+
<CustomTableCell>The Godfather</CustomTableCell>
|
|
1100
|
+
<CustomTableCell>1972</CustomTableCell>
|
|
1101
|
+
<CustomTableCell>9.2</CustomTableCell>
|
|
1102
|
+
</CustomTableRow>
|
|
1103
|
+
<CustomTableRow>
|
|
1104
|
+
<CustomTableCell scope="row">2</CustomTableCell>
|
|
1105
|
+
<CustomTableCell>The Godfather: Part II</CustomTableCell>
|
|
1106
|
+
<CustomTableCell>1974</CustomTableCell>
|
|
1107
|
+
<CustomTableCell>9.0</CustomTableCell>
|
|
1108
|
+
</CustomTableRow>
|
|
1109
|
+
</Table.Body>
|
|
1110
|
+
</Table>
|
|
1111
|
+
</div>
|
|
1112
|
+
)
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
render(<Example />)
|
|
1116
|
+
```
|
|
1117
|
+
|
|
1118
|
+
### Guidelines
|
|
1119
|
+
|
|
1120
|
+
```js
|
|
1121
|
+
---
|
|
1122
|
+
type: embed
|
|
1123
|
+
---
|
|
1124
|
+
<Guidelines>
|
|
1125
|
+
<Figure recommendation="yes" title="Do">
|
|
1126
|
+
<Figure.Item>Column headers can be sortable</Figure.Item>
|
|
1127
|
+
<Figure.Item>Use the <Link href="#CondensedButton">CondensedButton</Link> and <strong>small</strong> inputs inside cells</Figure.Item>
|
|
1128
|
+
<Figure.Item>Actions must relate to that row only</Figure.Item>
|
|
1129
|
+
<Figure.Item>Use horizontal and vertical alignment that makes sense with the content</Figure.Item>
|
|
1130
|
+
<Figure.Item>Start align US dates and apply i18n</Figure.Item>
|
|
1131
|
+
<Figure.Item>Start align text and alphanumeric</Figure.Item>
|
|
1132
|
+
<Figure.Item>Start align currency</Figure.Item>
|
|
1133
|
+
<Figure.Item>End align quantities and decimals</Figure.Item>
|
|
1134
|
+
<Figure.Item>Table headers should have the same start or end alignment as their column contents</Figure.Item>
|
|
1135
|
+
</Figure>
|
|
1136
|
+
<Figure recommendation="no" title="Don't">
|
|
1137
|
+
<Figure.Item>Center align more than 4 characters/numbers, choose start or end</Figure.Item>
|
|
1138
|
+
<Figure.Item>Use to create a layout</Figure.Item>
|
|
1139
|
+
<Figure.Item>Use zebra stripes</Figure.Item>
|
|
1140
|
+
<Figure.Item>Bottom align ever</Figure.Item>
|
|
1141
|
+
</Figure>
|
|
1142
|
+
</Guidelines>
|
|
1143
|
+
```
|
|
1144
|
+
|
|
1145
|
+
```js
|
|
1146
|
+
---
|
|
1147
|
+
type: embed
|
|
1148
|
+
---
|
|
1149
|
+
<Guidelines>
|
|
1150
|
+
<Figure recommendation="a11y" title="Accessibility">
|
|
1151
|
+
<Figure.Item>In the case of a Table with selection, to prevent screenreaders from announcing the label of the select all checkbox when navigating in the rows, an aria-label should be added to the corresponding Table.Colheader like in our example above.
|
|
1152
|
+
</Figure.Item>
|
|
1153
|
+
</Figure>
|
|
1154
|
+
</Guidelines>
|
|
1155
|
+
```
|