# Button
**Category**: react
**URL**: https://www.heroui.com/docs/react/migration/button
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/migration/(components)/button.mdx
> Migration guide for Button from HeroUI v2 to v3
***
Refer to the [v3 Button documentation](/docs/react/components/button) for complete API reference, styling guide, and advanced examples. This guide only focuses on migrating from HeroUI v2.
## Structure Changes
In v2, `Button` used a combination of `color` and `variant` props:
```tsx
import { Button } from "@heroui/react";
export default function App() {
return ;
}
```
In v3, Button uses only the `variant` prop (no separate `color` prop):
```tsx
import { Button } from "@heroui/react";
export default function App() {
return ;
}
```
## Key Changes
### 1. Variants and Colors
**v2:** Used `color` + `variant` combination
**v3:** Uses `variant` only (no separate `color` prop)
| v2 Color + Variant | v3 Variant | Notes |
|-------------------|------------|-------|
| `color="primary" variant="solid"` | `variant="primary"` | Default primary button |
| `color="default" variant="solid"` | `variant="primary"` | Use primary variant |
| `color="secondary" variant="solid"` | `variant="secondary"` | Same |
| `color="success" variant="solid"` | `variant="primary"` | Use primary with custom styling if needed |
| `color="warning" variant="solid"` | `variant="primary"` | Use primary with custom styling if needed |
| `color="danger" variant="solid"` | `variant="danger"` | Danger variant available |
| `color="primary" variant="bordered"` | `variant="secondary"` | Similar appearance |
| `color="primary" variant="light"` | `variant="tertiary"` | Similar appearance |
| `color="primary" variant="flat"` | `variant="tertiary"` | Similar appearance |
| `color="primary" variant="faded"` | `variant="secondary"` | Similar appearance |
| `color="primary" variant="ghost"` | `variant="ghost"` | Same |
| `color="danger" variant="flat"` | `variant="danger-soft"` | New soft danger variant |
**v2 Variants:** `solid`, `bordered`, `light`, `flat`, `faded`, `shadow`, `ghost`
**v3 Variants:** `primary`, `secondary`, `tertiary`, `outline`, `ghost`, `danger`, `danger-soft`
### 2. Loading State: `isLoading` → `isPending`
**v2:** Used `isLoading` prop
**v3:** Uses `isPending` prop
### 3. Default Width Behavior
**v2:** Buttons had minimum widths based on size (`min-w-16` for sm, `min-w-20` for md, `min-w-24` for lg)
**v3:** Buttons use `w-fit` by default (width fits content, no minimum width)
This means v3 buttons will be narrower than v2 buttons when they have short text. To maintain v2's minimum width behavior, add Tailwind classes see the [Minimum Width](#minimum-width) example section.
### 4. Prop Changes
| v2 Prop | v3 Location | Notes |
|---------|-------------|-------|
| `isLoading` | `Button` | Renamed to `isPending` |
| `isIconOnly` | `Button` | Still available in v3 — renders a square button with only an icon |
| `color` | - | Removed (variants handle styling) |
| `radius` | - | Removed (use Tailwind e.g. `rounded-lg`) |
| `startContent`, `endContent` | - | Place icons as children |
| `spinner`, `spinnerPlacement` | - | Handle loading manually with render props |
| `disableRipple` | - | Removed (ripple removed in v3) |
| `disableAnimation` | - | Removed (animations handled internally) |
| `classNames` | - | Use `className` |
### 5. ButtonGroup Available
**v2:** Had a dedicated `ButtonGroup` component
**v3:** `ButtonGroup` continues to exist. See the [ButtonGroup migration guide](/docs/react/migration/button-group) for details.
## Migration Examples
### Variants
```tsx
```
```tsx
```
### Danger Soft Variant
The `danger-soft` variant is new in v3. It replaces the v2 pattern of using a flat danger button.
```tsx
```
```tsx
```
### Icon Only (`isIconOnly`)
The `isIconOnly` prop is available in both v2 and v3. It renders a square button sized to fit a single icon. In v3, use `variant` instead of `color` for styling.
```tsx
```
```tsx
import { Icon } from "@iconify/react";
```
### Loading State
```tsx
{/* Simple loading */}
{/* Loading with conditional content */}
```
```tsx
import { useState } from "react";
import { Spinner } from "@heroui/react";
import { Icon } from "@iconify/react";
const [isLoading, setIsLoading] = useState(false);
{/* Simple loading */}
{/* Loading with conditional content */}
```
### With Icons
```tsx
import { Icon } from "@iconify/react";
}
>
Take a photo
}
variant="bordered"
>
Delete user
```
```tsx
import { Icon } from "@iconify/react";
```
### Icon Only Button
```tsx
```
```tsx
import { Icon } from "@iconify/react";
```
### Button Group
```tsx
import { Button, ButtonGroup } from "@heroui/react";
```
```tsx
import { Button, ButtonGroup } from "@heroui/react";
```
### Sizes and Minimum Width
```tsx
{/* v2 automatically applies minimum widths */}
```
```tsx
{/* v3 uses w-fit by default - add min-width to match v2 */}
```
## Render Props Pattern
v3 Button supports a render prop pattern that provides state information:
```tsx
```
Available render props:
- `isPending` - Whether button is in loading state
- `isPressed` - Whether button is currently pressed
- `isHovered` - Whether button is hovered
- `isFocused` - Whether button is focused
- `isFocusVisible` - Whether button should show focus indicator
- `isDisabled` - Whether button is disabled
## Summary
1. **Color Prop Removed**: Use `variant` prop instead of `color` + `variant`
2. **Variants Changed**: New variant system (`primary`, `secondary`, `tertiary`, `outline`, `ghost`, `danger`, `danger-soft`)
3. **`danger-soft` Variant**: New in v3, replaces v2's `color="danger" variant="flat"` pattern
4. **isLoading → isPending**: Loading prop renamed
5. **isIconOnly**: Still supported in v3 — renders a square button for icon-only use
6. **Default Width Changed**: Buttons now use `w-fit` instead of minimum widths - add `min-w-*` classes to match v2 behavior
7. **Icons**: `startContent`/`endContent` removed - place icons as children
8. **Loading Spinner**: Must handle spinner manually with render props
9. **Render Props**: v3 Button children can be a function receiving `isPending`, `isPressed`, `isHovered`, `isFocused`, `isFocusVisible`, and `isDisabled`
10. **Radius Removed**: Use Tailwind CSS classes
11. **Ripple Removed**: No ripple effect in v3
12. **ButtonGroup Available**: See [ButtonGroup migration guide](/docs/react/migration/button-group)
13. **ClassNames Removed**: Use `className` prop