import { Button } from '@uhg-abyss/web/ui/Button';<Button>Click Here!</Button>Size
Use the size prop to change the size of the button. The default is set to 'md'. The size prop can take in the Abyss standardized 'sm', 'md', and 'lg'.
Button colors and variants
Button provides distinct visual styles through separate color and variant props:
- Use the
variantprop to specify the button style category:filled,outline, ortext. - Use the
colorprop to indicate color and purpose:brand(primary actions),neutral(secondary actions),destructive(dangerous actions), orinverse(on dark backgrounds).
By default, brand color and filled variant are enabled.
Icons
To insert an IconSymbol into the Button, use the icon props. This prop accepts an object of the following type:
{ icon: string; position: 'leading' | 'trailing' | 'icon-only'; variant?: 'filled' | 'outlined';}icon: The name of the icon to display.position: The position of the icon relative to the button text.variant: The variant of the icon.
Icon-only
Buttons can also be created without any text by providing an icon with position 'icon-only'. This button can be used with any of the available variants.
Note: The child text of the button will be visually hidden, but will remain accessible for screen readers.
useForm (recommended)
Using the useForm hook lets the DOM handle form data.
useState
Using the useState hook gets values from the component state.
Href
If the href prop is present, the button will render as an HTML anchor (<a>) and navigate to the given href when clicked. For an accessible and user-friendly site, it is recommended to use buttons only for executing actions and using Links instead for navigating to other pages.
Additionally, you can set the openNewWindow prop to true if you want the link to open in a new window. Note: The icon prop will be overridden with a trailing icon indicating the link opens in a new window.
Disabled
Use the isDisabled prop to disable the button.
Note: It is recommended that screen readers be provided a reason for a button being in a disabled state. For example, if a form submit button is disabled because all fields must have valid inputs before the user is allowed to submit the form, it is helpful to convey this information so the user understands why the button is disabled. As shown in the example below, this can be achieved using the aria-describedby attribute and the VisuallyHidden component to point to off-screen content that conveys the reason for the disabled state.
Loading
Note: isDisabled takes precedence over isLoading. If both props are passed, the button will be disabled and the loading spinner will not be shown.
A UI concept which merges the loading spinner indicator into the action that invokes it. Primarily intended for use with forms where it gives users immediate feedback upon pressing submit.
The use of the ariaLoadingLabel prop is highly encouraged for accessibility standards. Be as descriptive as possible when coming up with a description. Common labels are 'Submitting Form', 'Downloading Files', 'Content is loading', etc.
When button is passed the ariaLoadingLabel prop, it also takes in the isLoading attribute to dynamically toggle the Loading Spinner to populate after the text within button.
<Button isLoading={true} ariaLoadingLabel="Downloading Files"> Submit</Button>With this feature, the accessibility of spinner changes so when being read by a screen reader, the live region of the button will be read. Visit the LoadingSpinner documentation to learn more about this accessibility feature.
Button Props
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
ariaLoadingLabel | string | - | - | Screen reader text describing the loading state of the Button; only used if isLoading is true |
children | React.ReactNode | - | - | The contents of the button component |
className | string | - | - | CSS class name to apply to each element within the component |
color | "brand" | "neutral" | "inverse" | "destructive" | 'brand' | - | The color of the Button |
css | Abyss.CSSProperties | Partial<Record<`abyss-${T}`, Abyss.CSSProperties>> | - | - | Object containing CSS styling to apply; uses the classes listed in the "Integration" tab of the component's documentation |
data-testid | string | - | - | Suffix used to create a unique ID used for automated testing |
disableDefaultProviderProps | boolean | false | - | If set to true, the component will not use the DefaultPropsProvider values. If you aren’t using the DefaultPropsProvider, this prop can be ignored. |
href | string | - | - | The href to navigate to |
icon | { icon: string; position: "leading" | "trailing" | "icon-only"; variant?: "filled" | "outlined" | undefined; } | - | - | The IconSymbol to insert into the Button |
isActive | boolean | - | - | If true, the Link is considered the active route |
isDisabled | boolean | false | - | If true, the Button is disabled |
isLoading | boolean | false | - | If true, the Button will be in a loading state; ariaLoadingLabel is required when using this prop |
isStandardAnchor | boolean | false | - | If true, ignore router and external Link checks |
onClick | (event: React.MouseEvent<HTMLElement, MouseEvent>) => void | - | - | Callback function executed when the Button is clicked |
openNewWindow | boolean | false | - | If true, the Link opens in a new window. By default, external links will open in a new window. |
routerComponent | React.ComponentType<any> | - | - | Custom router component to use for client-side navigation (e.g., Next.js Link, Gatsby Link, etc.) |
size | "sm" | "$sm" | "md" | "$md" | "lg" | "$lg" | 'md' | - | The size of the Button |
variant | "text" | "filled" | "outline" | 'filled' | - | The variant of the Button |
Button Classes
| Class Name | Description |
|---|---|
| .abyss-button-root | Button root element |
| .abyss-button-content-container | Content container element |
| .abyss-button-leading-icon | IconSymbol placed before the button content |
| .abyss-button-new-window-icon | Icon for new window anchor buttons |
| .abyss-button-trailing-icon | IconSymbol placed after the button content |
| .abyss-button-icon-only-icon | IconSymbol placed as the button content (icon-only position) |
| .abyss-button-loading-spinner | LoadingSpinner placed inside the button when `isLoading` is true |
| .abyss-button-active | Button root element when active |
A button is a widget that enables users to trigger an action or event, such as submitting a form, opening a dialog, canceling an action, or performing a delete operation. A common convention for informing users that a button launches a dialog is to append "…" (ellipsis) to the button label, e.g., "Save as…".
Adheres to the Button WAI-ARIA design pattern.
<Button>Click Here!</Button>Keyboard Interactions
| Key | Description |
|---|---|
| Space | Activates the button |
| Enter | Activates the button |
Disabled Accessibility Guidance
It is recommended that a screen reader be provided with a reason for a button being in a disabled state. For example if a form submit button is disabled because all fields must have valid inputs before the user is allowed to submit the form, it can be helpful to convey this information, so the user understands why the button is disabled. Target the disabled button state with the prop isDisabled, and use the aria-describedby attribute and the VisuallyHidden component to point to off-screen content that conveys the reason for the disabled state.
Loading State Button
For a loading state, button pulls in the Loading Spinner component and renders a status message to convey the action of loading without taking focus.
Loading Spinner is programmed through the ariaLoadingLabel property, and has been tested using a screen reader to present a status message to assistive technology without receiving focus.
Following the requirements of WAI-ARIA, Loading Spinner follows the requirements 4.1.3: Status Messages. Status messages are defined by WCAG as messages that provide information on the success or results of a user action, but do not change the users context (i.e. take focus).
The Toggle Loading button below can be used to toggle the loading state of the Submit button for screen readers.
Triggering Elements
Use the aria-haspopup attribute on buttons or other triggering elements that open content like dialogs, listboxes, trees, menus, grids, etc. Use a corresponding value that indicates what kind of popup will be displayed when the trigger element is activated. In turn, the element that pops up must be of the role indicated. For example, use aria-haspopup="dialog" on buttons that open modal dialogs. Be sure to include role="dialog" on the containing element of the dialog itself, too.
See the docs on aria-haspopup for more details.
Component Tokens
Note: Click on the token row to copy the token to your clipboard.
Button Tokens
| Token Name | Value | |
|---|---|---|
| button.color.text.label.filled-brand | #FFFFFF | |
| button.color.text.label.filled-disabled | #7D7F81 | |
| button.color.text.label.filled-neutral | #FFFFFF | |
| button.color.text.label.filled-destructive | #FFFFFF | |
| button.color.text.label.filled-inverse | #323334 | |
| button.color.text.label.outline-brand | #002677 | |
| button.color.text.label.outline-disabled | #7D7F81 | |
| button.color.text.label.outline-neutral | #323334 | |
| button.color.text.label.outline-destructive | #990000 | |
| button.color.text.label.outline-inverse.rest | #FFFFFF | |
| button.color.text.label.outline-inverse.hover | #F3F3F3 | |
| button.color.text.label.outline-inverse.active | #E5E5E6 | |
| button.color.text.label.text-brand.rest | #196ECF | |
| button.color.text.label.text-brand.hover | #004BA0 | |
| button.color.text.label.text-brand.active | #002677 | |
| button.color.text.label.text-disabled | #7D7F81 | |
| button.color.text.label.text-neutral.rest | #323334 | |
| button.color.text.label.text-neutral.hover | #222324 | |
| button.color.text.label.text-neutral.active | #000000 | |
| button.color.text.label.text-destructive.rest | #990000 | |
| button.color.text.label.text-destructive.hover | #B20000 | |
| button.color.text.label.text-destructive.active | #890000 | |
| button.color.text.label.text-inverse.rest | #FFFFFF | |
| button.color.text.label.text-inverse.hover | #F3F3F3 | |
| button.color.text.label.text-inverse.active | #E5E5E6 | |
| button.color.surface.container.filled-brand.rest | #002677 | |
| button.color.surface.container.filled-brand.hover | #004BA0 | |
| button.color.surface.container.filled-brand.active | #00184D | |
| button.color.surface.container.filled-neutral.rest | #323334 | |
| button.color.surface.container.filled-neutral.hover | #222324 | |
| button.color.surface.container.filled-neutral.active | #000000 | |
| button.color.surface.container.filled-destructive.rest | #990000 | |
| button.color.surface.container.filled-destructive.hover | #B20000 | |
| button.color.surface.container.filled-destructive.active | #990000 | |
| button.color.surface.container.filled-inverse.rest | #FFFFFF | |
| button.color.surface.container.filled-inverse.hover | #F3F3F3 | |
| button.color.surface.container.filled-inverse.active | #E5E5E6 | |
| button.color.surface.container.outline-brand.rest | #FFFFFF | |
| button.color.surface.container.outline-brand.hover | #EDF3FB | |
| button.color.surface.container.outline-brand.active | #E3EEFA | |
| button.color.surface.container.outline-neutral.rest | #FFFFFF | |
| button.color.surface.container.outline-neutral.hover | #FAF8F2 | |
| button.color.surface.container.outline-neutral.active | #F5F3ED | |
| button.color.surface.container.outline-destructive.rest | #FFFFFF | |
| button.color.surface.container.outline-destructive.hover | #FCF0F0 | |
| button.color.surface.container.outline-destructive.active | #F9D1D1 | |
| button.color.surface.container.filled-disabled | #F3F3F3 | |
| button.color.surface.container.outline-disabled | #F3F3F3 | |
| button.color.surface.loading-spinner.text-brand | #196ECF | |
| button.color.surface.loading-spinner.outline-neutral | #4B4D4F | |
| button.color.surface.loading-spinner.text-neutral | #4B4D4F | |
| button.color.surface.loading-spinner.outline-destructive | #990000 | |
| button.color.surface.loading-spinner.text-destructive | #990000 | |
| button.color.surface.loading-spinner.filled-inverse | #4B4D4F | |
| button.color.border.outline-brand | #002677 | |
| button.color.border.outline-disabled | #7D7F81 | |
| button.color.border.outline-neutral | #323334 | |
| button.color.border.outline-destructive | #990000 | |
| button.color.border.outline-inverse.rest | #FFFFFF | |
| button.color.border.outline-inverse.hover | #F3F3F3 | |
| button.color.border.outline-inverse.active | #E5E5E6 | |
| button.color.icon.filled-brand | #FFFFFF | |
| button.color.icon.filled-disabled | #7D7F81 | |
| button.color.icon.filled-neutral | #FFFFFF | |
| button.color.icon.filled-destructive | #FFFFFF | |
| button.color.icon.filled-inverse | #323334 | |
| button.color.icon.outline-brand | #002677 | |
| button.color.icon.outline-disabled | #7D7F81 | |
| button.color.icon.outline-neutral | #323334 | |
| button.color.icon.outline-destructive | #990000 | |
| button.color.icon.outline-inverse.rest | #FFFFFF | |
| button.color.icon.outline-inverse.hover | #F3F3F3 | |
| button.color.icon.outline-inverse.active | #E5E5E6 | |
| button.color.icon.text-brand.rest | #196ECF | |
| button.color.icon.text-brand.hover | #004BA0 | |
| button.color.icon.text-brand.active | #002677 | |
| button.color.icon.text-disabled | #7D7F81 | |
| button.color.icon.text-neutral.rest | #323334 | |
| button.color.icon.text-neutral.hover | #222324 | |
| button.color.icon.text-neutral.active | #000000 | |
| button.color.icon.text-destructive.rest | #990000 | |
| button.color.icon.text-destructive.hover | #B20000 | |
| button.color.icon.text-destructive.active | #890000 | |
| button.color.icon.text-inverse.rest | #FFFFFF | |
| button.color.icon.text-inverse.hover | #F3F3F3 | |
| button.color.icon.text-inverse.active | #E5E5E6 | |
| button.border-radius.all.container | 500px | |
| button.border-width.all.container | 1px | |
| button.sizing.all.icon | 16px | |
| button.sizing.all.icon-only.container.sm | 32px | |
| button.sizing.all.icon-only.container.md | 40px | |
| button.sizing.all.icon-only.container.lg | 48px | |
| button.sizing.all.icon-only.icon | 24px | |
| button.sizing.height.min.container.sm | 32px | |
| button.sizing.height.min.container.md | 40px | |
| button.sizing.height.min.container.lg | 48px | |
| button.spacing.gap.horizontal.container | 8px | |
| button.spacing.padding.horizontal.container.sm | 16px | |
| button.spacing.padding.horizontal.container.md | 24px | |
| button.spacing.padding.horizontal.container.lg | 24px | |
| button.spacing.padding.vertical.container.sm | 4px | |
| button.spacing.padding.vertical.container.md | 8px | |
| button.spacing.padding.vertical.container.lg | 12px |