Created
July 3, 2025 02:02
-
-
Save tak-dcxi/3e57bbeb3277d7d283370bc1705d4ea4 to your computer and use it in GitHub Desktop.
ResponsiveTable
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Add ARIA attributes to table elements and their children. | |
| * When the display property is changed with CSS, the element may not be recognized as a table. | |
| * @see https://adrianroselli.com/2018/05/functions-to-add-aria-to-tables-and-lists.html | |
| * @param {HTMLElement} container - Container element to apply ARIA attributes to | |
| * @returns {void} | |
| */ | |
| function addTableARIA(container: HTMLElement): void { | |
| const tables = container.querySelectorAll<HTMLTableElement>("table"); | |
| for (const table of tables) { | |
| table.setAttribute("role", "table"); | |
| const caption = table.querySelector("caption"); | |
| if (caption) { | |
| caption.setAttribute("role", "caption"); | |
| } | |
| const rowGroups = table.querySelectorAll<HTMLElement>( | |
| "thead, tbody, tfoot" | |
| ); | |
| for (const rowGroup of rowGroups) { | |
| rowGroup.setAttribute("role", "rowgroup"); | |
| } | |
| const rows = table.querySelectorAll<HTMLTableRowElement>("tr"); | |
| for (const row of rows) { | |
| row.setAttribute("role", "row"); | |
| const cells = row.querySelectorAll<HTMLTableCellElement>("td"); | |
| for (const cell of cells) { | |
| cell.setAttribute("role", "cell"); | |
| } | |
| const headers = row.querySelectorAll<HTMLTableCellElement>("th"); | |
| for (const header of headers) { | |
| header.setAttribute( | |
| "role", | |
| header.getAttribute("scope") === "row" ? "rowheader" : "columnheader" | |
| ); | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| * Custom element to preserve table semantics | |
| * Maintains accessibility even when display property is changed with CSS | |
| */ | |
| export class ResponsiveTable extends HTMLElement { | |
| /** @private */ | |
| private observer: MutationObserver | null = null; | |
| constructor() { | |
| super(); | |
| } | |
| /** | |
| * Called when the element is added to the document | |
| * Sets up initial ARIA attributes and mutation observer | |
| * @returns {void} | |
| */ | |
| connectedCallback(): void { | |
| // Initial ARIA attribute addition | |
| this.applyARIA(); | |
| // MutationObserver to handle dynamically added elements | |
| this.observer = new MutationObserver(() => { | |
| this.applyARIA(); | |
| }); | |
| this.observer.observe(this, { | |
| childList: true, | |
| subtree: true | |
| }); | |
| } | |
| /** | |
| * Called when the element is removed from the document | |
| * Cleans up the mutation observer | |
| * @returns {void} | |
| */ | |
| disconnectedCallback(): void { | |
| if (this.observer) { | |
| this.observer.disconnect(); | |
| this.observer = null; | |
| } | |
| } | |
| /** | |
| * Apply ARIA attributes to table elements within this custom element | |
| * @private | |
| * @returns {void} | |
| */ | |
| private applyARIA(): void { | |
| addTableARIA(this); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment