Tag
A tag labels content: topics on an article, chosen filters above a list. If the tag says what state something is in, such as “Approved” or “Overdue”, Badge is the right choice instead.
How to use it
Section titled “How to use it”<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.36.0/src/tokens/tokens.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.36.0/src/components/css/tag/tag.css"><!-- Or everything in one file: https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.36.0/dist/lotek.css --><span class="lt-tag">Housing benefit</span><span class="lt-tag" data-variant="filled">Nursery</span><span class="lt-tag" aria-disabled="true">Archived</span>import "@lo-tek/interfaces/tokens.css"import "@lo-tek/interfaces/tag.css"lt is used in two ways, and which one depends on whether you create the element or find it.
If you create the markup, spread the attributes in. That is the way in React, Astro and anything else that renders:
import { lt } from "@lo-tek/interfaces/react"
<span {...lt.tag()}>Housing benefit</span>The import is from /react here, since the block is JSX. From there the keys are className and htmlFor. In Astro and anything else without React, import @lo-tek/interfaces and you get class and for.
If you have the element in a variable, set them on it with setAttributes. That is the way without JSX, whether you just created the element or found it in a page the server sent:
import { lt } from "@lo-tek/interfaces"
const tag = document.createElement("button")tag.type = "button"
lt.setAttributes(tag, lt.tag({ selectable: true }))tag.setAttribute("aria-pressed", "false")data-variant | Used for |
|---|---|
| (omitted) | Outline. The default. |
filled | Muted surface, when the tags sit on a light surface |
Filters that can be toggled
Section titled “Filters that can be toggled”Three filters above a list of cases. “Approved” is selected, the other two are not, and aria-pressed says which is which:
Show cases with status
<h3 class="lt-heading" data-size="xs" id="filters">Show cases with status</h3>
<div role="group" aria-labelledby="filters"><button class="lt-tag" data-selectable aria-pressed="true" type="button">Approved</button><button class="lt-tag" data-selectable aria-pressed="false" type="button">In progress</button><button class="lt-tag" data-selectable aria-pressed="false" type="button">Rejected</button></div><div role="group"> with a label is what ties the three together. Without it they are three loose buttons, and someone listening to the page does not know they belong to the same question.
data-selectable gives hover and a focus indicator. The element has to be a <button>, and you set aria-pressed yourself:
<script type="module"> for (const tag of document.querySelectorAll(".lt-tag[data-selectable]")) { tag.addEventListener("click", () => { const selected = tag.getAttribute("aria-pressed") === "true" tag.setAttribute("aria-pressed", String(!selected)) }) }</script>aria-pressed is what makes the screen reader say “pressed” or “not pressed”. Colour alone says nothing.
Classes you can style
Section titled “Classes you can style”| Class | What it is |
|---|---|
.lt-tag | The tag. The variant comes from data-variant. |
| Variable | Default |
|---|---|
--lt-tag-padding | var(--lt-spacing-0-5) var(--lt-spacing-2) |
--lt-tag-radius | var(--lt-spacing-1) |
See Customising for how the variables and the layer work.
Accessibility
Section titled “Accessibility”- A tag that cannot be pressed should not look as if it can. Use
data-selectableonly on real buttons. - If you have many filters, put them in a list with a heading that says what they filter.
- If the tag should be removable, make a separate button inside it with text that says what is removed: “Remove the Approved filter”, not just a cross.