Press / to search

    No results

    Search failed

    npm GitHub

    Elementals

    One page per element, and one question behind every one of them: what is the smallest element that deserves to exist? Each takes a chunk of ARIA, state and keyboard handling off your hands and does nothing else.

    Installing, the CDN bundles and the optional themes are on the home page.

    Where an APG pattern applies

    The pattern is the specification. Roles, states, focus order and keyboard handling follow it; anything the pattern does not cover is named on the element's own page.

    Element Pattern
    <accordion-elemental> APG Accordion, over native <details>
    <carousel-elemental> APG Carousel, on a scroll-snapping list โ€” the scroller is the state, so there is nothing to measure on resize
    <checkbox-group-elemental> APG Checkbox (Mixed-State), a select-all that shows the dash when it is some of them
    <combobox-elemental> APG Combobox, a <select> you can type your way down, one value or many
    <disclosure-elemental> APG Disclosure, where <details> cannot go
    <feed-elemental> APG Feed โ€” a stream of articles that keeps growing: the indices, the keys and the way out, with the fetching left to you and the scrolling bounded by a budget
    <menu-elemental> APG Menu Button, nested, and not a menu below a breakpoint
    <modal-elemental> APG Modal Dialog on native <dialog> โ€” nested, animated out, and dismissed the way the platform says
    <navbar-elemental> APG Disclosure Navigation, that folds itself away when the links stop fitting
    <segmented-elemental> APG Radio Group on native radios, drawn as a track with a knob that slides
    <slider-elemental> APG Slider on native range inputs, and Slider (Multi-Thumb) when you write two of them โ€” the thumb count is the markup
    <splitter-elemental> APG Window Splitter โ€” two panes and a draggable seam, keyboard included, for the one pattern the APG has never written an example for
    <suggest-elemental> APG Combobox with a listbox popup โ€” the results panel, minus any opinion about where the results came from
    <switch-elemental> APG Switch, for a setting that takes effect at once
    <tabs-elemental> APG Tabs, horizontal or vertical, written on a list of in-page links
    <toolbar-elemental> APG Toolbar โ€” a row of buttons the arrows walk and Tab passes in one step
    <tooltip-elemental> APG Tooltip as far as it has consensus โ€” a description on hover and focus, and a sentence on the page without script
    <tree-view-elemental> APG Tree View on a nested list of links โ€” one tab stop for the whole sidebar, and the arrows for the rest. The last pattern with no native equivalent at all

    Where none does

    No pattern is not a licence to invent one. These implement what WCAG and the platform ask for, and the page says which part of the APG is missing and why that is fine.

    Element What it is instead
    <copy-elemental> No APG pattern, because there is no widget โ€” a <button>, the clipboard write behind it, and the status message every copy button forgets
    <field-elemental> No APG pattern, because there is no widget โ€” the control is already accessible and the constraints already enforced, so this is only what the platform leaves undone after a refused submit: the bubble cancelled, the browser's own message in a paragraph, and the aria-describedby and aria-invalid that tie it to the field
    <marquee-elemental> No APG pattern, because nothing is operated โ€” a strip that loops, the copies counted against the container rather than guessed at, kept out of the keyboard's way and still under the pointer, and the stop button every other marquee leaves you to write
    <password-elemental> No APG pattern, because there is no widget โ€” a <button> beside an <input>, and the state neither of them carries: aria-pressed rather than a swapped name, a live region rather than a swapped icon, and the field masked again before the form is submitted
    <progress-elemental> No APG pattern, because <progress> already is one โ€” this adds the two things it has never had: where its fill ends, as something CSS can draw with, and a second value beside it for the part that is loaded but not played
    <rearrange-elemental> No APG pattern, because there is none for rearranging a list or a table body by hand โ€” the closest the APG has is its rearrangeable listbox example, and this takes the part that is not the listbox: buttons that move an item, focus that stays on the one that moved, and the live region saying where it landed. Dragging is the option on top, because WCAG 2.2 SC 2.5.7 asks for it that way round
    <search-elemental> No APG pattern, because the widget is next door โ€” the query half of a search field: the debounce, the abort, the loading state, and the status message a panel filling itself does not make
    <sortable-table-elemental> No APG pattern, because <table> already is one โ€” this adds only what the APG's own sortable table example describes: a button in the header, aria-sort on the column, and the caption note that explains them once instead of once per column
    <tilt-elemental> No APG pattern, because nothing is operated โ€” a card that leans under the pointer, layers that rise out of it, a glare that follows, and the reduced-motion switch every other tilt library animates straight through

    Not in the book

    More pages are being written, and three custom elements are published separately today. They keep their own packages, because this book does not break anyone's install to absorb them.

    Element What it is
    <media-player> A player over the <audio> or <video> you already wrote โ€” and you write the controls, in your markup, in the order you put them. npm i media-player-element
    <compare-images-slider> A before/after reveal: two layers, one clipped over the other, and a handle between them
    <code-preview> A code block that renders itself in an isolated iframe. It is what builds the live previews on these pages

    <media-player> is worth a look even if you never want a player, because its control bar is a <toolbar-elemental> with a <slider-elemental> scrubber inside it โ€” these elements composing into something bigger. The media player example builds that skeleton by hand so you can see what the composition costs; <media-player> is what it looks like finished.

    <compare-images-slider> is worth telling apart from <splitter-elemental>, because both put role="separator" on a handle you drag and they do opposite things. A splitter resizes two panes that share a width. The compare slider reveals: its two layers are both full size, one clipped over the other, and nothing on the page changes size at all. The before and after example fakes the second out of the first and says where that stops working.