✨(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>
This commit is contained in:
@@ -10,6 +10,7 @@ and this project adheres to
|
|||||||
|
|
||||||
- ♿(frontend) improve accessibility:
|
- ♿(frontend) improve accessibility:
|
||||||
- ♿(frontend) improve ARIA in doc grid and editor for a11y #1519
|
- ♿(frontend) improve ARIA in doc grid and editor for a11y #1519
|
||||||
|
- ♿(frontend) improve accessibility and styling of summary table #1528
|
||||||
- 🐛(docx) fix image overflow by limiting width to 600px during export #1525
|
- 🐛(docx) fix image overflow by limiting width to 600px during export #1525
|
||||||
- 🐛(frontend) preserve @ character when esc is pressed after typing it #1512
|
- 🐛(frontend) preserve @ character when esc is pressed after typing it #1512
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { css } from 'styled-components';
|
||||||
|
|
||||||
import { BoxButton, Text } from '@/components';
|
import { BoxButton, Text } from '@/components';
|
||||||
import { useCunninghamTheme } from '@/cunningham';
|
import { useCunninghamTheme } from '@/cunningham';
|
||||||
@@ -40,7 +41,6 @@ export const Heading = ({
|
|||||||
<BoxButton
|
<BoxButton
|
||||||
id={`heading-${headingId}`}
|
id={`heading-${headingId}`}
|
||||||
$width="100%"
|
$width="100%"
|
||||||
key={headingId}
|
|
||||||
onMouseOver={() => setIsHover(true)}
|
onMouseOver={() => setIsHover(true)}
|
||||||
onMouseLeave={() => setIsHover(false)}
|
onMouseLeave={() => setIsHover(false)}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -59,8 +59,19 @@ export const Heading = ({
|
|||||||
}}
|
}}
|
||||||
$radius="4px"
|
$radius="4px"
|
||||||
$background={isActive ? `${colorsTokens['greyscale-100']}` : 'none'}
|
$background={isActive ? `${colorsTokens['greyscale-100']}` : 'none'}
|
||||||
$css="text-align: left;"
|
$css={css`
|
||||||
|
text-align: left;
|
||||||
|
&:focus-visible {
|
||||||
|
/* Scoped focus style: same footprint as hover, with theme shadow */
|
||||||
|
outline: none;
|
||||||
|
box-shadow: 0 0 0 2px ${colorsTokens['primary-400']};
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
`}
|
||||||
className="--docs--table-content-heading"
|
className="--docs--table-content-heading"
|
||||||
|
aria-label={text}
|
||||||
|
aria-selected={isHighlight}
|
||||||
|
aria-current={isHighlight ? 'true' : undefined}
|
||||||
>
|
>
|
||||||
<Text
|
<Text
|
||||||
$width="100%"
|
$width="100%"
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { Heading } from './Heading';
|
|||||||
export const TableContent = () => {
|
export const TableContent = () => {
|
||||||
const { headings } = useHeadingStore();
|
const { headings } = useHeadingStore();
|
||||||
const { editor } = useEditorStore();
|
const { editor } = useEditorStore();
|
||||||
const { spacingsTokens } = useCunninghamTheme();
|
const { spacingsTokens, colorsTokens } = useCunninghamTheme();
|
||||||
|
|
||||||
const [headingIdHighlight, setHeadingIdHighlight] = useState<string>();
|
const [headingIdHighlight, setHeadingIdHighlight] = useState<string>();
|
||||||
|
|
||||||
@@ -99,33 +99,62 @@ export const TableContent = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
|
as="nav"
|
||||||
id="summaryContainer"
|
id="summaryContainer"
|
||||||
$width={!isHover ? '40px' : '200px'}
|
$width={!isHover ? '40px' : '200px'}
|
||||||
$height={!isHover ? '40px' : 'auto'}
|
$height={!isHover ? '40px' : 'auto'}
|
||||||
$maxHeight="calc(50vh - 60px)"
|
$maxHeight="calc(50vh - 60px)"
|
||||||
$zIndex={1000}
|
$zIndex={1000}
|
||||||
$align="center"
|
$align="center"
|
||||||
$padding="xs"
|
$padding={isHover ? 'xs' : '0'}
|
||||||
$justify="center"
|
$justify="center"
|
||||||
|
$position="relative"
|
||||||
|
aria-label={t('Summary')}
|
||||||
$css={css`
|
$css={css`
|
||||||
border: 1px solid #ccc;
|
border: 1px solid ${colorsTokens['greyscale-300']};
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: var(--c--theme--spacings--3xs);
|
border-radius: ${spacingsTokens['3xs']};
|
||||||
background: var(--c--theme--colors--greyscale-000);
|
background: ${colorsTokens['greyscale-000']};
|
||||||
${isHover &&
|
${isHover &&
|
||||||
css`
|
css`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: var(--c--theme--spacings--2xs);
|
gap: ${spacingsTokens['2xs']};
|
||||||
`}
|
`}
|
||||||
`}
|
`}
|
||||||
className="--docs--table-content"
|
className="--docs--table-content"
|
||||||
>
|
>
|
||||||
{!isHover && (
|
{!isHover && (
|
||||||
<BoxButton onClick={onOpen} $justify="center" $align="center">
|
<BoxButton
|
||||||
<Icon iconName="list" $theme="primary" $variation="800" />
|
onClick={onOpen}
|
||||||
|
$width="100%"
|
||||||
|
$height="100%"
|
||||||
|
$justify="center"
|
||||||
|
$align="center"
|
||||||
|
aria-label={t('Summary')}
|
||||||
|
aria-expanded={isHover}
|
||||||
|
aria-controls="toc-list"
|
||||||
|
$css={css`
|
||||||
|
&:hover {
|
||||||
|
background: ${colorsTokens['primary-100']};
|
||||||
|
}
|
||||||
|
&:focus-visible {
|
||||||
|
outline: none;
|
||||||
|
box-shadow: 0 0 0 4px ${colorsTokens['primary-400']};
|
||||||
|
background: ${colorsTokens['primary-100']};
|
||||||
|
width: 90%;
|
||||||
|
height: 90%;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
iconName="list"
|
||||||
|
$theme="primary"
|
||||||
|
$variation="800"
|
||||||
|
variant="symbols-outlined"
|
||||||
|
/>
|
||||||
</BoxButton>
|
</BoxButton>
|
||||||
)}
|
)}
|
||||||
{isHover && (
|
{isHover && (
|
||||||
@@ -134,10 +163,11 @@ export const TableContent = () => {
|
|||||||
$overflow="hidden"
|
$overflow="hidden"
|
||||||
$css={css`
|
$css={css`
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
padding: ${spacingsTokens['4xs']};
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
$margin={{ bottom: '10px' }}
|
$margin={{ bottom: spacingsTokens.xs }}
|
||||||
$direction="row"
|
$direction="row"
|
||||||
$justify="space-between"
|
$justify="space-between"
|
||||||
$align="center"
|
$align="center"
|
||||||
@@ -149,30 +179,46 @@ export const TableContent = () => {
|
|||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
$justify="center"
|
$justify="center"
|
||||||
$align="center"
|
$align="center"
|
||||||
|
aria-label={t('Summary')}
|
||||||
|
aria-expanded={isHover}
|
||||||
|
aria-controls="toc-list"
|
||||||
$css={css`
|
$css={css`
|
||||||
|
transition: none !important;
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
|
&:focus-visible {
|
||||||
|
outline: none;
|
||||||
|
box-shadow: 0 0 0 2px ${colorsTokens['primary-400']};
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
<Icon iconName="menu_open" $theme="primary" $variation="800" />
|
<Icon iconName="menu_open" $theme="primary" $variation="800" />
|
||||||
</BoxButton>
|
</BoxButton>
|
||||||
</Box>
|
</Box>
|
||||||
<Box
|
<Box
|
||||||
|
as="ul"
|
||||||
|
id="toc-list"
|
||||||
|
role="list"
|
||||||
$gap={spacingsTokens['3xs']}
|
$gap={spacingsTokens['3xs']}
|
||||||
$css={css`
|
$css={css`
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
list-style: none;
|
||||||
|
padding: ${spacingsTokens['3xs']};
|
||||||
|
margin: 0;
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
{headings?.map(
|
{headings?.map(
|
||||||
(heading) =>
|
(heading) =>
|
||||||
heading.contentText && (
|
heading.contentText && (
|
||||||
<Heading
|
<Box as="li" role="listitem" key={heading.id}>
|
||||||
editor={editor}
|
<Heading
|
||||||
headingId={heading.id}
|
editor={editor}
|
||||||
level={heading.props.level}
|
headingId={heading.id}
|
||||||
text={heading.contentText}
|
level={heading.props.level}
|
||||||
key={heading.id}
|
text={heading.contentText}
|
||||||
isHighlight={headingIdHighlight === heading.id}
|
isHighlight={headingIdHighlight === heading.id}
|
||||||
/>
|
/>
|
||||||
|
</Box>
|
||||||
),
|
),
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
Reference in New Issue
Block a user