diff --git a/.changeset/light-moose-travel.md b/.changeset/light-moose-travel.md new file mode 100644 index 00000000..fbae4833 --- /dev/null +++ b/.changeset/light-moose-travel.md @@ -0,0 +1,9 @@ +--- +"streamdown": patch +--- + +Fix accessibility warnings for Mermaid toolbar icon buttons: + +- Add `aria-hidden="true"` to all decorative SVG icons to hide them from screen readers +- Add `aria-label` attributes to all icon-only buttons for proper screen reader announcements +- Add translation keys (`zoomIn`, `zoomOut`, `resetView`) for zoom controls diff --git a/packages/streamdown/__tests__/mermaid.test.tsx b/packages/streamdown/__tests__/mermaid.test.tsx index 7af696fd..f7b4a1a9 100644 --- a/packages/streamdown/__tests__/mermaid.test.tsx +++ b/packages/streamdown/__tests__/mermaid.test.tsx @@ -511,7 +511,7 @@ describe("Mermaid", () => { }); const mmdButton = await waitFor(() => - getByRole("button", { name: "MMD" }) + getByRole("button", { name: "Download diagram as MMD" }) ); await act(() => { @@ -553,7 +553,7 @@ describe("Mermaid", () => { }); const svgButton = await waitFor(() => - getByRole("button", { name: "SVG" }) + getByRole("button", { name: "Download diagram as SVG" }) ); await act(() => { @@ -624,7 +624,7 @@ describe("Mermaid", () => { }); const pngButton = await waitFor(() => - getByRole("button", { name: "PNG" }) + getByRole("button", { name: "Download diagram as PNG" }) ); await act(() => { @@ -665,7 +665,7 @@ describe("Mermaid", () => { }); const svgButton = await waitFor(() => - getByRole("button", { name: "SVG" }) + getByRole("button", { name: "Download diagram as SVG" }) ); await act(() => { diff --git a/packages/streamdown/lib/code-block/copy-button.tsx b/packages/streamdown/lib/code-block/copy-button.tsx index b254cb05..66832413 100644 --- a/packages/streamdown/lib/code-block/copy-button.tsx +++ b/packages/streamdown/lib/code-block/copy-button.tsx @@ -67,6 +67,7 @@ export const CodeBlockCopyButton = ({ return ( ); }; diff --git a/packages/streamdown/lib/mermaid/download-button.tsx b/packages/streamdown/lib/mermaid/download-button.tsx index 7f287f2d..b77541bc 100644 --- a/packages/streamdown/lib/mermaid/download-button.tsx +++ b/packages/streamdown/lib/mermaid/download-button.tsx @@ -107,6 +107,7 @@ export const MermaidDownloadDropdown = ({ return (
{isOpen ? (
{isFullscreen @@ -108,6 +109,7 @@ export const MermaidFullscreenButton = ({ tabIndex={0} > {/* biome-ignore lint/a11y/noStaticElementInteractions: "div with role=presentation is used for event propagation control" */}
{ const { RotateCcwIcon, ZoomInIcon, ZoomOutIcon } = useIcons(); const cn = useCn(); + const t = useTranslations(); const containerRef = useRef(null); const contentRef = useRef(null); const [zoom, setZoom] = useState(initialZoom); @@ -167,36 +169,39 @@ export const PanZoom = ({ )} >
) : null} diff --git a/packages/streamdown/lib/translations-context.tsx b/packages/streamdown/lib/translations-context.tsx index fe11bc2d..ef857911 100644 --- a/packages/streamdown/lib/translations-context.tsx +++ b/packages/streamdown/lib/translations-context.tsx @@ -33,10 +33,13 @@ export interface StreamdownTranslations { mermaidFormatSvg: string; openExternalLink: string; openLink: string; + resetView: string; tableFormatCsv: string; tableFormatMarkdown: string; tableFormatTsv: string; viewFullscreen: string; + zoomIn: string; + zoomOut: string; } export const defaultTranslations: StreamdownTranslations = { @@ -53,6 +56,9 @@ export const defaultTranslations: StreamdownTranslations = { mermaidFormatSvg: "SVG", mermaidFormatPng: "PNG", mermaidFormatMmd: "MMD", + zoomIn: "Zoom in", + zoomOut: "Zoom out", + resetView: "Reset zoom and pan", // Table copyTable: "Copy table", copyTableAsMarkdown: "Copy table as Markdown",