Card
A frame around content that belongs together, such as one claim in a list of claims. The card is a container, not a component with behaviour: the content decides what the user can do.
How to use it
Section titled “How to use it”Runner's policy AV-2079-0233
Taken out 4 March. Premium EB 1,200 a month.
ActiveClaim AV-2079-0481
Claim denied. Black ICE is an act of God.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.40.0/src/tokens/tokens.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.40.0/src/components/css/card/card.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.40.0/src/components/css/badge/badge.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.40.0/src/components/css/button/button.css"><!-- Or everything in one file: https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.40.0/dist/lotek.css --><div class="lt-card"><h3 class="lt-card__title">Runner's policy AV-2079-0233</h3><p>Taken out 4 March. Premium EB 1,200 a month.</p><span class="lt-badge" data-color="success">Active</span></div>
<div class="lt-card" data-variant="filled"><h3 class="lt-card__title">Claim AV-2079-0481</h3><p>Claim denied. Black ICE is an act of God.</p><button class="lt-button" data-variant="secondary">Appeal the decision</button></div>import "@lo-tek/interfaces/tokens.css"import "@lo-tek/interfaces/card.css"import "@lo-tek/interfaces/badge.css"import "@lo-tek/interfaces/button.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"
<div {...lt.card({ variant: "outline" })}> <h3 className={lt.card.title}>Claim AV-2079-0477</h3> <p>In progress.</p></div>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 card = document.createElement("a")card.href = `/claims/${claim.id}`
lt.setAttributes(card, lt.card({ interactive: true }))lt.card.title gives the class for the heading. See Type-safe use.
// Once for the whole app, in the page template: every stylesheet, from the WebJar.head { link(rel = "stylesheet", href = LotekWebJar.CSS) }On a Kotlin or Java server, the same with kotlinx.html and lo-tek-kotlinx-html. The builder functions are in Lt, with an enum for each list of values:
import kotlinx.html.*import no.lotek.*import no.lotek.html.lt
fun FlowContent.policies() { div { lt(Lt.card()) h3 { lt(Lt.card.title); +"Runner's policy AV-2079-0233" } p { +"Taken out 4 March. Premium EB 1,200 a month." } span { lt(Lt.badge(color = BadgeColor.SUCCESS)); +"Active" } } div { lt(Lt.card(variant = SurfaceVariant.FILLED)) h3 { lt(Lt.card.title); +"Claim AV-2079-0481" } p { +"Claim denied. Black ICE is an act of God." } button { lt(Lt.button(variant = ButtonVariant.SECONDARY)); +"Appeal the decision" } }}data-variant | Used for |
|---|---|
| (omitted) | Outline on the page surface. The default. |
filled | Muted surface, when the card should stand out from white without a border |
The whole card as a link
Section titled “The whole card as a link”<a class="lt-card" data-interactive href="#"><h3 class="lt-card__title">See the whole claim</h3><p>All attachments, messages and the small print in one place.</p></a>data-interactive gives hover and a focus indicator, but makes nothing clickable on its own. The element has to be an <a> or a <button>. A <div> with a click listener can neither be reached with the keyboard nor be announced as something to press.
If the card has several actions, the whole card should not be a link. The buttons then end up inside a link, and the user cannot press them without navigating. Make one clear link in the heading instead.
Classes you can style
Section titled “Classes you can style”| Class | What it is |
|---|---|
.lt-card | The card itself. The variant comes from data-variant. |
.lt-card__title | The heading inside the card |
| Variable | Default |
|---|---|
--lt-card-padding | var(--lt-spacing-4) |
--lt-card-radius | var(--lt-spacing-2) |
An example. A card that carries a whole section can take more space than one in a list:
Default
The spacing that comes with the package.
Roomy
Same markup, one more class.
<div class="lt-card"><h3 class="lt-heading" data-size="s">Default</h3><p class="lt-paragraph">The spacing that comes with the package.</p></div>
<div class="lt-card roomy-card"><h3 class="lt-heading" data-size="s">Roomy</h3><p class="lt-paragraph">Same markup, one more class.</p></div>.roomy-card {--lt-card-padding: var(--lt-spacing-6);}See Customising for how the variables and the layer work.
Accessibility
Section titled “Accessibility”- The heading in the card should be a real heading element, at the right level for the page. The class sets the size, weight and line height, not the level.
- If the cards are a list, mark them up as a list with
<ul>and<li>. The screen reader then says how many there are and where in the list the user is. - Do not hide important information behind hover. It does not exist on a touch screen.
- The order in the markup is the order the keyboard follows. Moving something visually with CSS does not move focus.