diff --git a/.changeset/healthy-jobs-act.md b/.changeset/healthy-jobs-act.md
new file mode 100644
index 00000000..90f89ded
--- /dev/null
+++ b/.changeset/healthy-jobs-act.md
@@ -0,0 +1,5 @@
+---
+"dom-accessibility-api": patch
+---
+
+Dynamically calculates the aria role for
elements instead of always returning 'columnheader'
diff --git a/sources/__tests__/getRole.js b/sources/__tests__/getRole.js
index cb5b958d..3f6a5535 100644
--- a/sources/__tests__/getRole.js
+++ b/sources/__tests__/getRole.js
@@ -168,7 +168,13 @@ const cases = [
["title", null, createElementFactory("title", {})],
// WARNING: Only in certain contexts
["td", "cell", createElementFactory("td", {})],
- ["th", "columnheader", createElementFactory("th", {})],
+ // default scope=auto
+ ["th missing scope", "columnheader", createElementFactory("th", {})],
+ ["th scope explicitly set to `auto`", "columnheader", createElementFactory("th", {scope:"auto"})],
+ ["th scope=col", "columnheader", createElementFactory("th", {scope:"col"})],
+ ["th scope=colgroup", "columnheader", createElementFactory("th", {scope:"colgroup"})],
+ ["th scope=row", "rowheader", createElementFactory("th", {scope:"row"})],
+ ["th scope=rowgroup", "rowheader", createElementFactory("th", {scope:"rowgroup"})],
["tr", "row", createElementFactory("tr", {})],
["track", null, createElementFactory("track", {})],
["ul", "list", createElementFactory("ul", {})],
@@ -182,7 +188,7 @@ const cases = [
["presentational with prohibited aria attributes", null, createElementFactory("div", {'aria-label': "hello", role: "none"})],
];
-it.each(cases)("%s has the role %s", (name, role, elementFactory) => {
+it.each(cases)("%s has the role %s", (_name, role, elementFactory) => {
const element = elementFactory();
expect(getRole(element)).toEqual(role);
diff --git a/sources/getRole.ts b/sources/getRole.ts
index 14096a97..53f79276 100644
--- a/sources/getRole.ts
+++ b/sources/getRole.ts
@@ -59,7 +59,6 @@ const localNameToRoleMappings: Record = {
tfoot: "rowgroup",
// WARNING: Only in certain context
td: "cell",
- th: "columnheader",
thead: "rowgroup",
tr: "row",
ul: "list",
@@ -143,12 +142,13 @@ export default function getRole(element: Element): string | null {
}
function getImplicitRole(element: Element): string | null {
- const mappedByTag = localNameToRoleMappings[getLocalName(element)];
+ const elName = getLocalName(element);
+ const mappedByTag = localNameToRoleMappings[elName];
if (mappedByTag !== undefined) {
return mappedByTag;
}
- switch (getLocalName(element)) {
+ switch (elName) {
case "a":
case "area":
case "link":
@@ -205,6 +205,17 @@ function getImplicitRole(element: Element): string | null {
return "listbox";
}
return "combobox";
+ case "th":
+ switch (element.getAttribute("scope")) {
+ case "row":
+ case "rowgroup":
+ return "rowheader";
+ case "col":
+ case "colgroup":
+ case "auto":
+ default:
+ return "columnheader";
+ }
}
return null;
}
|