ButtonLink is mainly used as a navigational element to direct users to a new page or location.

Figma:

Responsive:

Adaptive:

Props

Component props
Name
Type
Default
href
Required
string
-

Specifies a link URL.

text
Required
string
-

Text to render inside the ButtonLink to convey the function and purpose of the ButtonLink.

accessibilityLabel
string
-

Label to provide more context around ButtonLink’s function or purpose. See the Accessibility guidelines to learn more.,

color
ComponentProps<typeof Button>["color"]
"gray"

The background color of ButtonLink.

dataTestId
string
-

Available for testing purposes, if needed. Consider better queries before using this prop.

disabled
boolean
false

Indicates if ButtonLink is disabled. Disabled Buttons are inactive and cannot be interacted with.

focusColor
"lightBackground" | "darkBackground"
-

Indicates whether this component is hosted in a light or dark container.
Used for improving focus ring color contrast.

fullWidth
boolean
false

Default Buttons are sized by the text within the ButtonLink whereas full-width Buttons expand to the full width of their container.

iconEnd
unknown
-

An icon displayed after the text to help clarify the usage of ButtonLink. See the icon variant to learn more.

iconStart
unknown
-

An icon displayed before the text to help clarify the usage of ButtonLink. See the icon variant to learn more.

onClick
(arg1: {
  event: React.MouseEvent<HTMLAnchorElement> | React.KeyboardEvent<HTMLAnchorElement>;
  dangerouslyDisableOnNavigation: () => void;
}) => void
-

Callback invoked when the user clicks (press and release) on ButtonLink with the mouse or keyboard.
See GlobalEventsHandlerProvider to learn more about link navigation.

rel
"none" | "nofollow"
"none"

Provides hints for SEO. See the MDN Web Docs to learn more.

size
"sm" | "md" | "lg"
"md"

sm: 32px, md: 40px, lg: 48px

tabIndex
-1 | 0
0

Use "-1" to remove ButtonLink from keyboard navigation. See the Accessibility guidelines to learn more.

target
null | "self" | "blank"
"null"

Indicates the browsing context where an href will be opened:

  • 'null' opens the anchor in the same window.
  • 'blank' opens the anchor in a new window.
  • 'self' opens an anchor in the same frame.

Usage guidelines

When to use
  • Communicating a navigation that will occur.
  • Triggering or enabling a navigation, such as visiting another URL.
  • Progressing or regressing a user through a step in a flow in separate URLs.
When not to use
  • Inlined in text. Instead, use Link.
  • Limited space available. Consider using an IconButtonLink instead.

Best practices

Do

Place primary ButtonLinks to the right or top of other ButtonLink styles.

Don't

Place more than one primary ButtonLink per container/area.

Do

Show the full text on ButtonLinks. ButtonLinks should be stacked when they cannot be displayed side by side.

Don't

Truncate the ButtonLink text. In rare instances where ButtonLinks must remain on one line, truncate the text on the secondary ButtonLink before truncating on the primary ButtonLink.

Do

Use an IconButton + Tooltip next to the disabled ButtonLink if you need to explain why it is disabled.

Don't

Use a Tooltip on disabled ButtonLink, as it is not accessible for keyboard and screen reader users.

Accessibility

ARIA attributes

When ButtonLink text does not provide sufficient context about the ButtonLink’s behavior, supply a short, descriptive label for screen-readers using accessibilityLabel.
Texts like “Visit“, or “Learn more“ can be confusing when a screen reader reads them out of context. In those cases, we must pass an alternative text with deeper context to replace the ButtonLink text, like “Visit Pinterest's help center“ or “Learn more about Pinterest's ads policy”.

Color contrast in disabled state

Disabled Buttons do not need to pass color contrast guidelines.

From w3.org, 1.4.3 Contrast (Minimum): Text or images of text that are part of an inactive user interface component, that are pure decoration, that are not visible to anyone, or that are part of a picture that contains significant other visual content, have no contrast requirement.

Our current disabled ButtonLink implementation does fail to pass color contrast on accessibility integration tests. To exclude disabled buttons from the integration tests we recomment conditionally setting a data-test-id={ isDisabled ? "disabled-button-<name>" : undefined } and excluding them from the integration test.

On cypress-axe that can be achieved with cy.a11yCheck({ exclude: [['[data-test-id="disabled-button-submit"]']] })

Localization

Be sure to localize all text strings. Note that localization can lengthen text by 20 to 30 percent.

ButtonLink depends on DefaultLabelProvider for internal text strings. Localize the texts via DefaultLabelProvider. Learn more
import { ButtonLink, DefaultLabelProvider, Flex } from 'gestalt';

