@instructure/ui-table 11.0.1-snapshot-0 → 11.0.1-snapshot-2

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.
@@ -11,414 +11,212 @@ In stacked layout, column header is rendered in each cell, but not in row header
11
11
  > exceed the bounds of the table cell, use `fixed` or `stacked`, together with the [Text](#Text) component:
12
12
  > `<Text wrap="break-word">[long string]</Text>`.
13
13
 
14
- - ```javascript
15
- class Example extends React.Component {
16
- state = {
17
- layout: 'auto',
18
- hover: false
19
- }
20
-
21
- handleChange = (field, value) => {
22
- this.setState({
23
- [field]: value
24
- })
25
- }
26
-
27
- renderOptions() {
28
- const { layout, hover } = this.state
29
-
30
- return (
31
- <Flex alignItems="start">
32
- <Flex.Item margin="small">
33
- <RadioInputGroup
34
- name="layout"
35
- description="layout"
36
- value={layout}
37
- onChange={(e, value) => this.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) => this.handleChange('hover', !hover)}
49
- />
50
- </Flex.Item>
51
- </Flex>
52
- )
53
- }
54
-
55
- render() {
56
- const { layout, hover } = this.state
57
-
58
- return (
59
- <div>
60
- {this.renderOptions()}
61
- <Table caption="Top rated movies" layout={layout} hover={hover}>
62
- <Table.Head>
63
- <Table.Row>
64
- <Table.ColHeader id="Rank">Rank</Table.ColHeader>
65
- <Table.ColHeader id="Title">Title</Table.ColHeader>
66
- <Table.ColHeader id="Year">Year</Table.ColHeader>
67
- <Table.ColHeader id="Rating">Rating</Table.ColHeader>
68
- </Table.Row>
69
- </Table.Head>
70
- <Table.Body>
71
- <Table.Row>
72
- <Table.RowHeader>1</Table.RowHeader>
73
- <Table.Cell>The Shawshank Redemption</Table.Cell>
74
- <Table.Cell>1994</Table.Cell>
75
- <Table.Cell>9.3</Table.Cell>
76
- </Table.Row>
77
- <Table.Row>
78
- <Table.RowHeader>2</Table.RowHeader>
79
- <Table.Cell>The Godfather</Table.Cell>
80
- <Table.Cell>1972</Table.Cell>
81
- <Table.Cell>9.2</Table.Cell>
82
- </Table.Row>
83
- <Table.Row>
84
- <Table.RowHeader>3</Table.RowHeader>
85
- <Table.Cell>The Godfather: Part II</Table.Cell>
86
- <Table.Cell>1974</Table.Cell>
87
- <Table.Cell>9.0</Table.Cell>
88
- </Table.Row>
89
- </Table.Body>
90
- </Table>
91
- </div>
92
- )
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)
93
27
  }
94
28
  }
95
29
 
96
- render(<Example />)
97
- ```
98
-
99
- - ```javascript
100
- const Example = () => {
101
- const [layout, setLayout] = useState('auto')
102
- const [hover, setHover] = useState(false)
103
-
104
- const handleChange = (field, value) => {
105
- if (field === 'layout') {
106
- setLayout(value)
107
- } else if (field === 'hover') {
108
- setHover(value)
109
- }
110
- }
111
-
112
- const renderOptions = () => (
113
- <Flex alignItems="start">
114
- <Flex.Item margin="small">
115
- <RadioInputGroup
116
- name="layout"
117
- description="layout"
118
- value={layout}
119
- onChange={(e, value) => handleChange('layout', value)}
120
- >
121
- <RadioInput label="auto" value="auto" />
122
- <RadioInput label="fixed" value="fixed" />
123
- <RadioInput label="stacked" value="stacked" />
124
- </RadioInputGroup>
125
- </Flex.Item>
126
- <Flex.Item margin="small">
127
- <Checkbox
128
- label="hover"
129
- checked={hover}
130
- onChange={(e, value) => handleChange('hover', !hover)}
131
- />
132
- </Flex.Item>
133
- </Flex>
134
- )
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
+ )
135
53
 
136
- return (
137
- <div>
138
- {renderOptions()}
139
- <Table caption="Top rated movies" layout={layout} hover={hover}>
140
- <Table.Head>
141
- <Table.Row>
142
- <Table.ColHeader id="Rank">Rank</Table.ColHeader>
143
- <Table.ColHeader id="Title">Title</Table.ColHeader>
144
- <Table.ColHeader id="Year">Year</Table.ColHeader>
145
- <Table.ColHeader id="Rating">Rating</Table.ColHeader>
146
- </Table.Row>
147
- </Table.Head>
148
- <Table.Body>
149
- <Table.Row>
150
- <Table.RowHeader>1</Table.RowHeader>
151
- <Table.Cell>The Shawshank Redemption</Table.Cell>
152
- <Table.Cell>1994</Table.Cell>
153
- <Table.Cell>9.3</Table.Cell>
154
- </Table.Row>
155
- <Table.Row>
156
- <Table.RowHeader>2</Table.RowHeader>
157
- <Table.Cell>The Godfather</Table.Cell>
158
- <Table.Cell>1972</Table.Cell>
159
- <Table.Cell>9.2</Table.Cell>
160
- </Table.Row>
161
- <Table.Row>
162
- <Table.RowHeader>3</Table.RowHeader>
163
- <Table.Cell>The Godfather: Part II</Table.Cell>
164
- <Table.Cell>1974</Table.Cell>
165
- <Table.Cell>9.0</Table.Cell>
166
- </Table.Row>
167
- </Table.Body>
168
- </Table>
169
- </div>
170
- )
171
- }
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
+ }
172
90
 
173
- render(<Example />)
174
- ```
91
+ render(<Example />)
92
+ ```
175
93
 
176
94
  ### Column width and alignment
177
95
 
178
96
  Each column (`ColHeader`) can have a custom width, and each cell (`ColHeader`, `RowHeader` or `Cell`)
179
97
  can be aligned differently.
180
98
 
181
- - ```javascript
182
- class Example extends React.Component {
183
- render() {
184
- const { headers, rows } = this.props
185
-
186
- return (
187
- <Responsive
188
- query={{
189
- small: { maxWidth: '40rem' },
190
- large: { minWidth: '41rem' }
191
- }}
192
- props={{
193
- small: { layout: 'stacked' },
194
- large: { layout: 'fixed' }
195
- }}
196
- >
197
- {({ layout }) => (
198
- <div>
199
- <Table caption="Top rated movies" layout={layout}>
200
- <Table.Head>
201
- <Table.Row>
202
- {(headers || []).map(({ id, text, width, textAlign }) => (
203
- <Table.ColHeader
204
- key={id}
205
- id={id}
206
- width={width}
207
- textAlign={textAlign}
208
- >
209
- {text}
210
- </Table.ColHeader>
211
- ))}
212
- </Table.Row>
213
- </Table.Head>
214
- <Table.Body>
215
- {rows.map((row) => (
216
- <Table.Row key={row.id}>
217
- {headers.map(({ id, renderCell, textAlign }) => (
218
- <Table.Cell
219
- key={id}
220
- textAlign={layout === 'stacked' ? 'start' : textAlign}
221
- >
222
- {renderCell ? renderCell(row[id], layout) : row[id]}
223
- </Table.Cell>
224
- ))}
225
- </Table.Row>
226
- ))}
227
- </Table.Body>
228
- </Table>
229
- </div>
230
- )}
231
- </Responsive>
232
- )
233
- }
234
- }
235
-
236
- const renderSummary = (summary, layout) =>
237
- layout === 'stacked' ? (
238
- summary
239
- ) : (
240
- <TruncateText truncate="word" ellipsis="...">
241
- {summary}
242
- </TruncateText>
243
- )
244
-
245
- render(
246
- <Example
247
- headers={[
248
- {
249
- id: 'Title',
250
- text: 'Title',
251
- width: '25%',
252
- textAlign: 'start'
253
- },
254
- {
255
- id: 'Year',
256
- text: 'Year',
257
- width: '15%',
258
- textAlign: 'start'
259
- },
260
- {
261
- id: 'Summary',
262
- text: 'Summary',
263
- width: '40%',
264
- renderCell: renderSummary,
265
- textAlign: 'start'
266
- },
267
- {
268
- id: 'BoxOffice',
269
- text: 'Box Office',
270
- width: '20%',
271
- textAlign: 'end'
272
- }
273
- ]}
274
- rows={[
275
- {
276
- id: '1',
277
- Title: 'The Shawshank Redemption',
278
- Year: 1994,
279
- Summary:
280
- 'Two imprisoned men bond over a number of years, finding solace and eventual redemption through acts of common decency.',
281
- BoxOffice: '$28,341,469'
282
- },
283
- {
284
- id: '2',
285
- Title: 'The Godfather',
286
- Year: 1972,
287
- Summary:
288
- 'The aging patriarch of an organized crime dynasty transfers control of his clandestine empire to his reluctant son.',
289
- BoxOffice: '$133,698,921'
290
- },
291
- {
292
- id: '3',
293
- Title: 'The Godfather: Part II',
294
- Year: 1974,
295
- Summary:
296
- '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.',
297
- BoxOffice: '$47,542,841'
298
- }
299
- ]}
300
- />
301
- )
302
- ```
303
-
304
- - ```javascript
305
- const Example = ({ headers, rows }) => {
306
- return (
307
- <Responsive
308
- query={{
309
- small: { maxWidth: '40rem' },
310
- large: { minWidth: '41rem' }
311
- }}
312
- props={{
313
- small: { layout: 'stacked' },
314
- large: { layout: 'fixed' }
315
- }}
316
- >
317
- {({ layout }) => (
318
- <div>
319
- <Table caption="Top rated movies" layout={layout}>
320
- <Table.Head>
321
- <Table.Row>
322
- {(headers || []).map(({ id, text, width, textAlign }) => (
323
- <Table.ColHeader
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
324
137
  key={id}
325
- id={id}
326
- width={width}
327
- textAlign={textAlign}
138
+ textAlign={layout === 'stacked' ? 'start' : textAlign}
328
139
  >
329
- {text}
330
- </Table.ColHeader>
140
+ {renderCell ? renderCell(row[id], layout) : row[id]}
141
+ </Table.Cell>
331
142
  ))}
332
143
  </Table.Row>
333
- </Table.Head>
334
- <Table.Body>
335
- {rows.map((row) => (
336
- <Table.Row key={row.id}>
337
- {headers.map(({ id, renderCell, textAlign }) => (
338
- <Table.Cell
339
- key={id}
340
- textAlign={layout === 'stacked' ? 'start' : textAlign}
341
- >
342
- {renderCell ? renderCell(row[id], layout) : row[id]}
343
- </Table.Cell>
344
- ))}
345
- </Table.Row>
346
- ))}
347
- </Table.Body>
348
- </Table>
349
- </div>
350
- )}
351
- </Responsive>
352
- )
353
- }
354
-
355
- const renderSummary = (summary, layout) =>
356
- layout === 'stacked' ? (
357
- summary
358
- ) : (
359
- <TruncateText truncate="word" ellipsis="...">
360
- {summary}
361
- </TruncateText>
362
- )
363
-
364
- render(
365
- <Example
366
- headers={[
367
- {
368
- id: 'Title',
369
- text: 'Title',
370
- width: '25%',
371
- textAlign: 'start'
372
- },
373
- {
374
- id: 'Year',
375
- text: 'Year',
376
- width: '15%',
377
- textAlign: 'start'
378
- },
379
- {
380
- id: 'Summary',
381
- text: 'Summary',
382
- width: '40%',
383
- renderCell: renderSummary,
384
- textAlign: 'start'
385
- },
386
- {
387
- id: 'BoxOffice',
388
- text: 'Box Office',
389
- width: '20%',
390
- textAlign: 'end'
391
- }
392
- ]}
393
- rows={[
394
- {
395
- id: '1',
396
- Title: 'The Shawshank Redemption',
397
- Year: 1994,
398
- Summary:
399
- 'Two imprisoned men bond over a number of years, finding solace and eventual redemption through acts of common decency.',
400
- BoxOffice: '$28,341,469'
401
- },
402
- {
403
- id: '2',
404
- Title: 'The Godfather',
405
- Year: 1972,
406
- Summary:
407
- 'The aging patriarch of an organized crime dynasty transfers control of his clandestine empire to his reluctant son.',
408
- BoxOffice: '$133,698,921'
409
- },
410
- {
411
- id: '3',
412
- Title: 'The Godfather: Part II',
413
- Year: 1974,
414
- Summary:
415
- '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.',
416
- BoxOffice: '$47,542,841'
417
- }
418
- ]}
419
- />
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>
420
160
  )
421
- ```
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
+ ```
422
220
 
423
221
  ### A sortable table using our Responsive component
424
222
 
@@ -426,1146 +224,548 @@ Resize the window to see how column headers transition into a `Select` for sorti
426
224
 
427
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.
428
226
 
429
- - ```javascript
430
- class SortableTable extends React.Component {
431
- constructor(props) {
432
- super(props)
433
- const { headers } = props
434
-
435
- const initialColWidth = {}
436
- headers.forEach((header) => {
437
- initialColWidth[header.id] = 'start'
438
- })
439
-
440
- this.state = {
441
- sortBy: headers && headers[0] && headers[0].id,
442
- ascending: true,
443
- colTextAligns: initialColWidth
444
- }
445
- }
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
+ })
446
236
 
447
- handleSort = (event, { id }) => {
448
- const { sortBy, ascending } = this.state
449
-
450
- if (id === sortBy) {
451
- this.setState({
452
- ascending: !ascending
453
- })
454
- } else {
455
- this.setState({
456
- sortBy: id,
457
- ascending: true
458
- })
459
- }
460
- }
237
+ const [sortBy, setSortBy] = useState(headers && headers[0] && headers[0].id)
238
+ const [ascending, setAscending] = useState(true)
239
+ const [colTextAligns, setColTextAligns] = useState(initialColWidth)
461
240
 
462
- handleColTextAlignChange(id, value) {
463
- this.setState((state) => ({
464
- colTextAligns: {
465
- ...state.colTextAligns,
466
- [id]: value
467
- }
468
- }))
469
- }
241
+ const sortedRows = useMemo(() => {
242
+ if (!sortBy) return rows
470
243
 
471
- renderHeaderRow(direction) {
472
- const { headers } = this.props
473
- const { colTextAligns, sortBy } = this.state
474
-
475
- return (
476
- <Table.Row>
477
- {(headers || []).map(({ id, text, width }) => (
478
- <Table.ColHeader
479
- key={id}
480
- id={id}
481
- width={width}
482
- {...(direction && {
483
- textAlign: colTextAligns[id],
484
- stackedSortByLabel: text,
485
- onRequestSort: this.handleSort,
486
- sortDirection: id === sortBy ? direction : 'none'
487
- })}
488
- >
489
- {id === sortBy ? (
490
- text
491
- ) : (
492
- <>
493
- <span aria-hidden="true">{text}</span>
494
- <ScreenReaderContent>sort by {text}</ScreenReaderContent>
495
- </>
496
- )}
497
- </Table.ColHeader>
498
- ))}
499
- </Table.Row>
500
- )
501
- }
244
+ const sorted = [...rows].sort((a, b) => {
245
+ return a[sortBy] > b[sortBy] ? 1 : a[sortBy] < b[sortBy] ? -1 : 0
246
+ })
502
247
 
503
- renderOptions() {
504
- const { headers } = this.props
505
- const { colTextAligns } = this.state
248
+ return ascending ? sorted : sorted.reverse()
249
+ }, [sortBy, ascending, rows])
506
250
 
507
- return (
508
- <ToggleGroup
509
- size="small"
510
- toggleLabel="Set text-align for columns"
511
- summary="Set text-align for columns"
512
- background="default"
513
- >
514
- <Table caption="Set text-align for columns">
515
- <Table.Head>{this.renderHeaderRow()}</Table.Head>
516
- <Table.Body>
517
- <Table.Row>
518
- {Object.entries(colTextAligns).map(([headerId, textAlign]) => {
519
- return (
520
- <Table.Cell key={headerId}>
521
- <RadioInputGroup
522
- description={
523
- <ScreenReaderContent>
524
- Set text-align for column: {headerId}
525
- </ScreenReaderContent>
526
- }
527
- name={`columnTextAlign_${headerId}`}
528
- value={textAlign}
529
- margin="0 0 small"
530
- size="small"
531
- onChange={(e, value) =>
532
- this.handleColTextAlignChange(headerId, value)
533
- }
534
- >
535
- <RadioInput label="start" value="start" />
536
- <RadioInput label="center" value="center" />
537
- <RadioInput label="end" value="end" />
538
- </RadioInputGroup>
539
- </Table.Cell>
540
- )
541
- })}
542
- </Table.Row>
543
- </Table.Body>
544
- </Table>
545
- </ToggleGroup>
546
- )
251
+ const handleSort = (event, { id }) => {
252
+ if (id === sortBy) {
253
+ setAscending(!ascending)
254
+ } else {
255
+ setSortBy(id)
256
+ setAscending(true)
547
257
  }
258
+ }
548
259
 
549
- render() {
550
- const { caption, headers, rows } = this.props
551
- const { sortBy, ascending, colTextAligns } = this.state
552
- const direction = ascending ? 'ascending' : 'descending'
553
- const sortedRows = [...(rows || [])].sort((a, b) => {
554
- if (a[sortBy] < b[sortBy]) {
555
- return -1
556
- }
557
- if (a[sortBy] > b[sortBy]) {
558
- return 1
559
- }
560
- return 0
561
- })
562
-
563
- if (!ascending) {
564
- sortedRows.reverse()
565
- }
566
- return (
567
- <Responsive
568
- query={{
569
- small: { maxWidth: '40rem' },
570
- large: { minWidth: '41rem' }
571
- }}
572
- props={{
573
- small: { layout: 'stacked' },
574
- large: { layout: 'auto' }
575
- }}
576
- >
577
- {(props) => (
578
- <div>
579
- {props.layout !== 'stacked' && (
580
- <View display="block" margin="0 0 medium">
581
- {this.renderOptions()}
582
- </View>
583
- )}
584
-
585
- <Table
586
- caption={`${caption}: sorted by ${sortBy} in ${direction} order`}
587
- {...props}
588
- >
589
- <Table.Head renderSortLabel="Sort by">
590
- {this.renderHeaderRow(direction)}
591
- </Table.Head>
592
- <Table.Body>
593
- {sortedRows.map((row) => (
594
- <Table.Row key={row.id}>
595
- {headers.map(({ id, renderCell }) => (
596
- <Table.Cell key={id} textAlign={colTextAligns[id]}>
597
- {renderCell ? renderCell(row[id]) : row[id]}
598
- </Table.Cell>
599
- ))}
600
- </Table.Row>
601
- ))}
602
- </Table.Body>
603
- </Table>
604
- <Alert
605
- liveRegion={() => document.getElementById('flash-messages')}
606
- liveRegionPoliteness="polite"
607
- screenReaderOnly
608
- >
609
- {`Sorted by ${sortBy} in ${direction} order`}
610
- </Alert>
611
- </div>
612
- )}
613
- </Responsive>
614
- )
615
- }
260
+ const handleColTextAlignChange = (id, value) => {
261
+ setColTextAligns((prevState) => ({
262
+ ...prevState,
263
+ [id]: value
264
+ }))
616
265
  }
617
266
 
618
- render(
619
- <SortableTable
620
- caption="Top rated movies"
621
- headers={[
622
- {
623
- id: 'rank',
624
- text: 'Rank',
625
- width: '15%'
626
- },
627
- {
628
- id: 'title',
629
- text: 'Title',
630
- width: '55%'
631
- },
632
- {
633
- id: 'year',
634
- text: 'Year',
635
- width: '15%'
636
- },
637
- {
638
- id: 'rating',
639
- text: 'Rating',
640
- width: '15%',
641
- renderCell: (rating) => rating.toFixed(1)
642
- }
643
- ]}
644
- rows={[
645
- {
646
- id: '1',
647
- rank: 1,
648
- title: 'The Shawshank Redemption',
649
- year: 1994,
650
- rating: 9.3
651
- },
652
- {
653
- id: '2',
654
- rank: 2,
655
- title: 'The Godfather',
656
- year: 1972,
657
- rating: 9.2
658
- },
659
- {
660
- id: '3',
661
- rank: 3,
662
- title: 'The Godfather: Part II',
663
- year: 1974,
664
- rating: 9.0
665
- },
666
- {
667
- id: '4',
668
- rank: 4,
669
- title: 'The Dark Knight',
670
- year: 2008,
671
- rating: 9.0
672
- },
673
- {
674
- id: '5',
675
- rank: 5,
676
- title: '12 Angry Men',
677
- year: 1957,
678
- rating: 8.9
679
- }
680
- ]}
681
- />
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>
682
292
  )
683
- ```
684
293
 
685
- - ```javascript
686
- const SortableTable = ({ caption, headers, rows }) => {
687
- const initialColWidth = {}
688
- headers.forEach((header) => {
689
- initialColWidth[header.id] = 'start'
690
- })
691
-
692
- const [sortBy, setSortBy] = useState(headers && headers[0] && headers[0].id)
693
- const [ascending, setAscending] = useState(true)
694
- const [colTextAligns, setColTextAligns] = useState(initialColWidth)
695
-
696
- const sortedRows = useMemo(() => {
697
- if (!sortBy) return rows
698
-
699
- const sorted = [...rows].sort((a, b) => {
700
- return a[sortBy] > b[sortBy] ? 1 : a[sortBy] < b[sortBy] ? -1 : 0
701
- })
702
-
703
- return ascending ? sorted : sorted.reverse()
704
- }, [sortBy, ascending, rows])
705
-
706
- const handleSort = (event, { id }) => {
707
- if (id === sortBy) {
708
- setAscending(!ascending)
709
- } else {
710
- setSortBy(id)
711
- setAscending(true)
712
- }
713
- }
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
+ )
714
332
 
715
- const handleColTextAlignChange = (id, value) => {
716
- setColTextAligns((prevState) => ({
717
- ...prevState,
718
- [id]: value
719
- }))
720
- }
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
+ )}
721
353
 
722
- const renderHeaderRow = (direction) => (
723
- <Table.Row>
724
- {(headers || []).map(({ id, text, width }) => (
725
- <Table.ColHeader
726
- key={id}
727
- id={id}
728
- width={width}
729
- {...(direction && {
730
- textAlign: colTextAligns[id],
731
- stackedSortByLabel: text,
732
- onRequestSort: handleSort,
733
- sortDirection: id === sortBy ? direction : 'none'
734
- })}
354
+ <Table
355
+ caption={`${caption}: sorted by ${sortBy} in ${direction} order`}
356
+ {...props}
735
357
  >
736
- {id === sortBy ? (
737
- text
738
- ) : (
739
- <>
740
- <span aria-hidden="true">{text}</span>
741
- <ScreenReaderContent>sort by {text}</ScreenReaderContent>
742
- </>
743
- )}
744
- </Table.ColHeader>
745
- ))}
746
- </Table.Row>
747
- )
748
-
749
- const renderOptions = () => (
750
- <ToggleGroup
751
- size="small"
752
- toggleLabel="Set text-align for columns"
753
- summary="Set text-align for columns"
754
- background="default"
755
- >
756
- <Table caption="Set text-align for columns">
757
- <Table.Head>{renderHeaderRow()}</Table.Head>
758
- <Table.Body>
759
- <Table.Row>
760
- {Object.entries(colTextAligns).map(([headerId, textAlign]) => (
761
- <Table.Cell key={headerId}>
762
- <RadioInputGroup
763
- description={
764
- <ScreenReaderContent>
765
- Set text-align for column: {headerId}
766
- </ScreenReaderContent>
767
- }
768
- name={`columnTextAlign_${headerId}`}
769
- value={textAlign}
770
- margin="0 0 small"
771
- size="small"
772
- onChange={(e, value) =>
773
- handleColTextAlignChange(headerId, value)
774
- }
775
- >
776
- <RadioInput label="start" value="start" />
777
- <RadioInput label="center" value="center" />
778
- <RadioInput label="end" value="end" />
779
- </RadioInputGroup>
780
- </Table.Cell>
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>
781
370
  ))}
782
- </Table.Row>
783
- </Table.Body>
784
- </Table>
785
- </ToggleGroup>
786
- )
787
-
788
- const direction = ascending ? 'ascending' : 'descending'
789
-
790
- return (
791
- <Responsive
792
- query={{
793
- small: { maxWidth: '40rem' },
794
- large: { minWidth: '41rem' }
795
- }}
796
- props={{
797
- small: { layout: 'stacked' },
798
- large: { layout: 'auto' }
799
- }}
800
- >
801
- {(props) => (
802
- <div>
803
- {props.layout !== 'stacked' && (
804
- <View display="block" margin="0 0 medium">
805
- {renderOptions()}
806
- </View>
807
- )}
808
-
809
- <Table
810
- caption={`${caption}: sorted by ${sortBy} in ${direction} order`}
811
- {...props}
812
- >
813
- <Table.Head renderSortLabel="Sort by">
814
- {renderHeaderRow(direction)}
815
- </Table.Head>
816
- <Table.Body>
817
- {sortedRows.map((row) => (
818
- <Table.Row key={row.id}>
819
- {headers.map(({ id, renderCell }) => (
820
- <Table.Cell key={id} textAlign={colTextAligns[id]}>
821
- {renderCell ? renderCell(row[id]) : row[id]}
822
- </Table.Cell>
823
- ))}
824
- </Table.Row>
825
- ))}
826
- </Table.Body>
827
- </Table>
828
- <Alert
829
- liveRegion={() => document.getElementById('flash-messages')}
830
- liveRegionPoliteness="polite"
831
- screenReaderOnly
832
- >
833
- {`Sorted by ${sortBy} in ${direction} order`}
834
- </Alert>
835
- </div>
836
- )}
837
- </Responsive>
838
- )
839
- }
840
-
841
- render(
842
- <SortableTable
843
- caption="Top rated movies"
844
- headers={[
845
- {
846
- id: 'rank',
847
- text: 'Rank',
848
- width: '15%'
849
- },
850
- {
851
- id: 'title',
852
- text: 'Title',
853
- width: '55%'
854
- },
855
- {
856
- id: 'year',
857
- text: 'Year',
858
- width: '15%'
859
- },
860
- {
861
- id: 'rating',
862
- text: 'Rating',
863
- width: '15%',
864
- renderCell: (rating) => rating.toFixed(1)
865
- }
866
- ]}
867
- rows={[
868
- {
869
- id: '1',
870
- rank: 1,
871
- title: 'The Shawshank Redemption',
872
- year: 1994,
873
- rating: 9.3
874
- },
875
- {
876
- id: '2',
877
- rank: 2,
878
- title: 'The Godfather',
879
- year: 1972,
880
- rating: 9.2
881
- },
882
- {
883
- id: '3',
884
- rank: 3,
885
- title: 'The Godfather: Part II',
886
- year: 1974,
887
- rating: 9.0
888
- },
889
- {
890
- id: '4',
891
- rank: 4,
892
- title: 'The Dark Knight',
893
- year: 2008,
894
- rating: 9.0
895
- },
896
- {
897
- id: '5',
898
- rank: 5,
899
- title: '12 Angry Men',
900
- year: 1957,
901
- rating: 8.9
902
- }
903
- ]}
904
- />
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>
905
383
  )
906
- ```
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
+ ```
907
452
 
908
453
  ### A sortable table with selection and pagination
909
454
 
910
455
  The composition order is important. `SelectableTable` -> `PaginatedTable` -> `SortableTable`, so
911
456
  that selection does not re-paginate or re-sort the table, and pagination does not re-sort the table.
912
457
 
913
- - ```javascript
914
- class SelectableTable extends React.Component {
915
- constructor(props) {
916
- super(props)
917
- this.state = {
918
- selected: new Set()
919
- }
920
- }
921
-
922
- handleSelectAll = (allSelected) => {
923
- const { rowIds } = this.props
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
+ }
924
476
 
925
- this.setState({
926
- selected: allSelected ? new Set() : new Set(rowIds)
927
- })
477
+ const handleSelectRow = (rowSelected, rowId) => {
478
+ const copy = new Set(selected)
479
+ if (rowSelected) {
480
+ copy.delete(rowId)
481
+ } else {
482
+ copy.add(rowId)
928
483
  }
484
+ setSelected(copy)
485
+ }
929
486
 
930
- handleSelectRow = (rowSelected, rowId) => {
931
- const { selected } = this.state
932
- const copy = new Set(selected)
933
- if (rowSelected) {
934
- copy.delete(rowId)
935
- } else {
936
- copy.add(rowId)
937
- }
938
-
939
- this.setState({
940
- selected: copy
941
- })
942
- }
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">
519
+ <Checkbox
520
+ label={
521
+ <ScreenReaderContent>Select all</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)
943
553
 
944
- render() {
945
- const { caption, headers, rows, onSort, sortBy, ascending, rowIds } =
946
- this.props
947
- const { selected } = this.state
948
- const allSelected =
949
- selected.size > 0 && rowIds.every((id) => selected.has(id))
950
- const someSelected = selected.size > 0 && !allSelected
951
- const direction = ascending ? 'ascending' : 'descending'
952
-
953
- return (
954
- <Responsive
955
- query={{
956
- small: { maxWidth: '40rem' },
957
- large: { minWidth: '41rem' }
958
- }}
959
- props={{
960
- small: { layout: 'stacked' },
961
- large: { layout: 'auto' }
962
- }}
963
- >
964
- {(props) => (
965
- <div>
966
- <View as="div" padding="small" background="primary-inverse">
967
- {`${selected.size} of ${rowIds.length} selected`}
968
- </View>
969
- <Table
970
- caption={`${caption}: sorted by ${sortBy} in ${direction} order`}
971
- {...props}
972
- >
973
- <Table.Head
974
- renderSortLabel={
975
- <ScreenReaderContent>Sort by</ScreenReaderContent>
976
- }
977
- >
978
- <Table.Row>
979
- <Table.ColHeader id="select">
554
+ return (
555
+ <Table.Row key={row.id}>
556
+ <Table.RowHeader>
980
557
  <Checkbox
981
558
  label={
982
- <ScreenReaderContent>Select all</ScreenReaderContent>
559
+ <ScreenReaderContent>
560
+ Select row
561
+ </ScreenReaderContent>
983
562
  }
984
- onChange={() => this.handleSelectAll(allSelected)}
985
- checked={allSelected}
986
- indeterminate={someSelected}
563
+ onChange={() => handleSelectRow(rowSelected, row.id)}
564
+ checked={rowSelected}
987
565
  />
988
- </Table.ColHeader>
989
- {(headers || []).map(({ id, text, width }) => (
990
- <Table.ColHeader
991
- key={id}
992
- id={id}
993
- width={width}
994
- onRequestSort={onSort}
995
- sortDirection={id === sortBy ? direction : 'none'}
996
- >
997
- {id === sortBy ? (
998
- text
999
- ) : (
1000
- <>
1001
- <span aria-hidden="true">{text}</span>
1002
- <ScreenReaderContent>
1003
- sort by {text}
1004
- </ScreenReaderContent>
1005
- </>
1006
- )}
1007
- </Table.ColHeader>
566
+ </Table.RowHeader>
567
+ {(headers || []).map(({ id, renderCell }) => (
568
+ <Table.Cell key={id}>
569
+ {renderCell ? renderCell(row[id]) : row[id]}
570
+ </Table.Cell>
1008
571
  ))}
1009
572
  </Table.Row>
1010
- </Table.Head>
1011
- <Table.Body>
1012
- {(rows || []).map((row) => {
1013
- const rowSelected = selected.has(row.id)
1014
-
1015
- return (
1016
- <Table.Row key={row.id}>
1017
- <Table.RowHeader>
1018
- <Checkbox
1019
- label={
1020
- <ScreenReaderContent>
1021
- Select row
1022
- </ScreenReaderContent>
1023
- }
1024
- onChange={() =>
1025
- this.handleSelectRow(rowSelected, row.id)
1026
- }
1027
- checked={rowSelected}
1028
- />
1029
- </Table.RowHeader>
1030
- {(headers || []).map(({ id, renderCell }) => (
1031
- <Table.Cell key={id}>
1032
- {renderCell ? renderCell(row[id]) : row[id]}
1033
- </Table.Cell>
1034
- ))}
1035
- </Table.Row>
1036
- )
1037
- })}
1038
- </Table.Body>
1039
- </Table>
1040
- <Alert
1041
- liveRegion={() => document.getElementById('flash-messages')}
1042
- liveRegionPoliteness="polite"
1043
- screenReaderOnly
1044
- >
1045
- {`${selected.size} of ${rowIds.length} selected`}
1046
- </Alert>
1047
- </div>
1048
- )}
1049
- </Responsive>
1050
- )
1051
- }
1052
- }
1053
-
1054
- class PaginatedTable extends React.Component {
1055
- constructor(props) {
1056
- super(props)
1057
- this.state = {
1058
- page: 0
1059
- }
1060
- }
1061
-
1062
- handleClick = (page) => {
1063
- this.setState({
1064
- page
1065
- })
1066
- }
1067
-
1068
- handleSort = (event, options) => {
1069
- const { onSort } = this.props
1070
-
1071
- this.setState({
1072
- page: 0
1073
- })
1074
- onSort(event, options)
1075
- }
1076
-
1077
- render() {
1078
- const { caption, headers, rows, sortBy, ascending, perPage } = this.props
1079
- const { page } = this.state
1080
- const startIndex = page * perPage
1081
- const slicedRows = rows.slice(startIndex, startIndex + perPage)
1082
- const pageCount = perPage && Math.ceil(rows.length / perPage)
1083
-
1084
- return (
1085
- <div>
1086
- <SelectableTable
1087
- caption={caption}
1088
- headers={headers}
1089
- rows={slicedRows}
1090
- onSort={this.handleSort}
1091
- sortBy={sortBy}
1092
- ascending={ascending}
1093
- rowIds={rows.map((row) => row.id)}
1094
- />
1095
- {pageCount > 1 && (
1096
- <Pagination
1097
- variant="compact"
1098
- labelNext="Next Page"
1099
- labelPrev="Previous Page"
1100
- margin="large"
1101
- >
1102
- {Array.from(Array(pageCount), (item, index) => (
1103
- <Pagination.Page
1104
- key={index}
1105
- onClick={() => this.handleClick(index)}
1106
- current={index === page}
1107
- >
1108
- {index + 1}
1109
- </Pagination.Page>
1110
- ))}
1111
- </Pagination>
1112
- )}
1113
- <Alert
1114
- liveRegion={() => document.getElementById('flash-messages')}
1115
- liveRegionPoliteness="polite"
1116
- screenReaderOnly
1117
- >
1118
- {`Table page ${page + 1} of ${pageCount}`}
1119
- </Alert>
1120
- </div>
1121
- )
1122
- }
1123
- }
1124
-
1125
- class SortableTable extends React.Component {
1126
- constructor(props) {
1127
- super(props)
1128
- const { headers } = props
1129
-
1130
- this.state = {
1131
- sortBy: headers && headers[0] && headers[0].id,
1132
- ascending: true
1133
- }
1134
- }
1135
-
1136
- handleSort = (event, { id }) => {
1137
- const { sortBy, ascending } = this.state
1138
-
1139
- if (id === sortBy) {
1140
- this.setState({
1141
- ascending: !ascending
1142
- })
1143
- } else {
1144
- this.setState({
1145
- sortBy: id,
1146
- ascending: true
1147
- })
1148
- }
1149
- }
1150
-
1151
- render() {
1152
- const { caption, headers, rows, perPage } = this.props
1153
- const { sortBy, ascending } = this.state
1154
- const sortedRows = [...rows].sort((a, b) => {
1155
- if (a[sortBy] < b[sortBy]) {
1156
- return -1
1157
- }
1158
- if (a[sortBy] > b[sortBy]) {
1159
- return 1
1160
- }
1161
- return 0
1162
- })
1163
-
1164
- if (!ascending) {
1165
- sortedRows.reverse()
1166
- }
1167
- return (
1168
- <div>
1169
- <PaginatedTable
1170
- caption={caption}
1171
- headers={headers}
1172
- rows={sortedRows}
1173
- onSort={this.handleSort}
1174
- sortBy={sortBy}
1175
- ascending={ascending}
1176
- perPage={perPage}
1177
- />
573
+ )
574
+ })}
575
+ </Table.Body>
576
+ </Table>
1178
577
  <Alert
1179
578
  liveRegion={() => document.getElementById('flash-messages')}
1180
579
  liveRegionPoliteness="polite"
1181
580
  screenReaderOnly
1182
581
  >
1183
- {`Sorted by ${sortBy} in ${
1184
- ascending ? 'ascending' : 'descending'
1185
- } order`}
582
+ {`${selected.size} of ${rowIds.length} selected`}
1186
583
  </Alert>
1187
584
  </div>
1188
- )
1189
- }
1190
- }
1191
-
1192
- const renderRating = (rating) => (
1193
- <Rating label="Rating" valueNow={rating} valueMax={10} iconCount={5} />
585
+ )}
586
+ </Responsive>
1194
587
  )
