Skip to the content

Kongens Nytorv

Metro M1, M2 and M3.

Variants and states

Sizes

Mediumsize.button · 36 px
Smallsize.button-sm · 30 px

With icons

An icon before the label, in reading order, so it moves to the right in right-to-left text. Hidden from screen readers: the label names the link.

Props

NameTypeDefaultDescription
hrefstring—Where the link goes: a URL or a path. Give it on every LinkButton, unless render gives a router's link that brings its own destination.
variant'solid' | 'outline''solid'How much the link stands out: solid is filled, for the main place a panel leads to; outline is an edge only, for the links and actions beside it.
size'small' | 'medium''medium'The link's height: medium is size.button, small is size.button-sm, for dense rows and panels.
fullWidthbooleanfalseWhether the link fills the width of its container, such as a bottom sheet's main link. Sets data-full-width.
startIconReactNode—An icon before the label, in reading order, so it moves to the right in right-to-left text. Hidden from screen readers: the label names the link.
endIconReactNode—An icon after the label, in reading order. Hidden from screen readers: the label names the link.
childrenReactNode—The label: the words that name where the link goes, in sentence case. Required in practice: a link with no words has no name.
classNamestring—Reaches the root; className is merged after pn-LinkButton.
styleCSSProperties—Reaches the root; className is merged after pn-LinkButton.
refRef<HTMLAnchorElement>—Reaches the root element.
hrefstring, default —
Where the link goes: a URL or a path. Give it on every LinkButton, unless render gives a router's link that brings its own destination.
variant'solid' | 'outline', default 'solid'
How much the link stands out: solid is filled, for the main place a panel leads to; outline is an edge only, for the links and actions beside it.
size'small' | 'medium', default 'medium'
The link's height: medium is size.button, small is size.button-sm, for dense rows and panels.
fullWidthboolean, default false
Whether the link fills the width of its container, such as a bottom sheet's main link. Sets data-full-width.
startIconReactNode, default —
An icon before the label, in reading order, so it moves to the right in right-to-left text. Hidden from screen readers: the label names the link.
endIconReactNode, default —
An icon after the label, in reading order. Hidden from screen readers: the label names the link.
childrenReactNode, default —
The label: the words that name where the link goes, in sentence case. Required in practice: a link with no words has no name.
classNamestring, default —
Reaches the root; className is merged after pn-LinkButton.
styleCSSProperties, default —
Reaches the root; className is merged after pn-LinkButton.
refRef<HTMLAnchorElement>, default —
Reaches the root element.

Use it

import { LinkButton } from '@mylder/perron'

Ask your agent

search_docs({ query: "LinkButton" })

Keyboard and ARIA

From the browser's native link and Base UI's useRender, which adds no behaviour. "From" says who does it.

KeyDoesFrom
Tab, Shift+TabMoves focus to the link and awayThe browser
EnterFollows the link: fires onClick, then goes to href unless the click is preventedThe browser
SpaceNothing: Space scrolls the page, as on every link, and never follows it (CR-4)The browser
ElementRoleAccessible name fromStates announced
rootlink, native, from <a href>Its text content: the label's children; aria-label or aria-labelledby from the caller winVisited, by the browser; aria-current when the caller sets it
startIcon, endIconnone: aria-hidden="true"nonenone

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 label is text the link is named by; the icons are aria-hidden, since an icon beside a word adds nothing the word doesn't say (Icons); variant carries emphasis, not meaning; and the role says "link" where the shape says "button", so the label names where it goes (see Do and don't).
  • Every landmark and named region has an accessible name: none here; a link is neither.
  • Every default label can be overridden: none here; LinkButton owns no strings.
  • Every shape the type accepts renders, in every variant: children, startIcon and endIcon render a string, an element and a list alike, in every variant and size.
  • A hidden copy kept for animation is aria-hidden, and a collapsed region is inert: none here; LinkButton keeps no hidden copy and collapses nothing.
  • Native semantics first: a native <a href>, never role="button" and never Base UI's Button (CR-1); a render element renders an <a> too.
  • Focus moves in reading order and returns on close: the link is one tab stop in document order, and opens nothing of its own to return from.
  • Every target is at least size.target-min square: the smallest target is a small LinkButton, size.button-sm (30 px) tall, and at least that wide with its space.300 padding on each side and a word between.
  • Loops stop when the system asks for less motion: none here; LinkButton has no loop and no transition.

Owned strings

No owned strings: every word comes from the caller, as children.

LinkButton announces nothing of its own when target="_blank" opens a new tab, and owns no "Opens in a new tab" string: a link that leaves Mylder names its destination in its label ("Open in Rejseplanen"), and Mylder's own links open in the same tab.

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.

RuleLevelDoDon'tChecked by
DD-1mustUse LinkButton when pressing it goes somewhere: another page, another place in the app, another siteUse LinkButton to run an action, such as showing a line or closing a panel, with an onClick that prevents the link: that is a Buttonreview
DD-2mustUse Button for an action and LinkButton for navigation, even when they sit side by side and look alikeRender a link through Button's render={<a href="/map" />}: Base UI gives it role="button", and a screen reader hears a button that navigatesreview
DD-3mustName where the link goes, in sentence case: "Back to the map", "Open in Rejseplanen"Write "Click here", "Read more", Title Case or an exclamation mark (Content design): the role already says it is a linkreview
DD-4mustGive a router's link through render, such as render={<Link to="/map" />}, so the app's navigation runs and the look staysWrap a LinkButton in a router link, or a router link in a LinkButton: two nested <a> elements are invalid and make two tab stopsreview
DD-5shouldUse a plain <a> inside a sentence, where a link is part of the textPut a LinkButton in running text: its height and padding break the linereview
DD-6mustKeep LinkButton in ink; give the screen's one main action to a brand ButtonRestyle a LinkButton in the brand yellow: brand is never a link (Intents)review
DD-7mustLeave a link out, or show a disabled Button, when there is nowhere to go yetRender a LinkButton without href or render, or fake a disabled one with opacity: an <a> with no href is not a link, and disabled is a colourreview
DD-8mustUse IconButton for a control with an icon and no wordsPass only a startIcon and no children: the icon is aria-hidden, so the link has no namereview