Link
A link style with a clear underline, hover and a focus indicator. If the link should look like a button, use Button on the <a> element instead.
How to use it
Section titled “How to use it”Your claim has been filed. The terms that apply are in the small print, and we will write to you when the claim has been processed.
<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/link/link.css"><!-- Or everything in one file: https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.40.0/dist/lotek.css --><p>Your claim has been filed. The terms that apply are in<a class="lt-link" href="#">the small print</a>, and we will write to youwhen the claim has been processed.</p>import "@lo-tek/interfaces/tokens.css"import "@lo-tek/interfaces/link.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"
<a {...lt.link()} href="/small-print">Read the small print</a>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 the element is already there, set them on it. That is the way when you enhance HTML a server or a template has sent:
import { lt } from "@lo-tek/interfaces"
const link = document.querySelector<HTMLAnchorElement>("#payout-statement")const ready = await hasPayoutStatement() // the app's own check
lt.setAttributes(link, lt.link({ disabled: !ready }))if (ready) link?.setAttribute("href", "/payout-statement")else link?.removeAttribute("href")href belongs to the app, not the builder function, so you set and remove it yourself. If the payout statement becomes ready later, run the lines again. aria-disabled, role and tabindex are then removed, and the link works again. lt.link() manages all three, so a role or tabindex you set yourself on the same link is removed too. If the link needs them, set them after setAttributes.
// 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.filed() { p { +"Your claim has been filed. The terms that apply are in " a(href = "#") { lt(Lt.link()); +"the small print" } +", and we will write to you when the claim has been processed." }}Disabled link
Section titled “Disabled link”<a class="lt-link" href="#">Read the small print</a><a class="lt-link" role="link" tabindex="0" aria-disabled="true">See payout statement</a>A disabled link has no href. aria-disabled="true" mutes the colour and turns off the mouse with pointer-events: none, but the keyboard follows href with Enter regardless. That is why it has to go.
Without href an <a> is not a link to the screen reader, and it is not in the tab order. role="link" and tabindex="0" give it both back, so screen readers find it and can say that it is unavailable. lt.link({ disabled: true }) gives all three.
lotek check reports an lt-link or lt-button with both aria-disabled="true" and href (the rule disabled-with-href).
Classes you can style
Section titled “Classes you can style”| Class | What it is |
|---|---|
.lt-link | The link. Visited and disabled are told apart by :visited and aria-disabled. |
See Customising for how the layer works.
Accessibility
Section titled “Accessibility”- The link text should make sense read on its own. Screen readers can list every link on the page, and there “Read the terms of the policy” helps where “Click here” says nothing.
- Do not remove
outlineon:focus-visible. It is the only thing keyboard users navigate by. - If the link opens in a new tab, say so in the text or with
aria-label.