1195
-
1196
- render(
1197
- <SortableTable
1198
- caption="Top rated movies"
1199
- headers={[
1200
- {
1201
- id: 'Rank',
1202
- text: 'Rank'
1203
- },
1204
- {
1205
- id: 'Title',
1206
- text: 'Title',
1207
- width: '40%'
1208
- },
1209
- {
1210
- id: 'Year',
1211
- text: 'Year'
1212
- },
1213
- {
1214
- id: 'Rating',
1215
- text: 'Rating',
1216
- renderCell: renderRating
1217
- }
1218
- ]}
1219
- rows={[
1220
- {
1221
- id: '1',
1222
- Rank: 1,
1223
- Title: 'The Shawshank Redemption',
1224
- Year: 1994,
1225
- Rating: 9.3
1226
- },
1227
- {
1228
- id: '2',
1229
- Rank: 2,
1230
- Title: 'The Godfather',
1231
- Year: 1972,
1232
- Rating: 9.2
1233
- },
1234
- {
1235
- id: '3',
1236
- Rank: 3,
1237
- Title: 'The Godfather: Part II',
1238
- Year: 1974,
1239
- Rating: 9.0
1240
- },
1241
- {
1242
- id: '4',
1243
- Rank: 4,
1244
- Title: 'The Dark Knight',
1245
- Year: 2008,
1246
- Rating: 9.0
1247
- },
1248
- {
1249
- id: '5',
1250
- Rank: 5,
1251
- Title: '12 Angry Men',
1252
- Year: 1957,
1253
- Rating: 8.9
1254
- }
1255
- ]}
1256
- perPage={3}
1257
- />
1258
- )
1259
- ```
1260
-
1261
- - ```javascript
1262
- const SelectableTable = ({
1263
- caption,
1264
- headers,
1265
- rows,
1266
- onSort,
1267
- sortBy,
1268
- ascending,
1269
- rowIds
1270
- }) => {
1271
- const [selected, setSelected] = useState(new Set())
1272
-
1273
- const handleSelectAll = (allSelected) => {
1274
- setSelected(allSelected ? new Set() : new Set(rowIds))
1275
- }
1276
-
1277
- const handleSelectRow = (rowSelected, rowId) => {
1278
- const copy = new Set(selected)
1279
- if (rowSelected) {
1280
- copy.delete(rowId)
1281
- } else {
1282
- copy.add(rowId)
1283
- }
1284
- setSelected(copy)
1285
- }
1286
-
1287
- const allSelected =
1288
- selected.size > 0 && rowIds.every((id) => selected.has(id))
1289
- const someSelected = selected.size > 0 && !allSelected
1290
- const direction = ascending ? 'ascending' : 'descending'
1291
-
1292
- return (
1293
- <Responsive
1294
- query={{
1295
- small: { maxWidth: '40rem' },
1296
- large: { minWidth: '41rem' }
1297
- }}
1298
- props={{
1299
- small: { layout: 'stacked' },
1300
- large: { layout: 'auto' }
1301
- }}
1302
- >
1303
- {(props) => (
1304
- <div>
1305
- <View as="div" padding="small" background="primary-inverse">
1306
- {`${selected.size} of ${rowIds.length} selected`}
1307
- </View>
1308
- <Table
1309
- caption={`${caption}: sorted by ${sortBy} in ${direction} order`}
1310
- {...props}
1311
- >
1312
- <Table.Head
1313
- renderSortLabel={
1314
- <ScreenReaderContent>Sort by</ScreenReaderContent>
1315
- }
1316
- >
1317
- <Table.Row>
1318
- <Table.ColHeader id="select">
1319
- <Checkbox
1320
- label={
1321
- <ScreenReaderContent>Select all</ScreenReaderContent>
1322
- }
1323
- onChange={() => handleSelectAll(allSelected)}
1324
- checked={allSelected}
1325
- indeterminate={someSelected}
1326
- />
1327
- </Table.ColHeader>
1328
- {(headers || []).map(({ id, text, width }) => (
1329
- <Table.ColHeader
1330
- key={id}
1331
- id={id}
1332
- width={width}
1333
- onRequestSort={onSort}
1334
- sortDirection={id === sortBy ? direction : 'none'}
1335
- >
1336
- {id === sortBy ? (
1337
- text
1338
- ) : (
1339
- <>
1340
- <span aria-hidden="true">{text}</span>
1341
- <ScreenReaderContent>
1342
- sort by {text}
1343
- </ScreenReaderContent>
1344
- </>
1345
- )}
1346
- </Table.ColHeader>
1347
- ))}
1348
- </Table.Row>
1349
- </Table.Head>
1350
- <Table.Body>
1351
- {(rows || []).map((row) => {
1352
- const rowSelected = selected.has(row.id)
1353
-
1354
- return (
1355
- <Table.Row key={row.id}>
1356
- <Table.RowHeader>
1357
- <Checkbox
1358
- label={
1359
- <ScreenReaderContent>
1360
- Select row
1361
- </ScreenReaderContent>
1362
- }
1363
- onChange={() => handleSelectRow(rowSelected, row.id)}
1364
- checked={rowSelected}
1365
- />
1366
- </Table.RowHeader>
1367
- {(headers || []).map(({ id, renderCell }) => (
1368
- <Table.Cell key={id}>
1369
- {renderCell ? renderCell(row[id]) : row[id]}
1370
- </Table.Cell>
1371
- ))}
1372
- </Table.Row>
1373
- )
1374
- })}
1375
- </Table.Body>
1376
- </Table>
1377
- <Alert
1378
- liveRegion={() => document.getElementById('flash-messages')}
1379
- liveRegionPoliteness="polite"
1380
- screenReaderOnly
1381
- >
1382
- {`${selected.size} of ${rowIds.length} selected`}
1383
- </Alert>
1384
- </div>
1385
- )}
1386
- </Responsive>
1387
- )
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)
1388
603
  }
