# 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.36.0/src/tokens/tokens.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.36.0/src/components/css/link/link.css">
<!-- Or everything in one file: https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.36.0/dist/lotek.css -->
```

```html
<p>
Your application has been sent. You will find it under
<a class="lt-link" href="#">My applications</a>, and we will send you an
email when it 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="/receipt">See receipt</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>("#tax-statement")
const ready = await hasTaxStatement() // the app's own check


lt.setAttributes(link, lt.link({ disabled: !ready }))
if (ready) link?.setAttribute("href", "/tax-statement")
else link?.removeAttribute("href")
```

`href` belongs to the app, not the builder function, so you set and remove it yourself. If the tax 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`.

## Disabled link

**Plain HTML**

```html
<a class="lt-link" href="#">See receipt</a>
<a class="lt-link" role="link" tabindex="0" aria-disabled="true">See tax 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 “See the invoice for March” 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`.