export default function Example() {
  return (
    <DefaultLabelProvider
      labels={{
        Link: {
          accessibilityNewTabLabel: 'Öffnet eine neue Browser-Registerkarte.',
          accessibilityDownloadLabel: 'Es lädt eine Datei herunter.',
        },
      }}
    >
      <Flex
        alignItems="center"
        height="100%"
        justifyContent="center"
        width="100%"
      >
        <ButtonLink
          color="red"
          href="https://www.pinterest.com/"
          iconEnd="visit"
          onClick={({ event }) => event.preventDefault()}
          size="lg"
          text="Besuchen Sie Pinterest"
        />
      </Flex>
    </DefaultLabelProvider>
  );
}

Variants

State

  1. Enabled
    The typical state of a ButtonLink that represents it can be interacted with and is not in a selected state.

  2. Disabled
    Used to block user interaction such as hover, focus and click. Disabled Buttons are completely unreachable by a keyboard and screenreader, so do not attach Tooltips to disabled Buttons.

Enabled
import { ButtonLink, Flex } from 'gestalt';

export default function Example() {
  return (
    <Flex
      alignItems="center"
      height="100%"
      justifyContent="center"
      width="100%"
    >
      <ButtonLink
        accessibilityLabel="Visit Pinterest"
        color="red"
        href="https://www.pinterest.com/"
        onClick={({ event }) => event.preventDefault()}
        size="lg"
        text="Visit Pinterest"
      />
    </Flex>
  );
}

Disabled
import { ButtonLink, Flex } from 'gestalt';

export default function Example() {
  return (
    <Flex
      alignItems="center"
      height="100%"
      justifyContent="center"
      width="100%"
    >
      <ButtonLink
        accessibilityLabel="Go back"
        disabled
        href="https://www.pinterest.com/"
        onClick={({ event }) => event.preventDefault()}
        size="lg"
        text="Go back"
      />
    </Flex>
  );
}

Size

ButtonLink is available in 3 fixed sizes. The ButtonLink text has always a fixed size of 16px:

  1. lg (48px)
    Large is the only size that should be used on Pinner surfaces.
  2. md (40px)
    Medium is used on more dense UI such as business surfaces or internal tools.
  3. sm (32px)
    Small should be used sparingly and only in places where the UI is very dense.
size="sm"
size="md"
size="lg"

Color

On white backgrounds

  1. Red (Primary)
    High emphasis, used for primary actions.
  2. Gray (Secondary)
    Medium emphasis, used for secondary actions.
  3. Transparent (Tertiary)
    Low emphasis when placed on dark/image backgrounds, used for tertiary actions in that context. Note, this treatment should be used with caution as it has potential color contrast issues.

On color/image backgrounds

  1. White (Primary)
    High emphasis when placed on color/image backgrounds, used for primary actions in that context.
  2. Semi-transparent white (Secondary)
    Medium emphasis when placed on color/image backgrounds, used for secondary actions in that context.
On white backgrounds
import { Box, ButtonLink, Flex, Text } from 'gestalt';

export default function Example() {
  return (
    <Box padding={4}>
      <Flex gap={6} height="100%" width="100%" wrap>
        {['gray', 'red', 'transparent'].map((color) => {
          const colorCopy = color;

          return (
            <Flex key={color} direction="column" gap={2}>
              <Box
                alignItems="center"
                borderStyle="sm"
                display="flex"
                height={200}
                justifyContent="center"
                rounding={4}
                width={200}
              >
                <ButtonLink
                  color={colorCopy}
                  href="https://pinterest.com"
                  iconEnd="visit"
                  onClick={({ event }) => event.preventDefault()}
                  size="lg"
                  text="Visit"
                />
              </Box>
              <Text size="200" weight="bold">
                {/* color=&quot;{color}&quot; */}
              </Text>
            </Flex>
          );
        })}
      </Flex>
    </Box>
  );
}

On color/image backgrounds
import { Box, ButtonLink, Flex, Text } from 'gestalt';

export default function Example() {
  return (
    <Box padding={4}>
      <Flex gap={6} height="100%" width="100%" wrap>
        {['semiTransparentWhite', 'transparentWhiteText', 'white'].map(
          (color) => {
            const colorCopy = color;

            return (
              <Flex key={color} direction="column" gap={2}>
                <Box
                  alignItems="center"
                  borderStyle="sm"
                  dangerouslySetInlineStyle={{
                    __style: {
                      backgroundImage:
                        'url("https://i.ibb.co/d0pQsJz/stock3.jpg")',
                    },
                  }}
                  display="flex"
                  height={200}
                  justifyContent="center"
                  rounding={4}
                  width={200}
                >
                  <ButtonLink
                    color={colorCopy}
                    href="https://www.pinterest.com/"
                    iconEnd="visit"
                    onClick={({ event }) => event.preventDefault()}
                    size="lg"
                    text="Visit"
                  />
                </Box>
                <Text size="200" weight="bold">
                  color=&quot;{color}&quot;
                </Text>
              </Flex>
            );
          }
        )}
      </Flex>
    </Box>
  );
}

