TextLink

Accessibility

Accessibility Props

NameTypeDescription
asComponentstring \| () => React.ElementAllows rendering the component as a different element.
ariaCurrentstringIndicates if the component represents the current item within a set of related elements.
aria-labelstringDefines accessible text for the component, replacing the visible text for screen readers.
aria-controlsstringIdentifies the element controlled by the component, establishing a relationship for screen readers.
titlestringHTML attribute providing additional information.

Automatic Accessibility Features

    • Uses the semantically correct element based on props:
      • Renders as <a> when href is provided
      • Renders as <button> when no href is provided
      • Renders as specified custom element when asComponent is provided
    • Sets role="button" when onClick is provided without href
    • Sets proper rel attributes for external links (noopener, noreferrer)
    • Sets type="button" when rendered as a button element
    • Native focus behavior is preserved based on the rendered element
    • Ensures proper focus appearance for keyboard users

Best Practices

    • 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
    • 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
    • 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

    • Users can focus on links using the Tab key
    • Users can activate links using the Enter key
    • Users can focus using the Tab key
    • Users can activate using both Enter and Space keys

Examples

Using aria-label

<TextLink href="https://orbit.kiwi" aria-label="Visit the Orbit design system website">
Orbit
</TextLink>

External link with accessible icon

<TextLink
href="https://orbit.kiwi"
external
iconRight={<NewWindow ariaLabel="Opens in new window" />}
>
Orbit design system
</TextLink>

Button behavior with onClick

<TextLink onClick={handleClick}>Perform an action</TextLink>

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>
);
}

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>
<TextLink
onClick={() => 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 navigate
directly between the control and this content.
</Text>
</Box>
)}
</Stack>
);
}