import * as React from "react"; import { useHotkeys } from "react-hotkeys-hook"; import config from "../get-config"; import { watchers } from "../story-hmr"; import { A11y } from "../icons"; import { Modal, Code } from "../ui"; import type { AddonProps } from "../../../shared/types"; type ViolationT = { id: string; impact: string; description: string; help: string; helpUrl: string; nodes: { html: string }[]; }; type ViolationsT = ViolationT[]; const runAxe = async ( setViolations: React.Dispatch>, setReportFinished: React.Dispatch>, el: HTMLElement | null, ) => { const axe = await import("axe-core"); try { const results = await axe.default.run( document.getElementsByTagName("main") as any, ); setViolations(results.violations as ViolationsT); setReportFinished(true); if (el) el.setAttribute("aria-hidden", "true"); } catch (e) {} }; const Violation = ({ violation }: { violation: ViolationT }) => { const [more, setMore] = React.useState(false); return (
  • {violation.help} ({violation.nodes.length}).{" "} {!more ? ( setMore(true)}> Show details ) : ( <>
    • ID: {violation.id}
    • Impact: {violation.impact}
    • Description: {violation.description}
    • Documentation

    Violating nodes:

      {violation.nodes.map((node) => (
    • {node.html}
    • ))}

    setMore(false)}> Hide details

    )}
  • ); }; const AxeReport = ({ reportFinished, violations, }: { reportFinished: boolean; violations: ViolationsT; }) => { if (!reportFinished) return

    Report is loading...

    ; if (violations.length === 0) { return (

    There are no axe{" "} accessibility violations. Good job!

    ); } return ( <>

    There are {violations.length}{" "} axe accessibility violations

    ); }; export const Button = ({ globalState }: AddonProps) => { const [showReport, setShowReport] = React.useState(false); const [reportFinished, setReportFinished] = React.useState(false); const [violations, setViolations] = React.useState([]); React.useEffect(() => { // re-run Axe on HMR updates, some timeout is needed to let the DOM settle watchers.push(() => { setTimeout(() => { const el = document.getElementById("ladle-root") as HTMLElement; // Addon Dialog aria hides the rest of page, we need to temporarily // make it visible for Axe function properly el.removeAttribute("aria-hidden"); runAxe(setViolations, setReportFinished, el).catch(console.error); }, 50); }); }, []); const text = "Show accessibility report."; const openReport = () => { runAxe(setViolations, setReportFinished, null).catch(console.error); // We give 100ms for axe to finish before displaying "Loading..." // inside of the dialog. Makes the UI transition to less jarring. setTimeout(() => setShowReport(!showReport), 100); }; useHotkeys( config.hotkeys.a11y, () => (showReport ? setShowReport(false) : openReport()), { enabled: globalState.hotkeys && config.addons.a11y.enabled, }, ); return (
  • ); };