Accessibility
The TextLink component has been designed with accessibility in mind.
Accessibility Props
The following props are available to improve the accessibility of your TextLink component:
Name | Type | Description |
---|---|---|
asComponent | string \| () => React.Element | Allows rendering the component as a different element. |
ariaCurrent | string | Indicates if the component represents the current item within a set of related elements. |
aria-label | string | Defines accessible text for the component, replacing the visible text for screen readers. |
aria-controls | string | Identifies the element controlled by the component, establishing a relationship for screen readers. |
title | string | HTML attribute providing additional information. |
The TextLink component accepts all standard HTML attributes including ARIA attributes. While ariaCurrent
is implemented as a specific prop, other ARIA attributes (like aria-controls
, aria-label
, etc.) can be passed directly as HTML attributes.
Automatic Accessibility Features
The TextLink component automatically manages several accessibility features:
The component automatically manages HTML semantics and ARIA attributes:
- Uses the semantically correct element based on props:
- Renders as
<a>
whenhref
is provided - Renders as
<button>
when nohref
is provided - Renders as specified custom element when
asComponent
is provided
- Renders as
- Sets
role="button"
whenonClick
is provided withouthref
- Sets proper
rel
attributes for external links (noopener
,noreferrer
) - Sets
type="button"
when rendered as a button element
- Uses the semantically correct element based on props:
Focus management is handled automatically:
- Native focus behavior is preserved based on the rendered element
- Ensures proper focus appearance for keyboard users
Best Practices
Use clear and descriptive link text that describes the destination or purpose of the link. Avoid generic text like “click here” or “read more” without proper context.
When using icons in links (with
iconLeft
oriconRight
), ensure they have appropriate accessibility labels:- If the icon is decorative and accompanied by text, the icon should be hidden from screen readers
- If the icon alone conveys meaning (especially when used without text), use the
ariaLabel
prop on the icon to describe its purpose
For links that open in a new window/tab (when
external={true}
), ensure users are aware of this behavior:- Always use the
<NewWindow />
icon to visually indicate that the link opens in a new window/tab - Add an accessibility label to the icon using
ariaLabel="Opens in new window"
to ensure screen reader users are informed
- Always use the
For TextLinks with only icons (no text content), always provide an
aria-label
to ensure screen reader users understand the link’s purpose.The
title
attribute is not reliably announced by screen readers and should not be used as the primary method for providing additional information to screen reader users. Instead:- Use descriptive link text
- Use
aria-label
for links with unclear text or icon-only links - For additional descriptive information, consider using visible text or alternative ARIA attributes
Keyboard Navigation
TextLink components are navigable with keyboard by default:
When rendered as anchor (
<a>
):- Users can focus on links using the Tab key
- Users can activate links using the Enter key
When rendered as button (
<button>
):- Users can focus using the Tab key
- Users can activate using both Enter and Space keys
On mobile devices with on-screen keyboards, standard touch interactions apply while maintaining the same keyboard accessibility patterns when an external keyboard is connected.
Examples
Using aria-label
<TextLink href="https://orbit.kiwi" aria-label="Visit the Orbit design system website">Orbit</TextLink>
Screen reader announces: “Visit the Orbit design system website, link”.
External link with accessible icon
<TextLinkhref="https://orbit.kiwi"externaliconRight={<NewWindow ariaLabel="Opens in new window" />}>Orbit design system</TextLink>
Screen reader announces: “Orbit design system, opens in new window, link”.
This pattern ensures both visual users and screen reader users understand that the link will open in a new window/tab.
Button behavior with onClick
<TextLink onClick={handleClick}>Perform an action</TextLink>
Screen reader announces: “Perform an action, button”.
This example shows TextLink rendering as a semantically correct button element when no href
is provided, improving accessibility while maintaining link-like styling. This ensures proper keyboard interaction patterns, as buttons respond to both Enter and Space keys, while links only respond to Enter.
Using ariaCurrent for navigation
import { Stack, List, ListItem, TextLink } from "@kiwicom/orbit-components";function Navigation() {// Assuming current page is "profile"const currentPage = "profile";return (<Stack as="nav" aria-label="Main navigation"><List type="secondary"><ListItem><TextLink href="/home" ariaCurrent={currentPage === "home" ? "page" : undefined}>Home</TextLink></ListItem><ListItem><TextLink href="/profile" ariaCurrent={currentPage === "profile" ? "page" : undefined}>Profile</TextLink></ListItem><ListItem><TextLink href="/settings" ariaCurrent={currentPage === "settings" ? "page" : undefined}>Settings</TextLink></ListItem></List></Stack>);}
When on the profile page, screen readers announce: “Profile, current page, link” when focused on the Profile link.
The ariaCurrent="page"
attribute helps users of assistive technologies understand which navigation item represents the current page, enhancing orientation within the site.
Using aria-controls with TextLink
import { Stack, Text, Box, TextLink } from "@kiwicom/orbit-components";import { ChevronDown, ChevronUp } from "@kiwicom/orbit-components/icons";function ExpandableContent() {const [isExpanded, setIsExpanded] = React.useState(false);const contentId = "expandable-content";return (<Stack><TextLinkonClick={() => setIsExpanded(!isExpanded)}aria-expanded={isExpanded}aria-controls={contentId}iconRight={isExpanded ? <ChevronUp ariaHidden /> : <ChevronDown ariaHidden />}type="secondary">{isExpanded ? "Hide details" : "Show details"}</TextLink>{isExpanded && (<Box id={contentId}><Text>This content is controlled by the TextLink. When expanded, screen readers can navigatedirectly between the control and this content.</Text></Box>)}</Stack>);}
In this example, the TextLink controls the visibility of content with ID “expandable-content”. The aria-controls
attribute creates a programmatic relationship between the TextLink and the content it controls, while aria-expanded
indicates the current state.
When the TextLink is focused, screen readers will announce its text content (‘Show details’), its role (‘button’), and its expanded state (‘collapsed’). Depending on the screen reader, it may also indicate the control relationship with the content it manages.