---
title: Button
description: Displays a button or a link that looks like a button.
featured: true
component: true
---
## Usage
```tsx
import { Button } from '@/components/ui/button'
```
```tsx
```
## Link
You can use the `buttonVariants` helper to create a link that looks like a button.
```tsx
import { buttonVariants } from '@/components/ui/button'
```
```tsx
Click here
```
Alternatively, you can set the `asChild` parameter and nest the link component.
```tsx
```
## Examples
### Sizes
Use the `size` prop to determine the size of the button.
### Variants
#### Default
Used when no `variant` is specified. Prefer this unless another variant fits better, as below.
#### Primary
Use sparingly for data insertion, confirming purchases, and other strong positive actions. Because it is so prominent, aim for at most one primary button in a viewport.
#### Secondary
Can be used for signaling a data or config change, but not as serious as a primary button.
For destructive or side effect actions, use the `destructive` or `warning` variant.
#### Warning
Used for actions that might have a side effect, but not as serious as a destructive action.
#### Destructive (currently `danger`)
Used for actions that will have a serious destructive side effect, like deleting data.
prop `variant` will probably be changed to `destructive` in the future.
#### Outline
Used for secondary actions, or actions that are not as important as the primary action.
#### Ghost (currently `text`)
Used for actions that are not as important as the primary action, or for actions that are not as important as the primary action.
prop `variant` will probably be changed to `ghost` in the future.
#### Link
Used for actions that are not as important as the primary action, or for actions that are not as important as the primary action.
### Icon-only
Render an [icon](./icons) in a button without accompanying text. Ensure the button is accessible by:
- Wrapping it in a [Tooltip](./tooltip) for sighted users.
- Adding an `aria-label` prop for screen readers.
- Setting its `aria-describedby` prop to `undefined` when the tooltip content repeats the label. Otherwise screen readers read the label twice.
Consider also squaring off the button container as shown in the example below. For the default `tiny` size (`h-[26px]`), use `w-6.5` so the button is square.
Compact icon-only buttons may also benefit from the `hit-area` utility. This increases their tap target slightly each side without changing the visual layout. See the [Table](./table#actions) component for more information.
### As child
Supports slot behavior with `asChild` prop.
### Split with dropdown
Pair a button with a chevron `DropdownMenu` trigger when there are variations of the same action, or alternative ways to accomplish the same goal. The default or most likely option should be used on the exposed button.
When secondary actions are related but distinct (not alternatives to the primary action) display the primary action as a button and place the rest in an overflow menu instead. See [Table multiple actions](./table#multiple-actions).
Ensure the middle border is shared rather than doubled-up. Do not use `border-l-0` on the chevron button as that drops the divider on hover/focus. Instead:
- Primary action: `rounded-r-none` and `hover:z-10` so its border stacks above the chevron on hover.
- Chevron trigger: `rounded-l-none`, `shrink-0`, `px-[4px] py-[5px]`, and `-ml-px` to overlap the adjacent border by one pixel.
- Both: `focus-visible:z-10` so the focus ring stacks above the neighbour, and `focus-visible:rounded-r-sm` / `focus-visible:rounded-l-sm` so the squared-off edge is slightly rounded while the ring is shown.
- Chevron trigger only: `aria-label` describing the menu (the icon is decorative).
Inside [Admonition](../fragments/admonition#split-button-with-dropdown) actions when `layout="responsive"`: also use `flex w-full @lg:w-auto` with `flex-1 @lg:flex-none` on the primary action.
## Default fill and floating buttons
The default variant is meant to read as raised chrome on whatever surface it sits on.
- **Light:** opaque `bg-card` (a solid elevated plate). Opaque on purpose so the button can cover busy content underneath.
- **Dark:** translucent `bg-muted` (a foreground wash). That adapts to the local surface, but content can show through the fill.
Hover: light uses `hover:bg-muted`; dark uses `dark:hover:bg-accent`.
### Floating over content
If a default button is absolutely or sticky-positioned over code, tables, maps, or other busy UI, wrap it in [`FloatingPlate`](#floating-plate) so nothing bleeds through:
Keep positioning, z-index, and hover/focus reveal on the plate's `className`. Use `rounded="full"` when the child is a pill. For clusters (split toggles, parallel actions), wrap the group once.
Do not override the button fill with `bg-popover` at the callsite. The plate owns occlusion; the button stays a normal default control.
## Floating plate
`FloatingPlate` is an opaque `bg-popover` shell for floating default buttons (and small clusters).
```tsx
import { Button, FloatingPlate } from 'ui'
```
| Prop | Default | Notes |
| ----------- | ------- | --------------------------------------------------------------- |
| `rounded` | `lg` | `md`, `lg`, or `full`. Match or exceed the child button radius. |
| `className` | — | Positioning, opacity, gaps for clusters. |
See [Floating over content](#floating-over-content) for when to use it.
## Accessibility
[Keyboard focus](../accessibility#focus-management) is automatically handled:
- Enabled buttons default to `tabIndex={0}` (keyboard accessible)
- Buttons with native `disabled` default to `tabIndex={-1}` (removed from tab order)
- You can still override with an explicit `tabIndex` prop when needed
- Keyboard focus uses the shared `focus-ring` utility; variants do not change ring colour
You therefore don't need to manually set `tabIndex` for buttons using native `disabled`.
When a disabled action has a non-obvious reason and needs a tooltip, add `focusableWhenDisabled` so keyboard users can still focus the control. See [Disabled controls](../accessibility#disabled-controls).
### Focusable when disabled
Use `focusableWhenDisabled` with `disabled` when the action is blocked for a non-obvious reason and you need a tooltip or other explanation. The control stays in the tab order and uses `aria-disabled` instead of native `disabled`.
```tsx
```
In Studio, `ButtonTooltip` adds `focusableWhenDisabled` to disabled buttons with tooltip text automatically.