Button
freeButton gives product actions a consistent hierarchy across forms, dialogs, and toolbars.
Preview
Dark
import Button from '@/components/ui/Button';
export default function UsageDemo() {
return (
<div className="inline-flex flex-wrap items-center justify-center gap-2">
<Button variant="solid">Save changes</Button>
<Button>Cancel</Button>
</div>
);
}Installation
Add this component with the NateUI CLI.
npx nateui@latest add ButtonExamples
Variants
Preview
Dark
import Button from '@/components/ui/Button';
export default function VariantDemo() {
return (
<div className="inline-flex flex-wrap items-center justify-center gap-2">
<Button>Default</Button>
<Button variant="solid">Solid</Button>
<Button variant="subtle">Subtle</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
</div>
);
}Sizes
Preview
Dark
import Button from '@/components/ui/Button';
export default function SizeDemo() {
return (
<div className="inline-flex flex-wrap items-center justify-center gap-2">
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
</div>
);
}Shapes
Preview
Dark
import { PiPlus } from 'react-icons/pi'
import Button from '@/components/ui/Button';
export default function ShapeDemo() {
return (
<div className="inline-flex flex-wrap items-center justify-center gap-2">
<Button shape="round">Round</Button>
<Button shape="none">None</Button>
<Button shape="circle" icon={<PiPlus />} aria-label="Add item" />
</div>
);
}States
Preview
Dark
import Button from '@/components/ui/Button';
export default function StatesDemo() {
return (
<div className="inline-flex flex-wrap items-center justify-center gap-2">
<Button active>Active</Button>
<Button disabled>Disabled</Button>
<Button loading>Loading</Button>
</div>
);
}Destructive
Preview
Dark
import Button from '@/components/ui/Button';
export default function DestructiveDemo() {
return (
<div className="inline-flex flex-wrap items-center justify-center gap-2">
<Button destructive>Default</Button>
<Button destructive variant="solid">
Solid
</Button>
<Button destructive variant="subtle">
Subtle
</Button>
<Button destructive variant="ghost">
Ghost
</Button>
<Button destructive variant="link">
Link
</Button>
</div>
);
}Icons
Preview
Dark
import { PiArrowRight, PiEnvelope, PiPlus } from 'react-icons/pi'
import Button from '@/components/ui/Button';
export default function IconDemo() {
return (
<div className="inline-flex flex-wrap items-center justify-center gap-2">
<Button icon={<PiEnvelope />}>Start icon</Button>
<Button icon={<PiArrowRight />} iconAlignment="end">
End icon
</Button>
<Button icon={<PiPlus />} aria-label="Add item" />
</div>
);
}Block
Preview
Dark
import Button from '@/components/ui/Button';
export default function BlockDemo() {
return (
<div className="w-80 max-w-full space-y-2">
<Button block variant="solid">
Full width action
</Button>
<Button block>Secondary action</Button>
</div>
);
}API
Button accepts the props below plus native props for the rendered element.
| Prop | Description | Type | Default |
|---|---|---|---|
asElement | Root element or component rendered by the button. | ElementType | 'button' |
active | Marks the button as active and applies the active visual state. | boolean | false |
block | Expands the button to the full width of its container. | boolean | false |
children | Button label or content. | ReactNode | - |
className | Static class string or state-aware class callback. | ButtonClassName | - |
clickFeedback | Enables the press-down transform feedback on activation. | boolean | true |
destructive | Switches the button into the destructive intent palette. | boolean | false |
disabled | Prevents interaction and applies the disabled visual state. | boolean | false |
icon | Icon content rendered with, or instead of, the label. | string | ReactNode | - |
iconAlignment | Icon placement when both icon and label are present. | ButtonIconAlignment | 'start' |
loading | Shows a spinner and prevents repeat activation. | boolean | false |
onClick | Click handler invoked only when the button is not disabled or loading. | ButtonClickHandler | - |
ref | Ref forwarded to the underlying button element. | Ref<HTMLButtonElement> | - |
shape | Border radius treatment. | ButtonShape | 'round' |
size | Control size. Falls back to InputGroup size, then ConfigProvider control size. | ControlSize | 'md' from ConfigProvider |
variant | Visual style. | ButtonVariant | 'default' |
...nativeProps | Native props for the rendered element, excluding Button-owned props. | NativeButtonProps<E> | - |
Types
type ButtonVariant = 'solid' | 'subtle' | 'default' | 'ghost' | 'link';
type ControlSize = 'sm' | 'md' | 'lg';
type ButtonShape = 'round' | 'circle' | 'none';
type ButtonIconAlignment = 'start' | 'end';
type ButtonClickHandler = (event: MouseEvent<HTMLButtonElement>) => void;
type ButtonClassName =
| string
| ((state: {
active: boolean;
destructive: boolean;
unclickable: boolean;
}) => string);
type NativeButtonProps<E extends ElementType> = Omit<
ComponentPropsWithoutRef<E>,
| 'asElement'
| 'active'
| 'block'
| 'className'
| 'clickFeedback'
| 'destructive'
| 'disabled'
| 'icon'
| 'iconAlignment'
| 'loading'
| 'onClick'
| 'ref'
| 'shape'
| 'size'
| 'variant'
>;