Files
Pasquale Vitiello 6c39b45718 refactor(button): add loading prop (#719)
* feat: add loading prop to button

* always decrease the opacity if disabled

* rebuild the registry

* add a new particle

* mc
2026-03-16 16:26:30 +01:00

186 lines
4.3 KiB
Plaintext

---
title: Button
description: A button or a component that looks like a button.
---
<ComponentPreview name="p-button-1" />
## Installation
<CodeTabs>
<TabsList>
<TabsTab value="cli">CLI</TabsTab>
<TabsTab value="manual">Manual</TabsTab>
</TabsList>
<TabsPanel value="cli">
```bash
npx shadcn@latest add @coss/button
```
</TabsPanel>
<TabsPanel value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Import the following variables into your CSS file</Step>
```css
@theme inline {
--color-destructive-foreground: var(--destructive-foreground);
}
:root {
--destructive-foreground: var(--color-red-700);
}
.dark {
--destructive-foreground: var(--color-red-400);
}
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="button" title="components/ui/button.tsx" />
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsPanel>
</CodeTabs>
## Usage
```tsx
import { Button } from "@/components/ui/button"
```
```tsx
<Button>Button</Button>
```
## Link
You can use the [`render`](https://base-ui.com/react/utils/use-render#migrating-from-radix-ui) prop to make another component look like a button. Here's an example of a link that looks like a button.
```tsx
import Link from "next/link"
import { Button } from "@/components/ui/button"
export function LinkAsButton() {
return <Button render={<Link href="/login" />}>Login</Button>
}
```
## API Reference
This is a custom component using Base UI's `useRender` hook, not a direct Base UI wrapper.
### Button
A button component with variant, size, and loading states.
| Prop | Type | Default | Description |
| --------- | ----------------------------------------------------------------------------------------------------------------- | ----------- | --------------------------------------------------------------------------- |
| `variant` | `"default" \| "destructive" \| "destructive-outline" \| "ghost" \| "link" \| "outline" \| "secondary"` | `"default"` | Controls the button styling |
| `size` | `"default" \| "icon" \| "icon-lg" \| "icon-sm" \| "icon-xl" \| "icon-xs" \| "lg" \| "sm" \| "xl" \| "xs"` | `"default"` | Controls the button size |
| `loading` | `boolean` | `false` | Shows a spinner and forces disabled button behavior while loading |
| `render` | `React.ReactElement` | - | Render as a different element (e.g., Link) |
When `loading` is `true`, the component:
- Renders a spinner (`data-slot="button-loading-indicator"`)
- Adds `data-loading` on the button root
- Forces the native `disabled` attribute
- Sets `aria-disabled="true"`
- Preserves button width by hiding content visually instead of unmounting it
## Examples
### Default
<ComponentPreview name="p-button-1" />
### Outline
<ComponentPreview name="p-button-2" />
### Secondary
<ComponentPreview name="p-button-3" />
### Destructive
<ComponentPreview name="p-button-4" />
### Destructive Outline
<ComponentPreview name="p-button-5" />
### Ghost
<ComponentPreview name="p-button-6" />
### Link
<ComponentPreview name="p-button-7" />
### Extra-small Size
<ComponentPreview name="p-button-8" />
### Small Size
<ComponentPreview name="p-button-9" />
### Large Size
<ComponentPreview name="p-button-10" />
### Extra-large Size
<ComponentPreview name="p-button-11" />
### Disabled
<ComponentPreview name="p-button-12" />
### Icon
<ComponentPreview name="p-button-13" />
### Icon Small Size
<ComponentPreview name="p-button-14" />
### Icon Large Size
<ComponentPreview name="p-button-15" />
### With Icon
<ComponentPreview name="p-button-16" />
### With Link
<ComponentPreview name="p-button-17" />
### Loading (Built-in Prop)
<ComponentPreview name="p-button-41" />
### Loading (Custom Composition)
<ComponentPreview name="p-button-18" />