uid

elements man ui/behaviors/uid

uid(prefix) returns a page-unique id for aria wiring: aria-labelledby, aria-controls, aria-describedby. The server and the browser each count from their own start, and the browser re-runs private initializers when it attaches, so the ids a template renders agree on both sides. Hold one in a private attribute and render it where the aria needs it.

Signature
function uid(prefix?: string): string;
Argument Type Default What it does
prefix string "ui" The text before the counter: uid("menu") is "menu-1", then "menu-2".

An id is unique within one page load, not across loads, so it belongs in attributes and never in a URL or in storage.

In a template of your own

app/shared/templates/disclosure/index.ehtml
import { uid } from "@elements/ui/behaviors"; <Disclosure (summary: string, private open: boolean = false, private ids = { panel: uid("disclosure") })> <button type="button" aria-expanded={open ? "true" : "false"} aria-controls={ids.panel} onclick={() => open = !open}>{summary}</button> <div id={ids.panel} hidden={!open}><slot/></div> </Disclosure>

Used by

Nearly every template with aria wiring: Accordion (opens in a new tab), Calendar (opens in a new tab), Dialog (opens in a new tab), Field (opens in a new tab), Popover (opens in a new tab), Select (opens in a new tab), Tabs (opens in a new tab) and the rest.