Skip to content

Commit e77bbb0

Browse files
committed
feat(ui-table): add column ordering to caption
INSTUI-4699
1 parent c827833 commit e77bbb0

File tree

2 files changed

+59
-52
lines changed

2 files changed

+59
-52
lines changed

packages/ui-table/src/Table/README.md

Lines changed: 4 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -582,10 +582,7 @@ By default, the options in the `Select` for sorting in stacked layout are genera
582582
</View>
583583
)}
584584

585-
<Table
586-
caption={`${caption}: sorted by ${sortBy} in ${direction} order`}
587-
{...props}
588-
>
585+
<Table {...props}>
589586
<Table.Head renderSortLabel="Sort by">
590587
{this.renderHeaderRow(direction)}
591588
</Table.Head>
@@ -601,13 +598,6 @@ By default, the options in the `Select` for sorting in stacked layout are genera
601598
))}
602599
</Table.Body>
603600
</Table>
604-
<Alert
605-
liveRegion={() => document.getElementById('flash-messages')}
606-
liveRegionPoliteness="polite"
607-
screenReaderOnly
608-
>
609-
{`Sorted by ${sortBy} in ${direction} order`}
610-
</Alert>
611601
</div>
612602
)}
613603
</Responsive>
@@ -806,10 +796,7 @@ By default, the options in the `Select` for sorting in stacked layout are genera
806796
</View>
807797
)}
808798

809-
<Table
810-
caption={`${caption}: sorted by ${sortBy} in ${direction} order`}
811-
{...props}
812-
>
799+
<Table {...props}>
813800
<Table.Head renderSortLabel="Sort by">
814801
{renderHeaderRow(direction)}
815802
</Table.Head>
@@ -825,13 +812,6 @@ By default, the options in the `Select` for sorting in stacked layout are genera
825812
))}
826813
</Table.Body>
827814
</Table>
828-
<Alert
829-
liveRegion={() => document.getElementById('flash-messages')}
830-
liveRegionPoliteness="polite"
831-
screenReaderOnly
832-
>
833-
{`Sorted by ${sortBy} in ${direction} order`}
834-
</Alert>
835815
</div>
836816
)}
837817
</Responsive>
@@ -966,10 +946,7 @@ that selection does not re-paginate or re-sort the table, and pagination does no
966946
<View as="div" padding="small" background="primary-inverse">
967947
{`${selected.size} of ${rowIds.length} selected`}
968948
</View>
969-
<Table
970-
caption={`${caption}: sorted by ${sortBy} in ${direction} order`}
971-
{...props}
972-
>
949+
<Table {...props}>
973950
<Table.Head
974951
renderSortLabel={
975952
<ScreenReaderContent>Sort by</ScreenReaderContent>
@@ -1175,15 +1152,6 @@ that selection does not re-paginate or re-sort the table, and pagination does no
11751152
ascending={ascending}
11761153
perPage={perPage}
11771154
/>
1178-
<Alert
1179-
liveRegion={() => document.getElementById('flash-messages')}
1180-
liveRegionPoliteness="polite"
1181-
screenReaderOnly
1182-
>
1183-
{`Sorted by ${sortBy} in ${
1184-
ascending ? 'ascending' : 'descending'
1185-
} order`}
1186-
</Alert>
11871155
</div>
11881156
)
11891157
}
@@ -1305,10 +1273,7 @@ that selection does not re-paginate or re-sort the table, and pagination does no
13051273
<View as="div" padding="small" background="primary-inverse">
13061274
{`${selected.size} of ${rowIds.length} selected`}
13071275
</View>
1308-
<Table
1309-
caption={`${caption}: sorted by ${sortBy} in ${direction} order`}
1310-
{...props}
1311-
>
1276+
<Table {...props}>
13121277
<Table.Head
13131278
renderSortLabel={
13141279
<ScreenReaderContent>Sort by</ScreenReaderContent>
@@ -1485,15 +1450,6 @@ that selection does not re-paginate or re-sort the table, and pagination does no
14851450
ascending={ascending}
14861451
perPage={perPage}
14871452
/>
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>
14971453
</div>
14981454
)
14991455
}

packages/ui-table/src/Table/index.tsx

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,46 @@ class Table extends Component<TableProps> {
101101
})
102102
}
103103

104+
getSortedHeaderInfo() {
105+
const [headChild] = Children.toArray(this.props.children)
106+
if (!headChild || !isValidElement(headChild)) return null
107+
const [firstRow] = Children.toArray(headChild.props.children)
108+
if (!firstRow || !isValidElement(firstRow)) return null
109+
const colHeaders = Children.toArray(firstRow.props.children)
110+
for (const colHeader of colHeaders) {
111+
if (
112+
isValidElement(colHeader) &&
113+
colHeader.props.sortDirection &&
114+
colHeader.props.sortDirection !== 'none'
115+
) {
116+
const headerText =
117+
typeof colHeader.props.children === 'string'
118+
? colHeader.props.children
119+
: colHeader.props.children?.props?.children ?? ''
120+
return {
121+
header: headerText,
122+
direction: colHeader.props.sortDirection
123+
}
124+
}
125+
}
126+
return null
127+
}
128+
104129
render() {
105130
const { margin, layout, caption, children, hover, styles } = this.props
106131
const isStacked = layout === 'stacked'
107132
const headers = isStacked ? this.getHeaders() : undefined
108133

134+
// Add sorting info to caption for screen readers
135+
const sortedHeaderInfo = this.getSortedHeaderInfo()
136+
let captionText = caption as string
137+
if (sortedHeaderInfo) {
138+
captionText = caption
139+
? caption +
140+
` Sorted by ${sortedHeaderInfo.header} (${sortedHeaderInfo.direction})`
141+
: `Sorted by ${sortedHeaderInfo.header} (${sortedHeaderInfo.direction})`
142+
}
143+
109144
return (
110145
<TableContext.Provider
111146
value={{
@@ -124,12 +159,28 @@ class Table extends Component<TableProps> {
124159
elementRef={this.handleRef}
125160
css={styles?.table}
126161
role={isStacked ? 'table' : undefined}
127-
aria-label={isStacked ? (caption as string) : undefined}
162+
aria-label={isStacked ? captionText : undefined}
128163
>
129164
{!isStacked && (
130-
<caption>
131-
<ScreenReaderContent>{caption}</ScreenReaderContent>
132-
</caption>
165+
<>
166+
<caption>
167+
<ScreenReaderContent>{captionText}</ScreenReaderContent>
168+
</caption>
169+
{sortedHeaderInfo && (
170+
<div
171+
aria-live="polite"
172+
style={{
173+
position: 'absolute',
174+
width: 1,
175+
height: 1,
176+
overflow: 'hidden',
177+
clip: 'rect(1px, 1px, 1px, 1px)'
178+
}}
179+
>
180+
{captionText}
181+
</div>
182+
)}
183+
</>
133184
)}
134185
{Children.map(children, (child) => {
135186
if (isValidElement(child)) {

0 commit comments

Comments
 (0)