@vakwerk/ui
v0.4.1
Published
Source-only Astro component package: the shared design system for the Vakwerk network of Dutch content sites.
Readme
@vakwerk/ui
Source-only Astro component package: the shared design system for the Vakwerk network of Dutch content sites.
Installation
Install @vakwerk/ui together with @vakwerk/tokens 0.3.0 or later (the peer range is >=0.3.0; pnpm only warns about a mismatch, and on tokens 0.2 numbers fall back to the surrounding font). Import @vakwerk/tokens/tokens.css (and optionally @vakwerk/tokens/dark.css) before the site's theme.css, then use the components.
Themeability rule
Components take colour and font only from semantic tokens. No hex, no rgb(/rgba(/hsl(/hsla(/oklch(/color(, no color-mix(/lab(/lch(/hwb(, no named colours used as values (white, black, red, …), no var(--color-(neutral|brand|accent)-N), and no font-family: unless the value is var(...) or inherit. transparent, currentColor and inherit are allowed. A themeability test in the package repository enforces this over every component.
Components
Import a component with import Name from '@vakwerk/ui/Name.astro'.
AnswerBlock: the direct answer to the page's question, a largevaluewith optionalunitandlabel; the default slot holds an explanation.ArticleMeta: trust line with optionalauthor,updatedandsource;labelsoverrides the Dutch defaults.Breadcrumbs: breadcrumb trail fromitems; the last item is the current page and is not linked.DataTable: accessible table from acaption,columnsandrows; columns can usealign: 'end'for numbers.FactList: label/value rows fromfacts, with optionaltitleandsource.PageHead: page heading with thetitleas h1; thebeforeslot sits above it (breadcrumbs) and the default slot below it (answer and meta line).RelatedLinks: row of related pages fromlinks, with an optionaltitle.SiteFooter: footer withsiteNameand trustlinks, plus optionalnoteandlabel.SiteHeader: header withsiteName,navand optionalsearch; collapses into a sheet on narrow screens.
RelatedLinks hideTitle
When the page already shows a heading above the links, hide the visible title. The <nav> keeps title as its accessible name.
<h3>Verwante landen</h3>
<RelatedLinks title="Verwante landen" hideTitle links={links} />FactList href
A fact with an href renders its value as a link; facts without one render plain text. All dd values use --font-family-numeric, so on a site with a distinct number font, text values such as "JP · JPN" get it too.
<FactList facts={[{ label: 'Landcode', value: 'JP · JPN', href: '/landcodes/#jpn' }]} />SiteHeader collapseBelow
The header collapses into a sheet below 48rem by default. A site with a longer nav sets collapseBelow="72rem" so the nav does not wrap. Only these two values exist because a media query cannot read var(); the choice is rendered as data-collapse-below.
<SiteHeader siteName="Voorbeeld" nav={nav} collapseBelow="72rem" />SiteHeader variant
variant="nav-row" is for a navigation too long to share a row with the logo, such as a list of categories. Logo and search stay on the top row at every width, and the navigation gets a full-width row of its own below them at body text size. On narrow screens that row scrolls sideways instead of collapsing into a sheet, so collapseBelow and menuId do nothing. The default, inline, is the header described above and renders no data-variant.
<SiteHeader siteName="Voorbeeld" nav={categories} search={{ href: '/zoeken', label: 'Zoeken' }} variant="nav-row" />SiteFooter groups and small print
groups renders link groups on rows below the trust links. Each group is a <nav> named by its label (no visible heading), and groups without links are omitted. The label is the landmark name, so it must be unique among the footer's navs. A default slot holds small print, rendered in .site-footer-small only when the slot has content.
<SiteFooter siteName="Voorbeeld" links={links} groups={[{ label: 'Rekentools', links: tools }]}>
© 2026 Voorbeeld
</SiteFooter>Footer links are at least 24px high (WCAG 2.5.8).
Theming
Sites theme the components through their theme.css, overriding --color-brand-solid, --color-brand-bg and --font-family. AnswerBlock, DataTable and FactList set their numbers in --font-family-numeric, which defaults to --font-family. A site with a separate number font overrides both on :root; overriding them on a deeper selector has no effect on the numeric alias, because it resolves where tokens.css declares it.
