# Button

Pill button that presses down under your finger, in eight styles from solid to glass, with a built-in loading state that swaps in place while an action runs.

> Primitive · Free · Actions — React Native, Expo Go compatible.

## Install

```bash
npx @lumioui/cli add button
```

## Import

```tsx
import { Button } from "@/components/ui/button/button";
```

## Variants

- `glass` — Glass: `npx @lumioui/cli add button-glass`
- `sizes` — Sizes: `npx @lumioui/cli add button-sizes`
- `styles` — Styles: `npx @lumioui/cli add button-styles`

## Props

| Prop | Type | Notes |
| --- | --- | --- |
| `onPress?` | `| ((e: GestureResponderEvent) => void) | ((e: GestureResponderEvent) => Promise<unknown>) | null` | Press handler — may return a Promise. With asyncTracking (default) the  button enters the loading state until the promise settles. Declared as  a union of signatures rather than `void | Promise<unknown>` so `void`  keeps its leniency — handlers returning other values (e.g. a timeout  id) still typecheck. |
| `variant?` | `"default" | "destructive" | "outline" | "tinted" | "secondary" | "ghost" | "link" | "glass"` | Visual style — "glass" is the glass material button. |
| `tone?` | `"accent" | "inverse" | "surface"` | Fill voice for the default variant — `inverse` is the near-black CTA,  `surface` a bordered card-colored button. Default "accent". |
| `radius?` | `"pill" | "xl" | "lg" | "md"` | Corner radius. Default "pill". |
| `size?` | `"sm" | "md" | "lg" | "icon"` | Size preset. |
| `loading?` | `boolean` | Swap the label for busy dots and block presses while true. |
| `asyncTracking?` | `boolean` | Auto-track async onPress — when onPress returns a Promise, the button  automatically enters loading state until it resolves. Default true. |
| `sheenOnResolve?` | `boolean` | @deprecated No effect: busy resolves by swapping the label back in place. |
| `haptic?` | `"light" | "medium" | "heavy" | false` | Haptic feedback on press. Default "light"; false to disable. |
| `pressedScale?` | `number` | Override the press-dip scale (1 = none). ButtonGroup sets this to 1 on  attached children — a scaled segment opens a gap in the weld. |
| `className?` | `string` | Extra NativeWind classes for the container. |
| `textClassName?` | `string` | Extra classes for the label. |
| `icon?` | `React.ReactNode` | Icon rendered before the label. |
| `ripple?` | `boolean` | Ignite a glow from the touch point that spreads as it dims (`ripple`).  Off by default; skipped under reduced motion. |
| `children?` | `React.ReactNode` | — |

Source: https://lumioui.com/components/button