alpha

Link

A link allows a user to navigate to another page or resource within a web page or application.

installyarn add react-aria-components
version1.0.0-alpha.0
usageimport {Link} from 'react-aria-components'

Example#


import {Link} from 'react-aria-components';

<Link>
  <a href="https://www.imdb.com/title/tt6348138/" target="_blank">
    The missing link
  </a>
</Link>
import {Link} from 'react-aria-components';

<Link>
  <a
    href="https://www.imdb.com/title/tt6348138/"
    target="_blank"
  >
    The missing link
  </a>
</Link>
import {Link} from 'react-aria-components';

<Link>
  <a
    href="https://www.imdb.com/title/tt6348138/"
    target="_blank"
  >
    The missing link
  </a>
</Link>
Show CSS
.react-aria-Link {
  --focus-ring-color: slateblue;
  --text-color: var(--spectrum-global-color-blue-600);
  --text-color-pressed: var(--spectrum-global-color-blue-700);
  --text-color-disabled: gray;

  color: var(--text-color);
  font-size: 18px;
  transition: all 200ms;
  text-decoration: underline;
  cursor: pointer;
  outline: none;
  position: relative;

  &[data-hovered] {
    text-decoration-style: wavy;
  }

  &[data-pressed] {
    color: var(--text-color-pressed);
  }

  &[aria-disabled] {
    cursor: default;
    color: var(--text-color-disabled);
  }

  &[data-focus-visible]:after {
    content: '';
    position: absolute;
    inset: -3px -6px;
    border-radius: 6px;
    border: 2px solid var(--focus-ring-color);
  }
}

@media (forced-colors: active) {
  .react-aria-Link {
    --focus-ring-color: Highlight;
    --text-color: LinkText;
    --text-color-pressed: LinkText;
    --text-color-disabled: GrayText;
  }
}
.react-aria-Link {
  --focus-ring-color: slateblue;
  --text-color: var(--spectrum-global-color-blue-600);
  --text-color-pressed: var(--spectrum-global-color-blue-700);
  --text-color-disabled: gray;

  color: var(--text-color);
  font-size: 18px;
  transition: all 200ms;
  text-decoration: underline;
  cursor: pointer;
  outline: none;
  position: relative;

  &[data-hovered] {
    text-decoration-style: wavy;
  }

  &[data-pressed] {
    color: var(--text-color-pressed);
  }

  &[aria-disabled] {
    cursor: default;
    color: var(--text-color-disabled);
  }

  &[data-focus-visible]:after {
    content: '';
    position: absolute;
    inset: -3px -6px;
    border-radius: 6px;
    border: 2px solid var(--focus-ring-color);
  }
}

@media (forced-colors: active) {
  .react-aria-Link {
    --focus-ring-color: Highlight;
    --text-color: LinkText;
    --text-color-pressed: LinkText;
    --text-color-disabled: GrayText;
  }
}
.react-aria-Link {
  --focus-ring-color: slateblue;
  --text-color: var(--spectrum-global-color-blue-600);
  --text-color-pressed: var(--spectrum-global-color-blue-700);
  --text-color-disabled: gray;

  color: var(--text-color);
  font-size: 18px;
  transition: all 200ms;
  text-decoration: underline;
  cursor: pointer;
  outline: none;
  position: relative;

  &[data-hovered] {
    text-decoration-style: wavy;
  }

  &[data-pressed] {
    color: var(--text-color-pressed);
  }

  &[aria-disabled] {
    cursor: default;
    color: var(--text-color-disabled);
  }

  &[data-focus-visible]:after {
    content: '';
    position: absolute;
    inset: -3px -6px;
    border-radius: 6px;
    border: 2px solid var(--focus-ring-color);
  }
}

@media (forced-colors: active) {
  .react-aria-Link {
    --focus-ring-color: Highlight;
    --text-color: LinkText;
    --text-color-pressed: LinkText;
    --text-color-disabled: GrayText;
  }
}

Features#


Links can be created in HTML with the <a> element with an href attribute. However, if the link does not have an href, and is handled client side with JavaScript instead, it will not be exposed to assistive technology properly. Link helps achieve accessible links with either native HTML elements or custom element types.

  • Flexible – Support for navigation links, JavaScript handled links, or custom element types (e.g. router links). Disabled links are also supported.
  • Accessible – Implemented as a custom ARIA link when handled via JavaScript, and otherwise as a native HTML link.
  • Styleable – Hover, press, and keyboard focus states are provided for easy styling. These states only apply when interacting with an appropriate input device, unlike CSS pseudo classes.

