A link in text: words, in a sentence or standing alone, that take the reader to another page or place, such as "Departures from Rejseplanen" or "Show all departures", underlined in the colour of the text around them.
When to use
Use Link for words that take the reader to another page or place, in a sentence or standing alone, such as "Departures from Rejseplanen".
| Use instead | When |
|---|---|
| LinkButton | The link stands apart, shaped like a button, such as "Back to the map" |
| Button | Pressing it runs an action on the screen it sits on |
Variants and states
| Rest | Hover | Pressed | Focus | |
|---|---|---|---|---|
| Default |
- Rest
- Hover
- Pressed
- Focus
Props
| Name | Type | Default | Description |
|---|---|---|---|
href | string | — | Where the link goes: a URL or a path. Give it on every Link, unless render gives a router's link that brings its own destination. |
children | ReactNode | — | The link's words, which name where it goes: "Rejseplanen", "Show all departures". Phrasing content only. Required in practice: a link with no words has no name. |
className | string | — | Reaches the root; className is merged after pn-Link. |
style | CSSProperties | — | Reaches the root; className is merged after pn-Link. |
ref | Ref<HTMLAnchorElement> | — | Reaches the root element. |
hrefstring, default —- Where the link goes: a URL or a path. Give it on every Link, unless
rendergives a router's link that brings its own destination. childrenReactNode, default —- The link's words, which name where it goes: "Rejseplanen", "Show all departures". Phrasing content only. Required in practice: a link with no words has no name.
classNamestring, default —- Reaches the root;
classNameis merged afterpn-Link. styleCSSProperties, default —- Reaches the root;
classNameis merged afterpn-Link. refRef<HTMLAnchorElement>, default —- Reaches the root element.
Use it
import { Link } from '@mylder/perron'Ask your agent
search_docs({ query: "Link" })Keyboard and ARIA
From the browser's native link and Base UI's useRender, which adds no behaviour. "From" says who does it. The Default story's play presses every key in this table.
| Key | Does | From |
|---|---|---|
Tab | Moves focus to the link, in document order | The browser |
Shift+Tab | Moves focus back out of the link, to the element before it | The browser |
Enter | Follows the link: fires onClick, then goes to href unless the click is prevented | The browser |
Space | Nothing to the link: Space scrolls the page, as on every link, and never follows it | The browser |
| Element | Role | Accessible name from | States announced |
|---|---|---|---|
root | link, native, from <a href> | Its text content, the caller's children; aria-label or aria-labelledby from the caller win | Visited, by the browser; aria-current when the caller sets it |
What axe won't catch, from the contract, each with how this component meets it:
- Everything the eye is told, the ear is told, for every shape each prop accepts: the underline tells the eye it is a link and the
linkrole tells the ear; its words are its name; its colour is the text's, so it tells nothing the text doesn't. - Every landmark and named region has an accessible name: none here; a link is neither.
- Every default label can be overridden: none here; Link owns no strings.
- Every shape the type accepts renders, in every variant:
childrenrenders a string, an element and a list alike, in everyState, alone or in running text, over one line or several. - A hidden copy kept for animation is
aria-hidden, and a collapsed region isinert: none here; Link keeps no hidden copy and collapses nothing. - Native semantics first: a native
<a href>, neverrole="button"and never Base UI'sButton(CR-1); arenderelement renders an<a>too. - Focus moves in reading order and returns on close: the link is one tab stop where it sits in the text, and opens nothing of its own to return from.
- Every target is at least
size.target-minsquare: Link adds no padding or minimum height of its own, so in running text it meets WCAG 2.2's target size (2.5.8) by its inline exception, and standing alone by its spacing exception, the caller giving itsize.target-minof room as Accessibility allows. Padding on an inline run would overlap the lines above and below it, and a minimum height doesn't apply to an inline box; a standalone link intypography.bodyis 21 px tall, undersize.target-min(24 px), so the room around it is the caller's, said in Do and don't. - Loops stop when the system asks for less motion: none here; Link has no loop and no transition.
Owned strings
No owned strings: every word comes from the caller, as children.
Link, like LinkButton, owns no "Opens in a new tab" string, draws no external-link icon and takes no external prop, leaving target and rel to the caller. Content design gives no rule on links or new tabs, so the answer LinkButton's spec gives stands for both: a link that leaves Mylder names its destination in its words ("Rejseplanen"), and Mylder's own links open in the same tab. A caller who opens a new tab passes target="_blank" with rel="noopener noreferrer", and both reach the <a> as they are. An owned string and icon can join later, as a new optional prop, without a break, and LinkButton would take the same.
Do and don't
For a caller using the component, with the reason. Each row is a rule: a must row's Don't is never right, a should row's needs a reason, and Checked by says what catches the Don't in a caller's code.
| Rule | Level | Do | Don't | Checked by |
|---|---|---|---|---|
| DD-1 | should | Use Link for a link in text, in a sentence or standing alone, and LinkButton for one shaped like a button | Put a LinkButton in running text: its height and padding break the line | review |
| DD-2 | must | Use Link when pressing it goes somewhere: another page, another place in the app, another site | Use Link to run an action, such as showing a line or closing a panel, with an onClick that prevents the link: that is a Button | review |
| DD-3 | must | Name where it goes, in the words of the sentence: "Departures from Rejseplanen", "Show all departures" | Write "Click here", "Read more" or a bare URL: the link's words are all a screen reader hears of it in a list of links (WCAG 2.2, 2.4.4 Link purpose) | review |
| DD-4 | must | Set the colour and type on the text around the link, and let Link take them | Recolour a Link in the brand yellow or a status colour on its own: brand is never a link (Intents), and the text's colour already carries any meaning | review |
| DD-5 | must | Give a standalone link size.target-min of room, such as a row of that height or a gap around it | Set a standalone link against another target, where a 21 px line leaves too small a mark to press | review |
| DD-6 | must | Give a router's link through render, such as render={<RouterLink to="/departures" />}, so the app's navigation runs | Wrap a Link in a router link, or a router link in a Link: two nested <a> elements are invalid and make two tab stops | review |
| DD-7 | must | Name a site the link leaves Mylder for, and keep Mylder's own links in the same tab | Open a new tab without saying where the link goes | review |
| DD-8 | must | Leave a link out when there is nowhere to go yet | Render a Link without href or render, or fake a disabled one with opacity: an <a> with no href is not a link, and disabled is a colour | review |