export const title = "Button components"
export const description = "Free and open-source React button components built for modern applications and websites. These buttons are built using React Aria and styled with Tailwind CSS."
export const links = {
github: "https://github.com/untitleduico/react/tree/main/components/base/buttons",
rac: "https://react-spectrum.adobe.com/react-aria/Button.html"
}
import * as Demos from "@/components/base/buttons/buttons.demo.tsx";
import { Check, Edit03, Trash01, Placeholder } from "@untitledui/icons";
}>Publish now
```jsx
import { Check } from "@untitledui/icons";
import { Button } from "@/components/base/buttons/button";
}>Publish now
```
## Installation
You can add this button component using our CLI or manually:
```bash
npx untitledui@latest add button
```
Copy the files below into your project:
Great! Now you can start using the button components in your project by just copy/pasting our examples below.
## Button examples
Below are examples and variations of this button component:
### Primary buttons {{ tocOnly:true }}
```jsx
import { Button } from "@/components/base/buttons/button";
```
### Link color buttons
We've designed our button components to be "hybrid," meaning they can function as either a link or a standard button with ease. This offers several benefits, for example, there are many situations where you might want a link that behaves like a button, or a button that acts as a link. These two essential components work interchangeably, so it was important for us to make them easy to use.
You can turn the button component into an anchor by simply passing the `href` prop. When the `href` prop is present, the button component uses the `Link` component from React Aria under the hood instead of `Button`. This means you can pass any props or attributes that an anchor tag would accept when `href` is provided.
```jsx
import { Button } from "@/components/base/buttons/button";
```
### Link gray buttons {{ tocOnly:true }}
```jsx
import { Button } from "@/components/base/buttons/button";
```
### Icon leading buttons
Our button component accepts the `iconLeading` and `iconTrailing` props to add an icon to the button. These icons should be either a function component that accepts a `className` prop or a JSX element with a `data-icon` attribute.
In server components, where you cannot directly pass a function component as a prop, we recommend passing a JSX element with a `data-icon` attribute to apply the button icon styles to the icon.
}>Button xs
}>Button sm
}>Button md
}>Button lg
}>Button xl
}>Button xs
}>Button sm
}>Button md
}>Button lg
}>Button xl
}>Button xs
}>Button sm
}>Button md
}>Button lg
}>Button xl
```jsx
import { Placeholder } from '@untitledui/icons';
import { Button } from "@/components/base/buttons/button";
}>Button xs
}>Button sm
}>Button md
}>Button lg
}>Button xl
}>Button xs
}>Button sm
}>Button md
}>Button lg
}>Button xl
}>Button xs
}>Button sm
}>Button md
}>Button lg
}>Button xl
```
### Icon trailing buttons
Similar to the `iconLeading` prop, you can display a trailing icon by passing a function component or a JSX element with a `data-icon` attribute to the `iconTrailing` prop.
}>Button xs
}>Button sm
}>Button md
}>Button lg
}>Button xl
}>Button xs
}>Button sm
}>Button md
}>Button lg
}>Button xl
}>Button xs
}>Button sm
}>Button md
}>Button lg
}>Button xl
```jsx
import { Placeholder } from '@untitledui/icons';
import { Button } from "@/components/base/buttons/button";
}>Button xs
}>Button sm
}>Button md
}>Button lg
}>Button xl
}>Button xs
}>Button sm
}>Button md
}>Button lg
}>Button xl
}>Button xs
}>Button sm
}>Button md
}>Button lg
}>Button xl
```
### Icon only buttons
You can also display an icon only button by omitting the button children and passing an icon to the `iconLeading` or `iconTrailing` prop.
Please note that, it's recommended to pass an `aria-label` to the button when using an icon only button in order to provide a better experience for screen readers as the icons themselves do not provide any context.
```jsx
import { Placeholder } from '@untitledui/icons';
import { Button } from "@/components/base/buttons/button";
} aria-label="Button CTA" />
} aria-label="Button CTA" />
} aria-label="Button CTA" />
} aria-label="Button CTA" />
} aria-label="Button CTA" />
} aria-label="Button CTA" />
} aria-label="Button CTA" />
} aria-label="Button CTA" />
} aria-label="Button CTA" />
} aria-label="Button CTA" />
} aria-label="Button CTA" />
} aria-label="Button CTA" />
} aria-label="Button CTA" />
} aria-label="Button CTA" />
} aria-label="Button CTA" />
```
### Loading buttons
Our button component makes it easy to implement loading states with the `isLoading` prop. When enabled, the button automatically displays a spinner and becomes non-interactive to prevent multiple submissions. You can control whether to show the button text alongside the spinner using the `showTextWhileLoading` prop—this is particularly useful for providing context about what's happening. The loading spinner is automatically sized and styled to match your button's size and color variant.
```jsx
import { Button } from "@/components/base/buttons/button";
```
### Disabled buttons
Our button component handles disabled states through the `isDisabled` prop, which applies appropriate styling and removes all interactive functionality. When disabled, buttons automatically change their appearance to indicate that they are not clickable, change their cursor to a not-allowed cursor, and any associated actions or navigation are prevented. The disabled styling is consistent across all button variants and sizes, ensuring a cohesive user experience throughout your application while maintaining accessibility standards.
```jsx
import { Button } from "@/components/base/buttons/button";
```
### Primary buttons destructive
Our button component provides three destructive variants: `primary-destructive`, `secondary-destructive`, and `tertiary-destructive`. Each variant maintains the same interaction patterns as their non-destructive counterparts while applying appropriate warning colors and styling. You can use these variants just like regular buttons, and they support all the same features including icons, loading states, and disabled states, ensuring consistency across your application's destructive actions.