1389
604
 
1390
- const PaginatedTable = ({
1391
- caption,
1392
- headers,
1393
- rows,
1394
- onSort,
1395
- sortBy,
1396
- ascending,
1397
- perPage
1398
- }) => {
1399
- const [page, setPage] = useState(0)
1400
-
1401
- const handleClick = (page) => {
1402
- setPage(page)
1403
- }
1404
-
1405
- const handleSort = (event, options) => {
1406
- setPage(0)
1407
- onSort(event, options)
1408
- }
1409
-
1410
- const startIndex = page * perPage
1411
- const slicedRows = rows.slice(startIndex, startIndex + perPage)
1412
- const pageCount = perPage && Math.ceil(rows.length / perPage)
605
+ const handleSort = (event, options) => {
606
+ setPage(0)
607
+ onSort(event, options)
608
+ }
1413
609
 
1414
- return (
1415
- <div>
1416
- <SelectableTable
1417
- caption={caption}
1418
- headers={headers}
1419
- rows={slicedRows}
1420
- onSort={handleSort}
1421
- sortBy={sortBy}
1422
- ascending={ascending}
1423
- rowIds={rows.map((row) => row.id)}
1424
- />
1425
- {pageCount > 1 && (
1426
- <Pagination
1427
- variant="compact"
1428
- labelNext="Next Page"
1429
- labelPrev="Previous Page"
1430
- margin="large"
1431
- >
1432
- {Array.from(Array(pageCount), (item, index) => (
1433
- <Pagination.Page
1434
- key={index}
1435
- onClick={() => handleClick(index)}
1436
- current={index === page}
1437
- >
1438
- {index + 1}
1439
- </Pagination.Page>
1440
- ))}
1441
- </Pagination>
1442
- )}
1443
- <Alert
1444
- liveRegion={() => document.getElementById('flash-messages')}
1445
- liveRegionPoliteness="polite"
1446
- screenReaderOnly
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"
1447
631
  >
1448
- {`Table page ${page + 1} of ${pageCount}`}
1449
- </Alert>
1450
- </div>
1451
- )
1452
- }
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
+ }
1453
653
 
