Vanilla Breeze

Vanilla Breeze v0.5.0 released

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,…

Read the release notes

author-index

Author-grouped view of site content. Reads pages.json and renders an accordion of authors with their pages listed underneath.

Overview

Reads pages.json via data-lens-src (or src) and groups pages by author. It adds a filter input, a live result count and per-author page counts. If the source request fails, any light-DOM markup you wrote inside the host stays in place and still gets the filter; if the host was empty, an error message is shown instead. See Fallback markup.

The demo loads a local fixture with several authors, shown twice: sorted alphabetically and with sort="count".

Attributes

AttributeTypeDefaultDescription
data-lens-srcstring—URL to pages.json or compatible source
srcstring—Alias for data-lens-src
placeholderstring"Filter authors…"Search input placeholder
sort"alpha" | "count""alpha"Group order for fetched data: alphabetical by author, or by page count (most first; ties alphabetical). Any other value falls back to alpha.
heading-level1–62Level of the generated Authors (N) heading. Set it to fit the page outline, for example 3 when the index sits under an <h2>.

Source contract

The component expects either a JSON array of records or an object with a pages array, where each record carries at minimum:

VB's Cook SSG plugin generate-pages-json emits this shape automatically.

Fallback markup

Light-DOM markup inside the host is the no-JS rendering, and it is never thrown away for nothing:

  • No src: nothing is fetched. The component keeps your markup and adds the filter input and live status.
  • src succeeds: the fetched data replaces the markup.
  • src fails (network error, non-2xx status, or invalid JSON): your markup stays and is enhanced exactly as if there were no src. An error message appears only if the host was empty.

Each group to be filtered must carry data-author-group. A group is hidden when its visible text does not contain the query. Matching ignores case and diacritics, so zoe finds Zoë. Native <details> elements keep the groups usable and keyboard-accessible without JavaScript.

Accessibility

  • Filter: a type="search" input whose accessible name is the placeholder text.
  • Result count: a polite live region (role="status") after the input announces results as you type, such as 2 of 5 authors match “zo” or Showing all 5 authors. It is visually hidden while there are results. When nothing matches, it becomes the visible No authors match … message.
  • Page counts: the visible (3) is aria-hidden. Screen readers hear real visually-hidden text instead (Ada Lovelace, 3 pages), because an aria-label on a generic <span> is ignored.
  • Heading: the generated heading defaults to <h2>. Use heading-level to keep the page outline correct.
  • Provenance colours use the VB status tokens (--color-success-text, --color-warning-text, --color-error-text), so they follow the theme and keep text contrast. The provenance word is always shown as text, so colour is never the only signal.

Ids and links

  • Group ids (author-<slug>) are stable link targets. The slug is the author name, NFKD-normalised, with diacritics stripped and lowercased. Letters and digits of any script are kept, so Zoë Ng becomes author-zoe-ng and 李明 becomes author-李明. A name with nothing usable left falls back to author. On a collision, either within one index or with an id already on the page (for example two indexes), the slug gets a -2, -3, … suffix. Ids are never empty and never shared.
  • Links from the source (url, authorUrl) are only rendered when they are http:, https: or relative. Values such as javascript: or data: are dropped. The page title is then shown as plain text, and the profile link is omitted.

Lifecycle

The fetch uses an AbortController that is aborted when the element is removed, so a detached index never renders late. Once the index is rendered, moving it in the DOM re-wires the filter without refetching or rebuilding.

↑