diff --git a/doc/rule-descriptions.md b/doc/rule-descriptions.md index 734d73b36b..319108744c 100644 --- a/doc/rule-descriptions.md +++ b/doc/rule-descriptions.md @@ -69,6 +69,7 @@ | [scrollable-region-focusable](https://dequeuniversity.com/rules/axe/4.9/scrollable-region-focusable?application=RuleDescription) | Ensure elements that have scrollable content are accessible by keyboard | Serious | cat.keyboard, wcag2a, wcag211, wcag213, TTv5, TT4.a, EN-301-549, EN-9.2.1.1, EN-9.2.1.3 | failure | [0ssw9k](https://act-rules.github.io/rules/0ssw9k) | | [select-name](https://dequeuniversity.com/rules/axe/4.9/select-name?application=RuleDescription) | Ensures select element has an accessible name | Critical | cat.forms, wcag2a, wcag412, section508, section508.22.n, TTv5, TT5.c, EN-301-549, EN-9.4.1.2, ACT | failure, needs review | [e086e5](https://act-rules.github.io/rules/e086e5) | | [server-side-image-map](https://dequeuniversity.com/rules/axe/4.9/server-side-image-map?application=RuleDescription) | Ensures that server-side image maps are not used | Minor | cat.text-alternatives, wcag2a, wcag211, section508, section508.22.f, TTv5, TT4.a, EN-301-549, EN-9.2.1.1 | needs review | | +| [summary-name](https://dequeuniversity.com/rules/axe/4.9/summary-name?application=RuleDescription) | Ensures summary elements have discernible text | Serious | cat.name-role-value, wcag2a, wcag412, section508, section508.22.a, TTv5, TT6.a, EN-301-549, EN-9.4.1.2 | failure, needs review | | | [svg-img-alt](https://dequeuniversity.com/rules/axe/4.9/svg-img-alt?application=RuleDescription) | Ensures <svg> elements with an img, graphics-document or graphics-symbol role have an accessible text | Serious | cat.text-alternatives, wcag2a, wcag111, section508, section508.22.a, TTv5, TT7.a, EN-301-549, EN-9.1.1.1, ACT | failure, needs review | [7d6734](https://act-rules.github.io/rules/7d6734) | | [td-headers-attr](https://dequeuniversity.com/rules/axe/4.9/td-headers-attr?application=RuleDescription) | Ensure that each cell in a table that uses the headers attribute refers only to other cells in that table | Serious | cat.tables, wcag2a, wcag131, section508, section508.22.g, TTv5, TT14.b, EN-301-549, EN-9.1.3.1 | failure, needs review | [a25f45](https://act-rules.github.io/rules/a25f45) | | [th-has-data-cells](https://dequeuniversity.com/rules/axe/4.9/th-has-data-cells?application=RuleDescription) | Ensure that <th> elements and elements with role=columnheader/rowheader have data cells they describe | Serious | cat.tables, wcag2a, wcag131, section508, section508.22.g, TTv5, TT14.b, EN-301-549, EN-9.1.3.1 | failure, needs review | [d0f69e](https://act-rules.github.io/rules/d0f69e) | diff --git a/lib/rules/summary-interactive-matches.js b/lib/rules/summary-interactive-matches.js new file mode 100644 index 0000000000..883dd51e9c --- /dev/null +++ b/lib/rules/summary-interactive-matches.js @@ -0,0 +1,22 @@ +export default function summaryIsInteractiveMatches(_, virtualNode) { + // Summary only interactive if its real DOM parent is a details element + const parent = virtualNode.parent; + if (parent.props.nodeName !== 'details' || isSlottedElm(virtualNode)) { + return false; + } + // Only the first summary element is interactive + const firstSummary = parent.children.find( + child => child.props.nodeName === 'summary' + ); + if (firstSummary !== virtualNode) { + return false; + } + return true; +} + +function isSlottedElm(vNode) { + // Normally this wouldn't be enough, but since we know parent is a details + // element, we can ignore edge cases like slot being the real parent + const domParent = vNode.actualNode?.parentElement; + return domParent && domParent !== vNode.parent.actualNode; +} diff --git a/lib/rules/summary-name.json b/lib/rules/summary-name.json new file mode 100644 index 0000000000..349d9c2977 --- /dev/null +++ b/lib/rules/summary-name.json @@ -0,0 +1,29 @@ +{ + "id": "summary-name", + "impact": "serious", + "selector": "summary", + "matches": "summary-interactive-matches", + "tags": [ + "cat.name-role-value", + "wcag2a", + "wcag412", + "section508", + "section508.22.a", + "TTv5", + "TT6.a", + "EN-301-549", + "EN-9.4.1.2" + ], + "metadata": { + "description": "Ensures summary elements have discernible text", + "help": "Summary elements must have discernible text" + }, + "all": [], + "any": [ + "has-visible-text", + "aria-label", + "aria-labelledby", + "non-empty-title" + ], + "none": [] +} diff --git a/locales/_template.json b/locales/_template.json index 63b6f1d3b6..52ad9a16e1 100644 --- a/locales/_template.json +++ b/locales/_template.json @@ -373,6 +373,10 @@ "description": "Ensure all skip links have a focusable target", "help": "The skip-link target should exist and be focusable" }, + "summary-name": { + "description": "Ensures summary elements have discernible text", + "help": "Summary elements must have discernible text" + }, "svg-img-alt": { "description": "Ensures elements with an img, graphics-document or graphics-symbol role have an accessible text", "help": " elements with an img role must have an alternative text" diff --git a/test/integration/full/all-rules/all-rules.html b/test/integration/full/all-rules/all-rules.html index fc982c3fb5..8066cb00a4 100644 --- a/test/integration/full/all-rules/all-rules.html +++ b/test/integration/full/all-rules/all-rules.html @@ -129,6 +129,10 @@

Ok

  • Hello
  • World
  • +
    + pass +

    Hello world

    +
    Large scroll area
    diff --git a/test/integration/full/isolated-env/isolated-env.html b/test/integration/full/isolated-env/isolated-env.html index 74c794e1bf..c9c60b5650 100644 --- a/test/integration/full/isolated-env/isolated-env.html +++ b/test/integration/full/isolated-env/isolated-env.html @@ -103,6 +103,10 @@

    Ok

    +
    + Hello world +

    Some text

    +