Skip to content

Commit 3d0b0e5

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 2f010cf commit 3d0b0e5

File tree

2 files changed

+63
-17
lines changed

2 files changed

+63
-17
lines changed

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';
@@ -59,8 +60,19 @@ export const Heading = ({
5960
}}
6061
$radius="4px"
6162
$background={isActive ? `${colorsTokens['greyscale-100']}` : 'none'}
62-
$css="text-align: left;"
63+
$css={css`
64+
text-align: left;
65+
&:focus-visible {
66+
/* Scoped focus style: same footprint as hover, with theme shadow */
67+
outline: none;
68+
box-shadow: 0 0 0 2px ${colorsTokens['primary-400']};
69+
border-radius: 4px;
70+
}
71+
`}
6372
className="--docs--table-content-heading"
73+
aria-label={text}
74+
aria-selected={isHighlight}
75+
aria-current={isHighlight ? 'true' : undefined}
6476
>
6577
<Text
6678
$width="100%"
@@ -69,7 +81,6 @@ export const Heading = ({
6981
$weight={isHighlight ? 'bold' : 'normal'}
7082
$css="overflow-wrap: break-word;"
7183
$hasTransition
72-
aria-selected={isHighlight}
7384
>
7485
{text}
7586
</Text>

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

Lines changed: 50 additions & 15 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,6 +99,7 @@ export const TableContent = () => {
9999

100100
return (
101101
<Box
102+
as="nav"
102103
id="summaryContainer"
103104
$width={!isHover ? '40px' : '200px'}
104105
$height={!isHover ? '40px' : 'auto'}
@@ -107,24 +108,41 @@ export const TableContent = () => {
107108
$align="center"
108109
$padding="xs"
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">
130+
<BoxButton
131+
onClick={() => (isHover ? onClose() : onOpen())}
132+
$justify="center"
133+
$align="center"
134+
aria-label={t('Summary')}
135+
aria-expanded={isHover}
136+
aria-controls="toc-list"
137+
$css={css`
138+
transition: none !important;
139+
&:focus-visible {
140+
outline: none;
141+
box-shadow: 0 0 0 2px ${colorsTokens['primary-400']};
142+
border-radius: 4px;
143+
}
144+
`}
145+
>
128146
<Icon iconName="list" $theme="primary" $variation="800" />
129147
</BoxButton>
130148
)}
@@ -134,10 +152,11 @@ export const TableContent = () => {
134152
$overflow="hidden"
135153
$css={css`
136154
user-select: none;
155+
padding: ${spacingsTokens['4xs']};
137156
`}
138157
>
139158
<Box
140-
$margin={{ bottom: '10px' }}
159+
$margin={{ bottom: spacingsTokens.xs }}
141160
$direction="row"
142161
$justify="space-between"
143162
$align="center"
@@ -149,30 +168,46 @@ export const TableContent = () => {
149168
onClick={onClose}
150169
$justify="center"
151170
$align="center"
171+
aria-label={t('Summary')}
172+
aria-expanded={isHover}
173+
aria-controls="toc-list"
152174
$css={css`
175+
transition: none !important;
153176
transform: rotate(180deg);
177+
&:focus-visible {
178+
outline: none;
179+
box-shadow: 0 0 0 2px ${colorsTokens['primary-400']};
180+
border-radius: 4px;
181+
}
154182
`}
155183
>
156184
<Icon iconName="menu_open" $theme="primary" $variation="800" />
157185
</BoxButton>
158186
</Box>
159187
<Box
188+
as="ul"
189+
id="toc-list"
190+
role="list"
160191
$gap={spacingsTokens['3xs']}
161192
$css={css`
162193
overflow-y: auto;
194+
list-style: none;
195+
padding: ${spacingsTokens['3xs']};
196+
margin: 0;
163197
`}
164198
>
165199
{headings?.map(
166200
(heading) =>
167201
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-
/>
202+
<Box as="li" role="listitem" key={heading.id}>
203+
<Heading
204+
editor={editor}
205+
headingId={heading.id}
206+
level={heading.props.level}
207+
text={heading.contentText}
208+
isHighlight={headingIdHighlight === heading.id}
209+
/>
210+
</Box>
176211
),
177212
)}
178213
</Box>

0 commit comments

Comments
 (0)