Width

  1. Inline (default)
    Inline is our default ButtonLink width. The width of an inline ButtonLink is based on the length of its text. Use in most cases where you need a ButtonLink.

  2. Full-width (fullWidth)
    Full-width ButtonLink can be used in narrower content areas when the text in the ButtonLink is close to full width in the content area. This is especially common to see in components such as BannerCallout and BannerUpsell at their smaller breakpoints.

import { Box, ButtonLink } from 'gestalt';

export default function Example() {
  return (
    <Box
      direction="column"
      display="flex"
      justifyContent="center"
      margin={4}
      width="100%"
    >
      <Box margin={2} width="100%">
        <ButtonLink
          color="red"
          fullWidth={false}
          href="https://pinterest.com"
          iconEnd="visit"
          onClick={({ event }) => event.preventDefault()}
          size="lg"
          text="Inline Link"
        />
      </Box>
      <Box margin={2} width="100%">
        <ButtonLink
          color="red"
          fullWidth
          href="https://pinterest.com"
          iconEnd="visit"
          onClick={({ event }) => event.preventDefault()}
          size="lg"
          text="Full-width Link"
        />
      </Box>
    </Box>
  );
}

Icons

iconEnd adds an icon after the ButtonLink text, and iconStart adds an icon before. Icons should only be used to visually reinforce a specific function or interaction of the ButtonLink. Menus and external links are a common use case. Use visit when linking to an external URL or arrow-down when displaying a Popover on click. Note that icons on ButtonLink are not accessible to screen readers.

import { ButtonLink, Flex } from 'gestalt';

export default function Example() {
  return (
    <Flex
      alignItems="center"
      height="100%"
      justifyContent="center"
      width="100%"
    >
      <ButtonLink
        accessibilityLabel=""
        href="https://www.pinterest.com/"
        iconEnd="visit"
        iconStart="sparkle"
        onClick={({ event }) => event.preventDefault()}
        size="lg"
        text="Visit AI solution"
      />
    </Flex>
  );
}

Focus style

import { Box, ButtonLink, Flex } from 'gestalt';

export default function Example() {
  return (
    <Flex
      alignItems="center"
      height="100%"
      justifyContent="center"
      width="100%"
    >
      <Box height={150} width={150}>
        <Flex
          alignItems="center"
          height="100%"
          justifyContent="center"
          width="100%"
        >
          <ButtonLink
            accessibilityLabel="Visit Pinterest"
            color="red"
            focusColor="lightBackground"
            href="https://www.pinterest.com/"
            onClick={({ event }) => event.preventDefault()}
            size="lg"
            text="Visit Pinterest"
          />
        </Flex>
      </Box>
      <Box color="inverse" height={150} width={150}>
        <Flex
          alignItems="center"
          height="100%"
          justifyContent="center"
          width="100%"
        >
          <ButtonLink
            accessibilityLabel="Visit Pinterest"
            color="red"
            focusColor="darkBackground"
            href="https://www.pinterest.com/"
            onClick={({ event }) => event.preventDefault()}
            size="lg"
            text="Visit Pinterest"
          />
        </Flex>
      </Box>
    </Flex>
  );
}

External handlers

ButtonLink consumes external handlers from GlobalEventsHandlerProvider.

Handlers:

See GlobalEventsHandlerProvider for more information.

rel and target

These optional props control the behavior of ButtonLink. External links commonly use target="_blank" to open the link in a new tab or window, and rel="nofollow" to provide hints for SEO.

import { ButtonLink, Flex } from 'gestalt';

export default function Example() {
  return (
    <Flex
      alignItems="center"
      height="100%"
      justifyContent="center"
      width="100%"
    >
      <ButtonLink
        accessibilityLabel="Visit Pinterest"
        href="https://www.pinterest.com/"
        iconEnd="visit"
        onClick={({ event }) => event.preventDefault()}
        rel="nofollow"
        size="lg"
        target="blank"
        text="Visit Pinterest"
      />
    </Flex>
  );
}

Component quality checklist

Component quality checklist
Quality item
Status
Status description
Figma Library
Component is not currently available in Figma.
Responsive Web
Ready
Component responds to changing viewport sizes in web and mobile web.

Internal documentation

ButtonLink
Use ButtonLink when an action is needed instead of a link.

ButtonGroup
When displaying multiple ButtonLinks in a layout, use ButtonGroup to ensure consistent spacing and wrapping behavior.

IconButton
Use IconButton when only an icon is needed instead of text.

TapArea
Use TapArea to make non-button elements interactive, like an Image. This ensures the element interaction is accessible and uses Gestalt styles.

Tabs
Tabs are intended for page-level navigation between multiple URLs.

GlobalEventsHandlerProvider
GlobalEventsHandlerProvider allows external link navigation control across all children components with link behavior.
See GlobalEventsHandlerProvider to learn more about link navigation.