Appearance
QsLink
<qs-link>alphaA text link to another page or resource. Renders a native <a>, always
underlined so it never relies on colour alone, and keeps any markup you put
inside it. Add icon for a leading icon, external for a link that opens in
a new tab, and current for the current page in a navigation. For a link that
looks like a button, use <qs-button href="…">.
Examples
html
<qs-text>
Every value comes from a token: see <qs-link href="/tokens">the token map</qs-link> for the full list.
</qs-text>Prop
| Prop | Type | Default | Description |
|---|---|---|---|
href | string | "" | Where the link goes. |
icon | string | "" | Name of a `qs-icon` shown before the text (e.g. `arrow-right`, `download`). Decorative: the link text stays the accessible name. |
external | boolean | false | Opens the link in a new tab and shows the external-link icon. The link itself tells assistive technology "(opens in a new tab)": through visually hidden `sr-only` text, or appended to `label` when one is set. The icon stays decorative. |
current | boolean | false | Marks the link as the current page (`aria-current="page"`), for navigation. |
label | string | "" | Accessible name for the link (`aria-label`), when the visible text needs more context, e.g. "Read more" → "Read more about tokens". With `external`, "(opens in a new tab)" is appended. |
text | string | — | The text content of the element, captured from light DOM before the first render. |
Usage
Use a link to go somewhere: another page, a section of this page, a file or another site. If the control does something on this page (saves, opens a dialog, deletes), use a button instead.
Inline and standalone
Inside running text the link wraps with the sentence and inherits its type. On its own line it works as a standalone link, for example at the end of a card or section.
With an icon
icon adds a leading icon from the icon set. It is decorative: the link text stays the accessible name.
html
<qs-link href="/tokens" icon="arrow-right">All tokens</qs-link>External link
external opens the link in a new tab (target="_blank", rel="noopener noreferrer") and adds the external-link icon. The icon is decorative (aria-hidden="true"): the warning lives on the link itself, in one of two ways.
- Visually hidden text (default). The link renders
<span class="sr-only"> (opens in a new tab)</span>after its text, so screen readers read "WCAG 2.2 quick reference (opens in a new tab)". See visually hidden text. label. When you setlabel, it becomes the link'saria-labeland "(opens in a new tab)" is appended to it. Use it when the visible text needs more context.
Use external only for other sites; links inside the docs open in place.
html
<!-- name: "WCAG 2.2 quick reference (opens in a new tab)", from sr-only text -->
<qs-link href="https://www.w3.org/WAI/WCAG22/quickref/" external>WCAG 2.2 quick reference</qs-link>
<!-- name: "Read more about link purpose (opens in a new tab)", from aria-label -->
<qs-link href="…" external label="Read more about link purpose">Read more</qs-link>Link styled as a button
For a call to action that navigates, use <qs-button href="…">. It renders a real <a> with the button look, so there is one source for button styles.
html
<qs-button href="/guide/creating-components" variant="primary">Create a component</qs-button>States
| State | Look |
|---|---|
| Default | Accent ink, thin underline |
| Hover | Body ink, thicker underline (pointer devices only) |
| Active | Body ink |
| Focus | Focus ring from the --focus-outline-* tokens, keyboard only |
| Visited | Secondary ink, underline kept |
| Current page | current: body ink, heavier weight, no underline, aria-current="page" |
html
<nav aria-label="Components">
<qs-link href="/components/button">Button</qs-link>
<qs-link href="/components/link" current>Link</qs-link>
<qs-link href="/components/dialog">Dialog</qs-link>
</nav>Do and don't
- Do write link text that makes sense on its own: "Read the dialog guidelines", not "click here".
- Do keep the underline; it is what tells a link from text for people who can't see the colour.
- Don't use a link for an action on the page; use a button.
- Don't open internal pages in a new tab; reserve
externalfor other sites.
In a framework
Children are the static content of the first render, and their markup (links, <em>, lang spans) is kept. For text that changes, bind Elena's text property instead of rendering a child, as Elena recommends:
html
<!-- React --> <qs-link text={label} />
<!-- Vue --> <qs-link :text="label" />
<!-- Angular --><qs-link [text]="label" />Don't let a framework add or remove individual children inside qs-link: once rendered, they live inside the component's own element.
Accessibility
- Renders a native
<a href>: reachable with Tab, activated with Enter, listed in screen-reader link lists. - The accessible name is the link's content. Markup inside it (
<em>,<span lang>) is kept. - Always underlined, so it is never marked by colour alone (WCAG 1.4.1). Link colours pass 4.5:1 on canvas and surface in both themes.
externalputs "(opens in a new tab)" in the link's own name, throughsr-onlytext or thelabel(aria-label), so the new tab is never a surprise. The icon is alwaysaria-hidden="true".labelreplaces the visible text as the accessible name; keep the visible words at the start of it (WCAG 2.5.3, label in name).currentsetsaria-current="page"; the link stays focusable.- Only colour and underline thickness animate, so there is nothing to remove under reduced motion.