Components
Things to build with. Each has a main class, classes for its parts, and classes for its variations. They draw everything from the tokens, so they follow the theme, the Appearance page and the density.
- Button
- Form field
- Inputs, dropdowns and text areas
- Input group
- Checkboxes, radios and toggles
- Card
- Card list and grid list
- Table
- Badge
- Callout
- Toolbar
- Description list
- Empty state
Button
An action: a <button>, an <a> or an <input type="submit">. A secondary button by default.
| Class | What it does |
|---|---|
fz-btn | A secondary button. |
fz-btn-- | The main action. Usually one per area. |
fz-btn-- | A destructive action, such as delete. |
fz-btn-- | No border or background until hovered, for less important actions. |
fz-btn-- | Smaller or larger. |
fz-btn-- | Square, for an icon on its own. Give it an aria-label. |
fz-btn-- | The full width of its container. |
- Use a
<button>for an action on the page and an<a>for going somewhere else; they look the same. - A disabled button, or one with
aria-disabled="true", is faded.
Example
<div class="fz-cluster">
<button type="button" class="fz-btn fz-btn--primary">Save</button>
<button type="button" class="fz-btn">Cancel</button>
<a href="#" class="fz-btn fz-btn--ghost">View history</a>
<button type="button" class="fz-btn fz-btn--danger">Delete</button>
<button type="button" class="fz-btn fz-btn--sm">Small</button>
<button type="button" class="fz-btn fz-btn--lg">Large</button>
<button type="button" class="fz-btn fz-btn--icon" aria-label="Settings">⚙</button>
<button type="button" class="fz-btn" disabled>Disabled</button>
</div>Form field
A label, a control and its help text.
| Class | What it does |
|---|---|
fz-field | The field: its label above its control. |
fz-field__ | The label: a <label for="…">, or a <legend> on a <fieldset>. |
fz-field__ | The required marker, inside the label. |
fz-field__ | The control and its help text. |
fz-field__ | Help text, or an error message. |
fz-field-- | The label beside the control, stacking when there isn't room. |
- For a group of choices, use
fz-fieldon a<fieldset>, with a<legend class="fz-field__label">. - Connect help text to its control with aria-describedby, so screen readers read it too.
Example
<div class="fz-stack">
<div class="fz-field">
<label class="fz-field__label" for="sg-name">Student name <span class="fz-field__req" aria-hidden="true">*</span></label>
<div class="fz-field__body">
<input class="fz-input" id="sg-name" required aria-describedby="sg-name-help">
<p class="fz-field__help" id="sg-name-help">As it appears on the student's report card.</p>
</div>
</div>
<div class="fz-field fz-field--horizontal">
<label class="fz-field__label" for="sg-school">School</label>
<div class="fz-field__body"><input class="fz-input" id="sg-school"></div>
</div>
</div>Inputs, dropdowns and text areas
Text-like inputs, dropdowns and text areas, sharing one look. Their height follows the density.
| Class | What it does |
|---|---|
fz-input | An <input>: text, email, number, date and the like. |
fz-select | A <select>, with its own chevron. |
fz-textarea | A <textarea>, several lines, taller when dragged. |
aria-invalid="true"marks a control as invalid. Say what is wrong in the field's help text too, since the colour alone doesn't.
Example
<div class="fz-auto-grid fz-auto-grid--max-2 fz-auto-grid--wide">
<input class="fz-input" placeholder="A text input" aria-label="A text input">
<select class="fz-select" aria-label="A dropdown"><option>Grade 6</option><option>Grade 7</option></select>
<input class="fz-input" value="not-an-email" aria-invalid="true" aria-label="An invalid input">
<input class="fz-input" value="Disabled" disabled aria-label="A disabled input">
<textarea class="fz-textarea" placeholder="A text area" aria-label="A text area"></textarea>
</div>Input group
An input with text or an icon attached before or after it, such as a currency or a unit.
| Class | What it does |
|---|---|
fz-input-group | Wraps an fz-input and its add-ons. |
fz-input-group__ | The attached text or icon. |
Example
<div class="fz-input-group" style="max-width: 20rem">
<span class="fz-input-group__addon">$</span>
<input class="fz-input" inputmode="decimal" value="120.00" aria-label="Program fee">
<span class="fz-input-group__addon">CAD</span>
</div>Checkboxes, radios and toggles
Real checkboxes and radio buttons, drawn in the theme's colours; a toggle is a checkbox drawn as an on/off switch.
| Class | What it does |
|---|---|
fz-checkbox | An <input type="checkbox">. |
fz-radio | An <input type="radio">. |
fz-toggle | An <input type="checkbox"> drawn as a switch. |
fz-choice | A <label> around a checkbox, radio or toggle and its text, all of it clickable. |
fz-choice-group | A set of choices, one below the other. |
Example
<div class="fz-switcher">
<fieldset class="fz-field">
<legend class="fz-field__label">Transportation</legend>
<div class="fz-choice-group">
<label class="fz-choice"><input type="radio" class="fz-radio" name="sg-t" checked> Bus</label>
<label class="fz-choice"><input type="radio" class="fz-radio" name="sg-t"> Picked up by a parent</label>
</div>
</fieldset>
<div class="fz-choice-group">
<label class="fz-choice"><input type="checkbox" class="fz-checkbox" checked> Photo consent</label>
<label class="fz-choice"><input type="checkbox" class="fz-toggle" checked> Email updates</label>
</div>
</div>Card
A surface for one thing: an entry, a summary, a group of fields. Its children are stacked 3 steps apart.
| Class | What it does |
|---|---|
fz-card | The card. |
fz-card__ | A row for the title and any actions, wrapping when out of room. |
fz-card__ | The title, on a heading that fits the page (h2, h3…). |
fz-card__ | A line of secondary text under the title. |
fz-card__ | A row at the bottom, separated by a line. |
fz-card-- | No padding: for a table or an image that should reach the edges. |
fz-card-- | The whole card is clickable, through its fz-card__link. |
fz-card__ | The one link the whole card clicks through to: on the link, or on an element around it when the link is generated for you, such as by viewEntryLink() in a list template. |
- In an interactive card, other links and buttons still work on their own.
Example
<div class="fz-auto-grid fz-auto-grid--max-2 fz-auto-grid--wide">
<article class="fz-card">
<div class="fz-card__header">
<div><h3 class="fz-card__title">Robotics club</h3><p class="fz-card__subtitle">Thursdays, 3:30 to 5pm</p></div>
<span class="fz-badge fz-badge--success">Open</span>
</div>
<p>An after-school program for students in grades 6 to 8.</p>
<div class="fz-card__footer"><span class="fz-text-muted fz-text-sm">18 of 24 places taken</span><button type="button" class="fz-btn fz-btn--sm fz-ms-auto">Register</button></div>
</article>
<article class="fz-card fz-card--interactive">
<h3 class="fz-card__title"><a href="#" class="fz-card__link">Coding camp</a></h3>
<p class="fz-text-muted">The whole card is a link.</p>
<div class="fz-cluster"><span class="fz-badge fz-badge--warning">Waitlist</span></div>
</article>
</div>Card list and grid list
A list of entries shown as cards instead of table rows: one below the other, or in columns.
| Class | What it does |
|---|---|
fz-card-list | On a <ul> or <ol>: cards one below the other. |
fz-grid-list | On a <ul> or <ol>: cards in columns, like fz-auto-grid. |
fz-grid-list-- | At most this many columns. |
fz-grid-list-- | Columns as narrow as 8rem, or at least 18rem. |
- Give each
<li>thefz-cardclass.
Example
<ul class="fz-grid-list fz-grid-list--max-3">
<li class="fz-card fz-card--interactive"><h3 class="fz-card__title fz-card__link"><a href="#">Amira Haddad</a></h3><div class="fz-cluster"><span class="fz-badge fz-badge--success">Approved</span><span class="fz-badge">Grade 7</span></div></li>
<li class="fz-card fz-card--interactive"><h3 class="fz-card__title fz-card__link"><a href="#">Liam Chen</a></h3><div class="fz-cluster"><span class="fz-badge fz-badge--warning">Under review</span><span class="fz-badge">Grade 8</span></div></li>
<li class="fz-card fz-card--interactive"><h3 class="fz-card__title fz-card__link"><a href="#">Sofia Rossi</a></h3><div class="fz-cluster"><span class="fz-badge fz-badge--info">Submitted</span><span class="fz-badge">Grade 6</span></div></li>
</ul>Table
A plain data table: a header row, a line under each row, and rows the row height, which follows the density.
| Class | What it does |
|---|---|
fz-table | On a <table>. |
fz-table-- | Every other row shaded. |
- For a table wider than its container, wrap it in an element with
fz-overflow-x-auto.
Example
<div class="fz-card fz-card--flush fz-overflow-x-auto">
<table class="fz-table">
<thead><tr><th>Student</th><th>School</th><th class="fz-text-end">Grade</th><th>Status</th></tr></thead>
<tbody>
<tr><td>Amira Haddad</td><td>Riverside Public School</td><td class="fz-text-end fz-tabular-nums">7</td><td><span class="fz-badge fz-badge--success">Approved</span></td></tr>
<tr><td>Liam Chen</td><td>Lakeview Middle School</td><td class="fz-text-end fz-tabular-nums">8</td><td><span class="fz-badge fz-badge--warning">Under review</span></td></tr>
</tbody>
</table>
</div>Badge
A short label: a status, a category, a count.
| Class | What it does |
|---|---|
fz-badge | A neutral badge, with a grey dot. |
fz-badge-- | A coloured tint and dot. |
fz-badge-- | No dot. |
- The colour is in the tint and the dot; the text stays the normal text colour, so it is readable in every theme. The word should say what the status is: don't rely on the colour alone.
Example
<div class="fz-cluster">
<span class="fz-badge">Draft</span>
<span class="fz-badge fz-badge--info">Submitted</span>
<span class="fz-badge fz-badge--warning">Under review</span>
<span class="fz-badge fz-badge--success">Approved</span>
<span class="fz-badge fz-badge--danger">Rejected</span>
<span class="fz-badge fz-badge--accent fz-badge--plain">12 new</span>
</div>Callout
A message set apart from the content around it: instructions, a warning, the result of an action.
| Class | What it does |
|---|---|
fz-callout | A callout, in the accent colour. |
fz-callout-- | A status callout. |
fz-callout__ | A bold first line. |
- Add
role="status"to a callout that appears because of something the user just did, so screen readers announce it.
Example
<div class="fz-stack fz-gap-3">
<div class="fz-callout"><p class="fz-callout__title">Before you start</p><p>Have your student number and your school's address ready.</p></div>
<div class="fz-callout fz-callout--success" role="status"><p>Your application was submitted.</p></div>
<div class="fz-callout fz-callout--warning"><p>This entry has not been reviewed yet.</p></div>
<div class="fz-callout fz-callout--danger"><p>The due date has passed.</p></div>
</div>Toolbar
A row with a group at each end, such as a heading and its buttons, wrapping when it runs out of room.
| Class | What it does |
|---|---|
fz-toolbar | The row. |
fz-toolbar__ | The group at the start. |
fz-toolbar__ | The group at the end. |
Example
<div class="fz-toolbar">
<div class="fz-toolbar__start"><h2 class="fz-text-xl fz-font-semibold">Applications</h2><span class="fz-badge fz-badge--plain">48</span></div>
<div class="fz-toolbar__end"><button type="button" class="fz-btn">Export</button><button type="button" class="fz-btn fz-btn--primary">New application</button></div>
</div>Description list
Labelled values, such as an entry's fields in a card. On a <dl>; each <dt> and <dd> pair may be wrapped in a <div>.
| Class | What it does |
|---|---|
fz-dl | Terms and values side by side. |
fz-dl-- | Each term above its value. |
Example
<div class="fz-switcher">
<dl class="fz-dl">
<dt>Student</dt><dd>Amira Haddad</dd>
<dt>School</dt><dd>Riverside Public School</dd>
<dt>Grade</dt><dd>7</dd>
</dl>
<dl class="fz-dl fz-dl--stacked">
<div><dt>Submitted</dt><dd>September 12, 2026</dd></div>
<div><dt>Status</dt><dd><span class="fz-badge fz-badge--success">Approved</span></dd></div>
</dl>
</div>Empty state
What to show where there is nothing to show yet, and what to do about it.
| Class | What it does |
|---|---|
fz-empty | A centred, outlined area. |
fz-empty__ | Its heading. |
Example
<div class="fz-empty">
<p class="fz-empty__title">No applications yet</p>
<p>They will appear here once students start submitting them.</p>
<button type="button" class="fz-btn fz-btn--primary">Share the form</button>
</div>