# Link

> Link style for navigation in running text. A CSS component with one class and no JavaScript.

A link style with a clear underline, hover and a focus indicator. If the link should look like a button, use [Button](/components/button.md) on the `<a>` element instead.

## How to use it

**Plain HTML**

```html
<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 -->
```

```html
<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 you
when the claim has been processed.
</p>
```

**TypeScript**

```ts
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:

```tsx
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:

```ts
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`.

**kotlinx.html**

```kotlin
// 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:

```kotlin
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

**Plain HTML**

```html
<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

| Class | What it is |
| - | - |
| `.lt-link` | The link. Visited and disabled are told apart by `:visited` and `aria-disabled`. |

See [Customising](/customising.md) for how the layer works.

## 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 `outline` on `: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`.
