0.5.0 is the first element quality release, covering every A, B and C element. Components rebuild cleanly when moved or re-populated, keyboard and screen-reader access is fixed across the C components, and several XSS paths are closed. Themes gain a --btn-border-width hook,…
How to link a vocabulary concept inline so the popover enhancement and the glossary page both pick it up. First mention in , subsequent mentions plain.
Why this exists
The site has a single glossary generated from site/src/_data/vocabulary.json. When you mention one of those concepts in article prose, link to it. Two things light up:
The glossary page is the canonical anchor (every concept has id="term-{@id}"), so the link is always valid even without JS.
A small popover script (/js/definition-popover.js, generated at build) fetches /definitions.json on first interaction and shows the definition in a native popover anchored to the term. Modifier-clicks fall through to the glossary page.
The pattern
Three forms, depending on whether the mention is the first defining use, a subsequent reference, or an abbreviation.
First (defining) use — <dfn>
Wrap the link in <dfn>. The data-concept attribute carries the SKOS @id from vocabulary.json. The href deep-links to the term's anchor on the glossary page so the link is meaningful with no JS.
HTML
123
<p>We use <dfn><ahref="/glossary/#term-progressive-enhancement"data-concept="progressive-enhancement">progressive enhancement</a></dfn> to ensure content is available before scripts load.</p>
Subsequent uses — plain anchor
Plain anchor — no <dfn>. <dfn> marks the defining instance; using it on every mention would be wrong semantically and visually noisy.
HTML
123
<p>This <ahref="/glossary/#term-progressive-enhancement"data-concept="progressive-enhancement">progressive enhancement</a> approach also benefits search engine indexing.</p>
Abbreviated mentions — <abbr>
When you reference a concept by an abbreviation that lives in its skos:altLabel array, wrap the link in <abbr> with title set to the prefLabel. The title tooltip gives sighted hover-readers the expansion; the popover still triggers because the script queries a[data-concept] regardless of wrapper.
HTML
1234
<p>The<abbrtitle="Progressive Enhancement"><ahref="/glossary/#term-progressive-enhancement"data-concept="progressive-enhancement">PE</a></abbr> approach pairs well with semantic HTML.</p>
Use <dfn> exactly once per concept per page (the defining mention, regardless of label form). Subsequent mentions are either plain anchors (full label) or <abbr>-wrapped (altLabel/abbreviation).
Rules of thumb
Link the concept, not the word. Only link when you genuinely mean the vocabulary entry — not every casual use of the word "review" or "trust".
One <dfn> per concept per page. Subsequent mentions on the same page should be plain anchors.
Don't link inside a heading. Headings are navigation; the popover would fight with the heading-link affordance. Link from the body prose right after.
Don't link inside <code>, <pre>, or another <a>. Code samples carry their own typography contract; nested anchors are invalid HTML.
Don't link more than one or two terms per paragraph. The dotted-underline cue is helpful in moderation; turn into noise quickly.
Add the concept to the page's frontmatter. If the page is about the concept, list it in concepts: [...]. The meta-tag contract already emits <meta name="concept"> + <link rel="tag"> + <link rel="glossary"> automatically.
How to find the right @id
Open site/src/_data/vocabulary.json and search for the concept's pref-label. The @id is the slug-form (e.g. "meta-tag-contract", "data-provenance", "page-info"). The href is always /glossary/#term-{@id} — that's what the build emits and what the popover script expects.
If the concept isn't in the vocabulary yet but should be, add it to vocabulary.json first (see the SKOS shape used by sibling entries) and re-run npm run build. The glossary page, /definitions.json, and head metadata regenerate from that single source.
What the popover does (and doesn't)
Feature-detects the Popover API; on browsers without it, every link is a normal navigation to the glossary anchor. Same accessibility either way.
Caches /definitions.json in sessionStorage under vb:definitions. One fetch per browsing session.
Respects Cmd / Ctrl / Shift / Alt / middle-click — those open the glossary page like any other link.
Native popover handles Escape and light-dismiss. We don't reimplement focus management.
Auto-linking at build time
Cook ships an auto-link-glossary plugin that scans every docs prose page (/docs/concepts/, /docs/elements/, /docs/attributes/, /docs/patterns/, /docs/integrations/, /docs/recipes/, /docs/snippets/) and wraps vocabulary terms automatically. The manual pattern above still works — author-written mentions always win and suppress auto-linking of that concept anywhere in the page.
What it does
First occurrence of a concept's prefLabel wraps with <dfn><a data-concept="...">
First occurrence of an opted-in altLabel wraps with <abbr title="prefLabel"><a data-concept="...">
Subsequent occurrences get a bare <a data-concept="...">
Max one auto-link per <p> / <li> / <td> / <dd> to keep prose readable
A specific section where auto-linking would distract
Manual <a data-concept="..."> anywhere on the page
That one concept on this page
You want explicit control over where the concept links from
Per-concept opt-in via vocabulary.json
By default, prefLabel auto-links and altLabel does not. That keeps short common-word altLabels like “review”, “lens”, or “index” from generating noise. To opt a concept's altLabels in, add a vb:autoLink object: