@xsolla/xui-link
v0.209.1
Published
An accessible inline link. Renders an `<a>` element with theme-aware colour, optional underline, and automatic security attributes for external targets. <!-- BEGIN:xui-mcp-instructions:link --> An inline interactive text element that navigates the user to
Readme
Link
An accessible inline link. Renders an <a> element with theme-aware colour, optional underline, and automatic security attributes for external targets.
An inline interactive text element that navigates the user to another location or triggers a related action. Renders as styled text with optional leading and trailing icons. Used inside body copy, lists, form helper text, and any context where navigation or a contextual action should blend with surrounding text rather than stand out as a button.
When to use
- For in-text navigation links — e.g. "Read our [Privacy Policy]", "See [all results]"
- For contextual actions inside helper text, empty states, or notifications — e.g. "[Resend code]", "[Clear filters]", "[Learn more]"
- When the action is secondary and should not visually compete with a primary Button
- In breadcrumbs, footers, settings descriptions, and legal text where navigation is part of the prose
When not to use
- As a primary call-to-action — use a Button
- When the interaction triggers an operation (save, delete, submit) rather than navigating — use a Button or Flex button
- For standalone navigation items in a menu or sidebar — use a Navigation component
- When the link needs a container, padding, or icon-only format — use a Flex button
Content guidelines
- Descriptive text — link labels must make sense out of context. Screen readers often navigate by listing all links on a page. Labels like "here", "this", or "more" are meaningless in isolation.
- Action links — use an imperative verb phrase: "Resend code", "Clear filters", "View all", "Download report".
- Navigation links — use the destination name or a descriptive noun phrase: "Privacy Policy", "API reference", "Account settings".
- Avoid punctuation — do not include trailing commas, periods, or colons inside the link text. Place punctuation outside the link: "See our [FAQ]." not "See our [FAQ.]"
- Capitalisation — use sentence case for action links ("View all results"). Use title case only for proper names and document titles ("Terms of Service", "Privacy Policy").
Behaviour guidelines
- Navigation vs action — use Link for navigation (opening a URL, switching routes) and for lightweight text-level actions (resend, clear, show more). For operations that change state on the server (delete, publish, submit), use a Button even if it is visually small.
- External links — when a link opens in a new tab, always add a Right icon (external link symbol ↗) and include target="_blank" with rel="noopener noreferrer". Inform screen reader users by including visually hidden text: "(opens in new tab)", or include it in the aria-label.
- Visited state — style :visited links distinctly in contexts where the browsing history is meaningful (documentation, article indexes). Do not override :visited styles in application UI where it adds no value.
- Disabled links — avoid disabled links. If an action is not available, either remove the link entirely or replace it with plain text. If a disabled link is unavoidable, use aria-disabled="true" and tabindex="-1" rather than the disabled attribute (which does not exist on elements).
- Text length — keep link text concise and descriptive. A link labelled "here" or "click here" is meaningless out of context and inaccessible. The link text should describe the destination or action: "View invoice #1042", "Reset password", "Download CSV".
- Underline — Link text must be distinguishable from surrounding non-link text by more than colour alone (WCAG 1.4.1). Use an underline, heavier weight, or other non-colour cue in addition to the palette colour.
Accessibility
- Link must be implemented as a native <a href="…"> element — not a , , or with a click handler. Native elements are keyboard-focusable, announced as links by screen readers, and support right-click context menus.
- The link must have a descriptive accessible name. If the visible text is not descriptive enough (e.g. it reads "here" in context), add aria-label with a more descriptive label.
- External links must include aria-label or visually hidden text announcing that they open in a new tab: e.g. aria-label="API reference (opens in new tab)".
- The focus state must have a visible :focus-visible ring that meets WCAG 2.4.7 (Focus Visible). Do not suppress the browser's default focus ring without providing a custom replacement.
- Do not rely on colour alone to distinguish links from surrounding text (WCAG 1.4.1). Always use an underline or weight change in addition to the palette colour.
- Icon-enriched links where the icon is decorative must have aria-hidden="true" on the icon element so screen readers do not announce icon names.
- Visited links in informational contexts (docs, knowledge base) should have a distinct :visited colour to help users track what they have already read.
Installation
npm install @xsolla/xui-linkImports
import { Link } from '@xsolla/xui-link';Quick start
import * as React from 'react';
import { Link } from '@xsolla/xui-link';
export default function Example() {
return <Link href="https://example.com">Visit Example</Link>;
}API Reference
<Link>
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| children | ReactNode | - | Link content. |
| href | string | - | Destination URL. Cleared when disabled. |
| onClick | () => void | - | Click handler. When provided, preventDefault() is called before invoking — browser navigation via href is suppressed, so handle navigation yourself (e.g. router push). href remains on the <a> for right-click and assistive tech. |
| target | string | - | Anchor target (e.g. '_blank'). When '_blank', rel="noopener noreferrer" is added automatically and merged with any caller-supplied rel. |
| rel | string | - | Additional rel tokens. |
| size | 'sm' \| 'md' \| 'lg' | 'md' | Font size preset (12/14/16px). |
| underline | boolean | false | Underline the text. |
| disabled | boolean | false | Removes href, sets tabIndex={-1}, and shows not-allowed cursor. |
| color | string | theme control.link.primary | Custom text colour (ignored when disabled). |
| testID | string | - | Test identifier. |
Inherits ThemeOverrideProps (themeMode, themeProductContext).
Examples
Sizes
import * as React from 'react';
import { Link } from '@xsolla/xui-link';
export default function Example() {
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
<Link size="sm" href="#">Small Link</Link>
<Link size="md" href="#">Medium Link</Link>
<Link size="lg" href="#">Large Link</Link>
</div>
);
}External link
import * as React from 'react';
import { Link } from '@xsolla/xui-link';
export default function Example() {
return (
<Link href="https://example.com" target="_blank">
Open in a new tab
</Link>
);
}Underlined inline link
import * as React from 'react';
import { Link } from '@xsolla/xui-link';
export default function Example() {
return (
<p>
Read our <Link href="/terms" underline>Terms of Service</Link> and{' '}
<Link href="/privacy" underline>Privacy Policy</Link>.
</p>
);
}Disabled
import * as React from 'react';
import { Link } from '@xsolla/xui-link';
export default function Example() {
return (
<Link href="/disabled" disabled>
Disabled Link
</Link>
);
}Accessibility
- Renders a native
<a>with explicitrole="link". - Disabled links lose their
hrefand become unfocusable (tabIndex={-1}). - Visible focus ring uses the theme's brand border colour.
- For
target="_blank",rel="noopener noreferrer"is enforced automatically. - Use descriptive link text — avoid generic phrases like "click here".