Anatomy#


A link consists of a pressable area usually containing a textual label or an icon that users can click or tap to navigate to another page or resource. In addition, keyboard users may activate links using the Enter key.

If a visual label is not provided (e.g. an icon or image only link), then an aria-label or aria-labelledby prop must be passed to identify the link to assistive technology.

Props#


NameTypeDefaultDescription
isDisabledbooleanWhether the link is disabled.
autoFocusbooleanWhether the element should receive focus on render.
childrenReactNode( (values: LinkRenderProps )) => ReactNodeThe children of the component. A function may be provided to alter the children based on component state.
classNamestring( (values: LinkRenderProps )) => stringThe CSS className for the element. A function may be provided to compute the class based on component state.
styleCSSProperties( (values: LinkRenderProps )) => CSSPropertiesThe inline style for the element. A function may be provided to compute the style based on component state.
Events
NameTypeDefaultDescription
onPress( (e: PressEvent )) => voidHandler that is called when the press is released over the target.
onPressStart( (e: PressEvent )) => voidHandler that is called when a press interaction starts.
onPressEnd( (e: PressEvent )) => void

Handler that is called when a press interaction ends, either over the target or when the pointer leaves the target.

onPressChange( (isPressed: boolean )) => voidHandler that is called when the press state changes.
onPressUp( (e: PressEvent )) => void

Handler that is called when a press is released over the target, regardless of whether it started on the target or not.

onFocus( (e: FocusEvent<Target> )) => voidHandler that is called when the element receives focus.
onBlur( (e: FocusEvent<Target> )) => voidHandler that is called when the element loses focus.
onFocusChange( (isFocused: boolean )) => voidHandler that is called when the element's focus status changes.
onKeyDown( (e: KeyboardEvent )) => voidHandler that is called when a key is pressed.
onKeyUp( (e: KeyboardEvent )) => voidHandler that is called when a key is released.
Layout
NameTypeDefaultDescription
slotstringA slot name for the component. Slots allow the component to receive props from a parent component.
Accessibility
NameTypeDefaultDescription
aria-labelstringDefines a string value that labels the current element.
aria-labelledbystringIdentifies the element (or elements) that labels the current element.
aria-describedbystringIdentifies the element (or elements) that describes the object.
aria-detailsstringIdentifies the element (or elements) that provide a detailed, extended description for the object.

Styling#


React Aria components can be styled in many ways, including using CSS classes, inline styles, utility classes (e.g. Tailwind), CSS-in-JS (e.g. Styled Components), etc. By default, all components include a builtin className attribute which can be targeted using CSS selectors. These follow the react-aria-ComponentName naming convention.

.react-aria-Link {
  /* ... */
}
.react-aria-Link {
  /* ... */
}
.react-aria-Link {
  /* ... */
}

A custom className can also be specified on any component. This overrides the default className provided by React Aria with your own.

<Link className="my-link">
  {/* ... */}
</Link>
<Link className="my-link">
  {/* ... */}
</Link>
<Link className="my-link">
  {/* ... */}
</Link>

In addition, some components support multiple UI states (e.g. focused, placeholder, readonly, etc.). React Aria components expose states using DOM attributes, which you can target in CSS selectors. These are ARIA attributes wherever possible, or data attributes when a relevant ARIA attribute does not exist. For example:

.react-aria-Link[data-pressed] {
  /* ... */
}
.react-aria-Link[data-pressed] {
  /* ... */
}
.react-aria-Link[data-pressed] {
  /* ... */
}

The className and style props also accept functions which receive states for styling. This lets you dynamically determine the classes or styles to apply, which is useful when using utility CSS libraries like Tailwind.

<Link
  className={({ isPressed }) => isPressed ? 'bg-gray-700' : 'bg-gray-600'}
/>
<Link
  className={({ isPressed }) =>
    isPressed ? 'bg-gray-700' : 'bg-gray-600'}
/>
<Link
  className={(
    { isPressed }
  ) =>
    isPressed
      ? 'bg-gray-700'
      : 'bg-gray-600'}
/>

Render props may also be used as children to alter what elements are rendered based on the current state. For example, you could render an extra element when the link is in a pressed state.

