Skip to content

Commit 3d45c7c

Browse files
committed
✨(frontend) improve accessibility and styling of summary table
adds semantic structure, aria attributes, and token-based focus styling Signed-off-by: Cyril <c.gromoff@gmail.com>
1 parent cdb26b4 commit 3d45c7c

File tree

3 files changed

+77
-19
lines changed

3 files changed

+77
-19
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to
1010

1111
- ♿(frontend) improve accessibility:
1212
- ♿(frontend) improve ARIA in doc grid and editor for a11y #1519
13+
- ♿(frontend) improve accessibility and styling of summary table #1528
1314
- 🐛(docx) fix image overflow by limiting width to 600px during export #1525
1415
- 🐛(frontend) preserve @ character when esc is pressed after typing it #1512
1516

src/frontend/apps/impress/src/features/docs/doc-table-content/components/Heading.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useState } from 'react';
2+
import { css } from 'styled-components';
23

34
import { BoxButton, Text } from '@/components';
45
import { useCunninghamTheme } from '@/cunningham';
@@ -40,7 +41,6 @@ export const Heading = ({
4041
<BoxButton
4142
id={`heading-${headingId}`}
4243
$width="100%"
43-
key={headingId}
4444
onMouseOver={() => setIsHover(true)}
4545
onMouseLeave={() => setIsHover(false)}
4646
onClick={() => {
@@ -59,8 +59,19 @@ export const Heading = ({
5959
}}
6060
$radius="4px"
6161
$background={isActive ? `${colorsTokens['greyscale-100']}` : 'none'}
62-
$css="text-align: left;"
62+
$css={css`
63+
text-align: left;
64+
&:focus-visible {
65+
/* Scoped focus style: same footprint as hover, with theme shadow */
66+
outline: none;
67+
box-shadow: 0 0 0 2px ${colorsTokens['primary-400']};
68+
border-radius: 4px;
69+
}
70+
`}
6371
className="--docs--table-content-heading"
72+
aria-label={text}
73+
aria-selected={isHighlight}
74+
aria-current={isHighlight ? 'true' : undefined}
6475
>
6576
<Text
6677
$width="100%"

src/frontend/apps/impress/src/features/docs/doc-table-content/components/TableContent.tsx

Lines changed: 63 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { Heading } from './Heading';
1212
export const TableContent = () => {
1313
const { headings } = useHeadingStore();
1414
const { editor } = useEditorStore();
15-
const { spacingsTokens } = useCunninghamTheme();
15+
const { spacingsTokens, colorsTokens } = useCunninghamTheme();
1616

1717
const [headingIdHighlight, setHeadingIdHighlight] = useState<string>();
1818

@@ -99,33 +99,62 @@ export const TableContent = () => {
9999

100100
return (
101101
<Box
102+
as="nav"
102103
id="summaryContainer"
103104
$width={!isHover ? '40px' : '200px'}
104105
$height={!isHover ? '40px' : 'auto'}
105106
$maxHeight="calc(50vh - 60px)"
106107
$zIndex={1000}
107108
$align="center"
108-
$padding="xs"
109+
$padding={isHover ? 'xs' : '0'}
109110
$justify="center"
111+
$position="relative"
112+
aria-label={t('Summary')}
110113
$css={css`
111-
border: 1px solid #ccc;
114+
border: 1px solid ${colorsTokens['greyscale-300']};
112115
overflow: hidden;
113-
border-radius: var(--c--theme--spacings--3xs);
114-
background: var(--c--theme--colors--greyscale-000);
116+
border-radius: ${spacingsTokens['3xs']};
117+
background: ${colorsTokens['greyscale-000']};
115118
${isHover &&
116119
css`
117120
display: flex;
118121
flex-direction: column;
119122
justify-content: flex-start;
120123
align-items: flex-start;
121-
gap: var(--c--theme--spacings--2xs);
124+
gap: ${spacingsTokens['2xs']};
122125
`}
123126
`}
124127
className="--docs--table-content"
125128
>
126129
{!isHover && (
127-
<BoxButton onClick={onOpen} $justify="center" $align="center">
128-
<Icon iconName="list" $theme="primary" $variation="800" />
130+
<BoxButton
131+
onClick={onOpen}
132+
$width="100%"
133+
$height="100%"
134+
$justify="center"
135+
$align="center"
136+
aria-label={t('Summary')}
137+
aria-expanded={isHover}
138+
aria-controls="toc-list"
139+
$css={css`
140+
&:hover {
141+
background: ${colorsTokens['primary-100']};
142+
}
143+
&:focus-visible {
144+
outline: none;
145+
box-shadow: 0 0 0 4px ${colorsTokens['primary-400']};
146+
background: ${colorsTokens['primary-100']};
147+
width: 90%;
148+
height: 90%;
149+
}
150+
`}
151+
>
152+
<Icon
153+
iconName="list"
154+
$theme="primary"
155+
$variation="800"
156+
variant="symbols-outlined"
157+
/>
129158
</BoxButton>
130159
)}
131160
{isHover && (
@@ -134,10 +163,11 @@ export const TableContent = () => {
134163
$overflow="hidden"
135164
$css={css`
136165
user-select: none;
166+
padding: ${spacingsTokens['4xs']};
137167
`}
138168
>
139169
<Box
140-
$margin={{ bottom: '10px' }}
170+
$margin={{ bottom: spacingsTokens.xs }}
141171
$direction="row"
142172
$justify="space-between"
143173
$align="center"
@@ -149,30 +179,46 @@ export const TableContent = () => {
149179
onClick={onClose}
150180
$justify="center"
151181
$align="center"
182+
aria-label={t('Summary')}
183+
aria-expanded={isHover}
184+
aria-controls="toc-list"
152185
$css={css`
186+
transition: none !important;
153187
transform: rotate(180deg);
188+
&:focus-visible {
189+
outline: none;
190+
box-shadow: 0 0 0 2px ${colorsTokens['primary-400']};
191+
border-radius: 4px;
192+
}
154193
`}
155194
>
156195
<Icon iconName="menu_open" $theme="primary" $variation="800" />
157196
</BoxButton>
158197
</Box>
159198
<Box
199+
as="ul"
200+
id="toc-list"
201+
role="list"
160202
$gap={spacingsTokens['3xs']}
161203
$css={css`
162204
overflow-y: auto;
205+
list-style: none;
206+
padding: ${spacingsTokens['3xs']};
207+
margin: 0;
163208
`}
164209
>
165210
{headings?.map(
166211
(heading) =>
167212
heading.contentText && (
168-
<Heading
169-
editor={editor}
170-
headingId={heading.id}
171-
level={heading.props.level}
172-
text={heading.contentText}
173-
key={heading.id}
174-
isHighlight={headingIdHighlight === heading.id}
175-
/>
213+
<Box as="li" role="listitem" key={heading.id}>
214+
<Heading
215+
editor={editor}
216+
headingId={heading.id}
217+
level={heading.props.level}
218+
text={heading.contentText}
219+
isHighlight={headingIdHighlight === heading.id}
220+
/>
221+
</Box>
176222
),
177223
)}
178224
</Box>

0 commit comments

Comments
 (0)