1454
- const SortableTable = ({ caption, headers, rows, perPage }) => {
1455
- const [sortBy, setSortBy] = useState(headers && headers[0] && headers[0].id)
1456
- const [ascending, setAscending] = useState(true)
654
+ const SortableTable = ({ caption, headers, rows, perPage }) => {
655
+ const [sortBy, setSortBy] = useState(headers && headers[0] && headers[0].id)
656
+ const [ascending, setAscending] = useState(true)
1457
657
 
1458
- const sortedRows = useMemo(() => {
1459
- if (!sortBy) return rows
658
+ const sortedRows = useMemo(() => {
659
+ if (!sortBy) return rows
1460
660
 
1461
- const sorted = [...rows].sort((a, b) => {
1462
- return a[sortBy] > b[sortBy] ? 1 : a[sortBy] < b[sortBy] ? -1 : 0
1463
- })
661
+ const sorted = [...rows].sort((a, b) => {
662
+ return a[sortBy] > b[sortBy] ? 1 : a[sortBy] < b[sortBy] ? -1 : 0
663
+ })
1464
664
 
1465
- return ascending ? sorted : sorted.reverse()
1466
- }, [sortBy, ascending, rows])
665
+ return ascending ? sorted : sorted.reverse()
666
+ }, [sortBy, ascending, rows])
1467
667
 
1468
- const handleSort = (event, { id }) => {
1469
- if (id === sortBy) {
1470
- setAscending(!ascending)
1471
- } else {
1472
- setSortBy(id)
1473
- setAscending(true)
1474
- }
668
+ const handleSort = (event, { id }) => {
669
+ if (id === sortBy) {
670
+ setAscending(!ascending)
671
+ } else {
672
+ setSortBy(id)
673
+ setAscending(true)
1475
674
  }
1476
-
1477
- return (
1478
- <div>
1479
- <PaginatedTable
1480
- caption={caption}
1481
- headers={headers}
1482
- rows={sortedRows}
1483
- onSort={handleSort}
1484
- sortBy={sortBy}
1485
- ascending={ascending}
1486
- perPage={perPage}
1487
- />
1488
- <Alert
1489
- liveRegion={() => document.getElementById('flash-messages')}
1490
- liveRegionPoliteness="polite"
1491
- screenReaderOnly
1492
- >
1493
- {`Sorted by ${sortBy} in ${
1494
- ascending ? 'ascending' : 'descending'
1495
- } order`}
1496
- </Alert>
1497
- </div>
1498
- )
1499
675
  }
1500
676
 
1501
- const renderRating = (rating) => (
1502
- <Rating label="Rating" valueNow={rating} valueMax={10} iconCount={5} />
1503
- )
1504
-
1505
- render(
1506
- <SortableTable
1507
- caption="Top rated movies"
1508
- headers={[
1509
- {
1510
- id: 'Rank',
1511
- text: 'Rank'
1512
- },
1513
- {
1514
- id: 'Title',
1515
- text: 'Title',
1516
- width: '40%'
1517
- },
1518
- {
1519
- id: 'Year',
1520
- text: 'Year'
1521
- },
1522
- {
1523
- id: 'Rating',
1524
- text: 'Rating',
1525
- renderCell: renderRating
1526
- }
1527
- ]}
1528
- rows={[
1529
- {
1530
- id: '1',
1531
- Rank: 1,
1532
- Title: 'The Shawshank Redemption',
1533
- Year: 1994,
1534
- Rating: 9.3
1535
- },
1536
- {
1537
- id: '2',
1538
- Rank: 2,
1539
- Title: 'The Godfather',
1540
- Year: 1972,
1541
- Rating: 9.2
1542
- },
1543
- {
1544
- id: '3',
1545
- Rank: 3,
1546
- Title: 'The Godfather: Part II',
1547
- Year: 1974,
1548
- Rating: 9.0
1549
- },
1550
- {
1551
- id: '4',
1552
- Rank: 4,
1553
- Title: 'The Dark Knight',
1554
- Year: 2008,
1555
- Rating: 9.0
1556
- },
1557
- {
1558
- id: '5',
1559
- Rank: 5,
1560
- Title: '12 Angry Men',
1561
- Year: 1957,
1562
- Rating: 8.9
1563
- }
1564
- ]}
1565
- perPage={3}
1566
- />
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>
1567
698
  )
1568
- ```
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
+ ```
1569
769
 
1570
770
  ### Using Custom Components as Children
1571
771
 
@@ -1575,188 +775,93 @@ In some cases you might want to use custom components in a `Table`, e.g. a HOC f
1575
775
 
1576
776
  Wrapper HOCs are simple, just return the original component:
1577
777
 
1578
- - ```javascript
1579
- class CustomTableCell extends React.Component {
1580
- render() {
1581
- return <Table.Cell {...this.props}>{this.props.children}</Table.Cell>
1582
- }
1583
- }
1584
-
1585
- class CustomTableRow extends React.Component {
1586
- render() {
1587
- return (
1588
- <Table.Row {...this.props}>
1589
- <Table.RowHeader>1</Table.RowHeader>
1590
- <Table.Cell>The Shawshank Redemption</Table.Cell>
1591
- <Table.Cell>1994</Table.Cell>
1592
- <CustomTableCell>9.3</CustomTableCell>
1593
- </Table.Row>
1594
- )
1595
- }
1596
- }
1597
-
1598
- class Example extends React.Component {
1599
- state = {
1600
- layout: 'auto',
1601
- hover: false
1602
- }
1603
-
1604
- handleChange = (field, value) => {
1605
- this.setState({
1606
- [field]: value
1607
- })
1608
- }
1609
-
1610
- renderOptions() {
1611
- const { layout, hover } = this.state
1612
-
1613
- return (
1614
- <Flex alignItems="start">
1615
- <Flex.Item margin="small">
1616
- <RadioInputGroup
1617
- name="layout2"
1618
- description="layout2"
1619
- value={layout}
1620
- onChange={(e, value) => this.handleChange('layout', value)}
1621
- >
1622
- <RadioInput label="auto" value="auto" />
1623
- <RadioInput label="fixed" value="fixed" />
1624
- <RadioInput label="stacked" value="stacked" />
1625
- </RadioInputGroup>
1626
- </Flex.Item>
1627
- <Flex.Item margin="small">
1628
- <Checkbox
1629
- label="hover"
1630
- checked={hover}
1631
- onChange={(e, value) => this.handleChange('hover', !hover)}
1632
- />
1633
- </Flex.Item>
1634
- </Flex>
1635
- )
1636
- }
1637
-
1638
- render() {
1639
- const { layout, hover } = this.state
1640
- return (
1641
- <div>
1642
- {this.renderOptions()}
1643
- <Table caption="Top rated movies" layout={layout} hover={hover}>
1644
- <Table.Head>
1645
- <Table.Row>
1646
- <Table.ColHeader id="Rank">Rank</Table.ColHeader>
1647
- <Table.ColHeader id="Title">Title</Table.ColHeader>
1648
- <Table.ColHeader id="Year">Year</Table.ColHeader>
1649
- <Table.ColHeader id="Rating">Rating</Table.ColHeader>
1650
- </Table.Row>
1651
- </Table.Head>
1652
- <Table.Body>
1653
- <CustomTableRow />
1654
- <Table.Row>
1655
- <Table.RowHeader>2</Table.RowHeader>
1656
- <Table.Cell>The Godfather</Table.Cell>
1657
- <Table.Cell>1972</Table.Cell>
1658
- <Table.Cell>9.2</Table.Cell>
1659
- </Table.Row>
1660
- <Table.Row>
1661
- <Table.RowHeader>3</Table.RowHeader>
1662
- <Table.Cell>The Godfather: Part II</Table.Cell>
1663
- <Table.Cell>1974</Table.Cell>
1664
- <Table.Cell>9.0</Table.Cell>
1665
- </Table.Row>
1666
- </Table.Body>
1667
- </Table>
1668
- </div>
1669
- )
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)
1670
804
  }
1671
805
  }
1672
806
 
1673
- render(<Example />)
1674
- ```
1675
-
1676
- - ```javascript
1677
- const CustomTableCell = ({ children, ...props }) => (
1678
- <Table.Cell {...props}>{children}</Table.Cell>
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>
1679
829
  )
1680
830
 
1681
- const CustomTableRow = ({ children, ...props }) => (
1682
- <Table.Row {...props}>
1683
- <Table.RowHeader>1</Table.RowHeader>
1684
- <Table.Cell>The Shawshank Redemption</Table.Cell>
1685
- <Table.Cell>1994</Table.Cell>
1686
- <CustomTableCell>9.3</CustomTableCell>
1687
- </Table.Row>
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>
1688
860
  )
861
+ }
1689
862
 
1690
- const Example = () => {
1691
- const [layout, setLayout] = useState('auto')
1692
- const [hover, setHover] = useState(false)
1693
-
1694
- const handleChange = (field, value) => {
1695
- if (field === 'layout') {
1696
- setLayout(value)
1697
- } else if (field === 'hover') {
1698
- setHover(!hover)
1699
- }
1700
- }
1701
-
1702
- const renderOptions = () => (
1703
- <Flex alignItems="start">
1704
- <Flex.Item margin="small">
1705
- <RadioInputGroup
1706
- name="layout2"
1707
- description="layout2"
1708
- value={layout}
1709
- onChange={(e, value) => handleChange('layout', value)}
1710
- >
1711
- <RadioInput label="auto" value="auto" />
1712
- <RadioInput label="fixed" value="fixed" />
1713
- <RadioInput label="stacked" value="stacked" />
1714
- </RadioInputGroup>
1715
- </Flex.Item>
1716
- <Flex.Item margin="small">
1717
- <Checkbox
1718
- label="hover"
1719
- checked={hover}
1720
- onChange={(e, value) => handleChange('hover', !hover)}
1721
- />
1722
- </Flex.Item>
1723
- </Flex>
1724
- )
1725
-
1726
- return (
1727
- <div>
1728
- {renderOptions()}
1729
- <Table caption="Top rated movies" layout={layout} hover={hover}>
1730
- <Table.Head>
1731
- <Table.Row>
1732
- <Table.ColHeader id="Rank">Rank</Table.ColHeader>
1733
- <Table.ColHeader id="Title">Title</Table.ColHeader>
1734
- <Table.ColHeader id="Year">Year</Table.ColHeader>
1735
- <Table.ColHeader id="Rating">Rating</Table.ColHeader>
1736
- </Table.Row>
1737
- </Table.Head>
1738
- <Table.Body>
1739
- <CustomTableRow />
1740
- <Table.Row>
1741
- <Table.RowHeader>2</Table.RowHeader>
1742
- <Table.Cell>The Godfather</Table.Cell>
1743
- <Table.Cell>1972</Table.Cell>
1744
- <Table.Cell>9.2</Table.Cell>
1745
- </Table.Row>
1746
- <Table.Row>
1747
- <Table.RowHeader>3</Table.RowHeader>
1748
- <Table.Cell>The Godfather: Part II</Table.Cell>
1749
- <Table.Cell>1974</Table.Cell>
1750
- <Table.Cell>9.0</Table.Cell>
1751
- </Table.Row>
1752
- </Table.Body>
1753
- </Table>
1754
- </div>
1755
- )
1756
- }
1757
-
1758
- render(<Example />)
1759
- ```
863
+ render(<Example />)
864
+ ```
1760
865
 
1761
866
  #### Fully custom components
1762
867
 
@@ -1769,211 +874,102 @@ If you want to use fully custom components you have to pay attention to the foll
1769
874
 
1770
875
  Basic fully custom table:
1771
876
 
1772
- - ```javascript
1773
- class CustomTableCell extends React.Component {
1774
- render() {
1775
- return <td>{this.props.children}</td>
1776
- }
1777
- }
1778
-
1779
- class CustomTableRow extends React.Component {
1780
- static contextType = TableContext
1781
- state = { isHovered: false }
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
+ }
1782
904
 
1783
- toggleHoverOff = () => {
1784
- this.setState({ isHovered: false })
1785
- }
1786
- toggleHoverOn = () => {
1787
- this.setState({ isHovered: true })
1788
- }
905
+ const Example = () => {
906
+ const [layout, setLayout] = useState('auto')
907
+ const [hover, setHover] = useState(false)
1789
908
 
1790
- render() {
1791
- const rowStyle =
1792
- this.context.hover && this.state.isHovered
1793
- ? { backgroundColor: 'SeaGreen' }
1794
- : { backgroundColor: 'white' }
1795
- return (
1796
- <tr
1797
- style={rowStyle}
1798
- onMouseOver={this.toggleHoverOn}
1799
- onMouseOut={this.toggleHoverOff}
1800
- >
1801
- {this.props.children}
1802
- </tr>
1803
- )
909
+ const handleChange = (field, value) => {
910
+ if (field === 'layout') {
911
+ setLayout(value)
912
+ } else if (field === 'hover') {
913
+ setHover(!hover)
1804
914
  }
1805
915
  }
1806
916
 
1807
- class Example extends React.Component {
1808
- state = {
1809
- layout: 'auto',
1810
- hover: false
1811
- }
1812
-
1813
- handleChange = (field, value) => {
1814
- this.setState({
1815
- [field]: value
1816
- })
1817
- }
1818
-
1819
- renderOptions() {
1820
- const { layout, hover } = this.state
1821
-
1822
- return (
1823
- <Flex alignItems="start">
1824
- <Flex.Item margin="small">
1825
- <RadioInputGroup
1826
- name="Layout"
1827
- description="Layout"
1828
- value={layout}
1829
- onChange={(e, value) => this.handleChange('layout', value)}
1830
- >
1831
- <RadioInput label="auto" value="auto" />
1832
- <RadioInput label="fixed" value="fixed" />
1833
- </RadioInputGroup>
1834
- </Flex.Item>
1835
- <Flex.Item margin="small">
1836
- <Checkbox
1837
- label="hover"
1838
- checked={hover}
1839
- onChange={(e, value) => this.handleChange('hover', !hover)}
1840
- />
1841
- </Flex.Item>
1842
- </Flex>
1843
- )
1844
- }
1845
-
1846
- render() {
1847
- const { layout, hover } = this.state
1848
-
1849
- return (
1850
- <div>
1851
- {this.renderOptions()}
1852
- <Table caption="Top rated movies" layout={layout} hover={hover}>
1853
- <Table.Head>
1854
- <CustomTableRow>
1855
- <CustomTableCell scope="col">Rank</CustomTableCell>
1856
- <CustomTableCell scope="col">Title</CustomTableCell>
1857
- <CustomTableCell scope="col">Year</CustomTableCell>
1858
- <CustomTableCell scope="col">Rating</CustomTableCell>
1859
- </CustomTableRow>
1860
- </Table.Head>
1861
- <Table.Body>
1862
- <CustomTableRow>
1863
- <CustomTableCell scope="row">1</CustomTableCell>
1864
- <CustomTableCell>The Godfather</CustomTableCell>
1865
- <CustomTableCell>1972</CustomTableCell>
1866
- <CustomTableCell>9.2</CustomTableCell>
1867
- </CustomTableRow>
1868
- <CustomTableRow>
1869
- <CustomTableCell scope="row">2</CustomTableCell>
1870
- <CustomTableCell>The Godfather: Part II</CustomTableCell>
1871
- <CustomTableCell>1974</CustomTableCell>
1872
- <CustomTableCell>9.0</CustomTableCell>
1873
- </CustomTableRow>
1874
- </Table.Body>
1875
- </Table>
1876
- </div>
1877
- )
1878
- }
1879
- }
1880
-
1881
- render(<Example />)
1882
- ```
1883
-
1884
- - ```javascript
1885
- const CustomTableCell = ({ children, ...props }) => (
1886
- <td {...props}>{children}</td>
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>
1887
938
  )
1888
939
 
1889
- const CustomTableRow = ({ children, ...props }) => {
1890
- const { hover } = useContext(TableContext)
1891
- const [isHovered, setIsHovered] = useState(false)
1892
-
1893
- const rowStyle =
1894
- hover && isHovered
1895
- ? { backgroundColor: 'SeaGreen' }
1896
- : { backgroundColor: 'white' }
1897
-
1898
- return (
1899
- <tr
1900
- style={rowStyle}
1901
- onMouseOver={() => setIsHovered(true)}
1902
- onMouseOut={() => setIsHovered(false)}
1903
- >
1904
- {children}
1905
- </tr>
1906
- )
1907
- }
1908
-
1909
- const Example = () => {
1910
- const [layout, setLayout] = useState('auto')
1911
- const [hover, setHover] = useState(false)
1912
-
1913
- const handleChange = (field, value) => {
1914
- if (field === 'layout') {
1915
- setLayout(value)
1916
- } else if (field === 'hover') {
1917
- setHover(!hover)
1918
- }
1919
- }
1920
-
1921
- const renderOptions = () => (
1922
- <Flex alignItems="start">
1923
- <Flex.Item margin="small">
1924
- <RadioInputGroup
1925
- name="Layout"
1926
- description="Layout"
1927
- value={layout}
1928
- onChange={(e, value) => handleChange('layout', value)}
1929
- >
1930
- <RadioInput label="auto" value="auto" />
1931
- <RadioInput label="fixed" value="fixed" />
1932
- </RadioInputGroup>
1933
- </Flex.Item>
1934
- <Flex.Item margin="small">
1935
- <Checkbox
1936
- label="hover"
1937
- checked={hover}
1938
- onChange={(e, value) => handleChange('hover', !hover)}
1939
- />
1940
- </Flex.Item>
1941
- </Flex>
1942
- )
1943
-
1944
- return (
1945
- <div>
1946
- {renderOptions()}
1947
- <Table caption="Top rated movies" layout={layout} hover={hover}>
1948
- <Table.Head>
1949
- <CustomTableRow>
1950
- <CustomTableCell scope="col">Rank</CustomTableCell>
1951
- <CustomTableCell scope="col">Title</CustomTableCell>
1952
- <CustomTableCell scope="col">Year</CustomTableCell>
1953
- <CustomTableCell scope="col">Rating</CustomTableCell>
1954
- </CustomTableRow>
1955
- </Table.Head>
1956
- <Table.Body>
1957
- <CustomTableRow>
1958
- <CustomTableCell scope="row">1</CustomTableCell>
1959
- <CustomTableCell>The Godfather</CustomTableCell>
1960
- <CustomTableCell>1972</CustomTableCell>
1961
- <CustomTableCell>9.2</CustomTableCell>
1962
- </CustomTableRow>
1963
- <CustomTableRow>
1964
- <CustomTableCell scope="row">2</CustomTableCell>
1965
- <CustomTableCell>The Godfather: Part II</CustomTableCell>
1966
- <CustomTableCell>1974</CustomTableCell>
1967
- <CustomTableCell>9.0</CustomTableCell>
1968
- </CustomTableRow>
1969
- </Table.Body>
1970
- </Table>
1971
- </div>
1972
- )
1973
- }
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
+ }
1974
970
 
1975
- render(<Example />)
1976
- ```
971
+ render(<Example />)
972
+ ```
1977
973
 
1978
974
  #### Fully custom components with `stacked` layout
1979
975
 
@@ -1995,269 +991,129 @@ Also you need the following props on the components:
1995
991
 
1996
992
  Custom table with `stacked` layout support:
1997
993
 
1998
- - ```javascript
1999
- class CustomTableCell extends React.Component {
2000
- static contextType = TableContext
2001
-
2002
- render() {
2003
- const isStacked = this.context.isStacked
2004
- if (isStacked) {
2005
- let headerTxt
2006
- if (typeof this.props.header === 'function') {
2007
- headerTxt = React.createElement(this.props.header)
2008
- } else {
2009
- headerTxt = this.props.header
2010
- }
2011
- return (
2012
- <div role="cell">
2013
- {headerTxt && headerTxt}
2014
- {headerTxt && ': '}
2015
- {this.props.children}
2016
- </div>
2017
- )
2018
- }
2019
- return <td>{this.props.children}</td>
2020
- }
2021
- }
2022
-
2023
- class CustomTableRow extends React.Component {
2024
- static contextType = TableContext
2025
- state = { isHovered: false }
2026
-
2027
- toggleHoverOff = () => {
2028
- this.setState({ isHovered: false })
2029
- }
2030
- toggleHoverOn = () => {
2031
- this.setState({ isHovered: true })
2032
- }
2033
-
2034
- render() {
2035
- const { hover, headers, isStacked } = this.context
2036
- const Tag = isStacked ? 'div' : 'tr'
2037
- const rowStyle =
2038
- hover && this.state.isHovered
2039
- ? { backgroundColor: 'SeaGreen' }
2040
- : { backgroundColor: 'white' }
2041
-
2042
- return (
2043
- <Tag
2044
- style={rowStyle}
2045
- role={isStacked ? 'row' : undefined}
2046
- onMouseOver={this.toggleHoverOn}
2047
- onMouseOut={this.toggleHoverOff}
2048
- >
2049
- {React.Children.toArray(this.props.children)
2050
- .filter(React.isValidElement)
2051
- .map((child, index) => {
2052
- return React.cloneElement(child, {
2053
- key: child.props.name,
2054
- // used by `CustomTableCell` to render its column title in `stacked` layout
2055
- header: headers && headers[index]
2056
- })
2057
- })}
2058
- </Tag>
2059
- )
2060
- }
2061
- }
2062
-
2063
- class Example extends React.Component {
2064
- state = {
2065
- layout: 'auto',
2066
- hover: false
2067
- }
2068
-
2069
- handleChange = (field, value) => {
2070
- this.setState({
2071
- [field]: value
2072
- })
2073
- }
2074
-
2075
- renderOptions() {
2076
- const { layout, hover } = this.state
2077
-
2078
- return (
2079
- <Flex alignItems="start">
2080
- <Flex.Item margin="small">
2081
- <RadioInputGroup
2082
- name="customStackedLayout"
2083
- description="Layout"
2084
- value={layout}
2085
- onChange={(e, value) => this.handleChange('layout', value)}
2086
- >
2087
- <RadioInput label="auto" value="auto" />
2088
- <RadioInput label="fixed" value="fixed" />
2089
- <RadioInput label="stacked" value="stacked" />
2090
- </RadioInputGroup>
2091
- </Flex.Item>
2092
- <Flex.Item margin="small">
2093
- <Checkbox
2094
- label="hover"
2095
- checked={hover}
2096
- onChange={(e, value) => this.handleChange('hover', !hover)}
2097
- />
2098
- </Flex.Item>
2099
- </Flex>
2100
- )
2101
- }
2102
-
2103
- render() {
2104
- const { layout, hover } = this.state
2105
-
2106
- return (
2107
- <div>
2108
- {this.renderOptions()}
2109
- <Table caption="Top rated movies" layout={layout} hover={hover}>
2110
- <Table.Head>
2111
- <CustomTableRow>
2112
- <CustomTableCell scope="col">Rank</CustomTableCell>
2113
- <CustomTableCell scope="col">Title</CustomTableCell>
2114
- <CustomTableCell scope="col">Year</CustomTableCell>
2115
- <CustomTableCell scope="col">Rating</CustomTableCell>
2116
- </CustomTableRow>
2117
- </Table.Head>
2118
- <Table.Body>
2119
- <CustomTableRow>
2120
- <CustomTableCell scope="row">1</CustomTableCell>
2121
- <CustomTableCell>The Godfather</CustomTableCell>
2122
- <CustomTableCell>1972</CustomTableCell>
2123
- <CustomTableCell>9.2</CustomTableCell>
2124
- </CustomTableRow>
2125
- <CustomTableRow>
2126
- <CustomTableCell scope="row">2</CustomTableCell>
2127
- <CustomTableCell>The Godfather: Part II</CustomTableCell>
2128
- <CustomTableCell>1974</CustomTableCell>
2129
- <CustomTableCell>9.0</CustomTableCell>
2130
- </CustomTableRow>
2131
- </Table.Body>
2132
- </Table>
2133
- </div>
2134
- )
2135
- }
2136
- }
2137
-
2138
- render(<Example />)
2139
- ```
2140
-
2141
- - ```javascript
2142
- const CustomTableCell = ({ children, header }) => {
2143
- const { isStacked } = useContext(TableContext)
2144
- if (isStacked) {
2145
- let headerTxt
2146
- if (typeof header === 'function') {
2147
- headerTxt = React.createElement(header)
2148
- } else {
2149
- headerTxt = header
2150
- }
2151
- return (
2152
- <div role="cell">
2153
- {headerTxt && headerTxt}
2154
- {headerTxt && ': '}
2155
- {children}
2156
- </div>
2157
- )
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
2158
1006
  }
2159
- return <td>{children}</td>
2160
- }
2161
-
2162
- const CustomTableRow = ({ children }) => {
2163
- const { hover, headers, isStacked } = useContext(TableContext)
2164
- const [isHovered, setIsHovered] = useState(false)
2165
-
2166
- const Tag = isStacked ? 'div' : 'tr'
2167
- const rowStyle =
2168
- hover && isHovered
2169
- ? { backgroundColor: 'SeaGreen' }
2170
- : { backgroundColor: 'white' }
2171
-
2172
1007
  return (
2173
- <Tag
2174
- style={rowStyle}
2175
- role={isStacked ? 'row' : undefined}
2176
- onMouseOver={() => setIsHovered(true)}
2177
- onMouseOut={() => setIsHovered(false)}
2178
- >
2179
- {React.Children.toArray(children)
2180
- .filter(React.isValidElement)
2181
- .map((child, index) => {
2182
- return React.cloneElement(child, {
2183
- key: child.props.name,
2184
- // used by `CustomTableCell` to render its column title in `stacked` layout
2185
- header: headers && headers[index]
2186
- })
2187
- })}
2188
- </Tag>
1008
+ <div role="cell">
1009
+ {headerTxt && headerTxt}
1010
+ {headerTxt && ': '}
1011
+ {children}
1012
+ </div>
2189
1013
  )
2190
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
+ }
2191
1047
 
2192
- const Example = () => {
2193
- const [layout, setLayout] = useState('auto')
2194
- const [hover, setHover] = useState(false)
1048
+ const Example = () => {
1049
+ const [layout, setLayout] = useState('auto')
1050
+ const [hover, setHover] = useState(false)
2195
1051
 
2196
- const handleChange = (field, value) => {
2197
- if (field === 'layout') {
2198
- setLayout(value)
2199
- } else if (field === 'hover') {
2200
- setHover(!hover)
2201
- }
1052
+ const handleChange = (field, value) => {
1053
+ if (field === 'layout') {
1054
+ setLayout(value)
1055
+ } else if (field === 'hover') {
1056
+ setHover(!hover)
2202
1057
  }
1058
+ }
2203
1059
 
2204
- const renderOptions = () => (
2205
- <Flex alignItems="start">
2206
- <Flex.Item margin="small">
2207
- <RadioInputGroup
2208
- name="customStackedLayout"
2209
- description="Layout"
2210
- value={layout}
2211
- onChange={(e, value) => handleChange('layout', value)}
2212
- >
2213
- <RadioInput label="auto" value="auto" />
2214
- <RadioInput label="fixed" value="fixed" />
2215
- <RadioInput label="stacked" value="stacked" />
2216
- </RadioInputGroup>
2217
- </Flex.Item>
2218
- <Flex.Item margin="small">
2219
- <Checkbox
2220
- label="hover"
2221
- checked={hover}
2222
- onChange={(e, value) => handleChange('hover', !hover)}
2223
- />
2224
- </Flex.Item>
2225
- </Flex>
2226
- )
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
+ )
2227
1083
 
2228
- return (
2229
- <div>
2230
- {renderOptions()}
2231
- <Table caption="Top rated movies" layout={layout} hover={hover}>
2232
- <Table.Head>
2233
- <CustomTableRow>
2234
- <CustomTableCell scope="col">Rank</CustomTableCell>
2235
- <CustomTableCell scope="col">Title</CustomTableCell>
2236
- <CustomTableCell scope="col">Year</CustomTableCell>
2237
- <CustomTableCell scope="col">Rating</CustomTableCell>
2238
- </CustomTableRow>
2239
- </Table.Head>
2240
- <Table.Body>
2241
- <CustomTableRow>
2242
- <CustomTableCell scope="row">1</CustomTableCell>
2243
- <CustomTableCell>The Godfather</CustomTableCell>
2244
- <CustomTableCell>1972</CustomTableCell>
2245
- <CustomTableCell>9.2</CustomTableCell>
2246
- </CustomTableRow>
2247
- <CustomTableRow>
2248
- <CustomTableCell scope="row">2</CustomTableCell>
2249
- <CustomTableCell>The Godfather: Part II</CustomTableCell>
2250
- <CustomTableCell>1974</CustomTableCell>
2251
- <CustomTableCell>9.0</CustomTableCell>
2252
- </CustomTableRow>
2253
- </Table.Body>
2254
- </Table>
2255
- </div>
2256
- )
2257
- }
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
+ }
2258
1114
 
2259
- render(<Example />)
2260
- ```
1115
+ render(<Example />)
1116
+ ```
2261
1117
 
2262
1118
  ### Guidelines
2263
1119