<Link>
  {({isPressed}) => (
    <>
      {isPressed && <PressHighlight />}
      Press me
    </>
  )}
</Link>
<Link>
  {({isPressed}) => (
    <>
      {isPressed && <PressHighlight />}
      Press me
    </>
  )}
</Link>
<Link>
  {({ isPressed }) => (
    <>
      {isPressed && (
        <PressHighlight />
      )}
      Press me
    </>
  )}
</Link>

The states, selectors, and render props for Link are documented below.

NameCSS SelectorDescription
isCurrent[aria-current]Whether the link is the current item within a list.
isHovered[data-hovered]Whether the link is currently hovered with a mouse.
isPressed[data-pressed]Whether the link is currently in a pressed state.
isFocused:focusWhether the link is focused, either via a mouse or keyboard.
isFocusVisible[data-focus-visible]Whether the link is keyboard focused.
isDisabled[aria-disabled]Whether the link is disabled.

Usage#


The <Link> component can wrap a custom link element provided by a router like React Router.

import {Link as RouterLink} from 'react-router-dom';

<Link>
  <RouterLink to="/foo">Foo</RouterLink>
</Link>
import {Link as RouterLink} from 'react-router-dom';

<Link>
  <RouterLink to="/foo">Foo</RouterLink>
</Link>
import {Link as RouterLink} from 'react-router-dom';

<Link>
  <RouterLink to="/foo">
    Foo
  </RouterLink>
</Link>

When the content is plain text, a <Link> is rendered as a <span> but exposed to assistive technologies as a link. Events will need to be handled in JavaScript with the onPress prop.

Note: this will not behave like a native link. Browser features like context menus and open in new tab will not apply.

<Link onPress={() => alert('Pressed link')}>Adobe</Link>
<Link onPress={() => alert('Pressed link')}>Adobe</Link>
<Link
  onPress={() =>
    alert(
      'Pressed link'
    )}
>
  Adobe
</Link>

Events#

Link supports user interactions via mouse, keyboard, and touch. You can handle all of these via the onPress prop. This is similar to the standard onClick event, but normalized to support all interaction methods equally. In addition, the onPressStart, onPressEnd, and onPressChange events are fired as the user interacts with the link.

Each of these handlers receives a PressEvent, which exposes information about the target and the type of event that triggered the interaction. See usePress for more details.

function Example() {
  let [pointerType, setPointerType] = React.useState('');

  return (
    <>
      <Link
        onPressStart={(e) => setPointerType(e.pointerType)}
        onPressEnd={() => setPointerType('')}
      >
        Press me
      </Link>
      <p>
        {pointerType
          ? `You are pressing the link with a ${pointerType}!`
          : 'Ready to be pressed.'}
      </p>
    </>
  );
}
function Example() {
  let [pointerType, setPointerType] = React.useState('');

  return (
    <>
      <Link
        onPressStart={(e) => setPointerType(e.pointerType)}
        onPressEnd={() => setPointerType('')}
      >
        Press me
      </Link>
      <p>
        {pointerType
          ? `You are pressing the link with a ${pointerType}!`
          : 'Ready to be pressed.'}
      </p>
    </>
  );
}
function Example() {
  let [
    pointerType,
    setPointerType
  ] = React.useState('');

  return (
    <>
      <Link
        onPressStart={(e) =>
          setPointerType(
            e.pointerType
          )}
        onPressEnd={() =>
          setPointerType(
            ''
          )}
      >
        Press me
      </Link>
      <p>
        {pointerType
          ? `You are pressing the link with a ${pointerType}!`
          : 'Ready to be pressed.'}
      </p>
    </>
  );
}

Disabled#

A link can be disabled by passing the isDisabled property. This will work with both native link elements as well as client handled links. Native navigation will be disabled, and the onPress event will not be fired. The link will be exposed as disabled to assistive technology with ARIA.

<Link isDisabled>
  <a href="https://adobe.com" target="_blank">Disabled link</a>
</Link>
<Link isDisabled>
  <a href="https://adobe.com" target="_blank">
    Disabled link
  </a>
</Link>
<Link isDisabled>
  <a
    href="https://adobe.com"
    target="_blank"
  >
    Disabled link
  </a>
</Link>

Advanced customization#


Hooks#

If you need to customize things further, such as customizing the DOM structure, you can drop down to the lower level Hook-based API. See useLink for more details.