laif-ds
Version:
Design System di Laif con componenti React basati su principi di Atomic Design
130 lines (97 loc) • 5.42 kB
Markdown
Versatile button with multiple variants and sizes, optional leading/trailing icons, loading state, and support for rendering as a child element.
---
| Prop | Type | Default | Description |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------- | -------------------------------------------------------- |
| `variant` | `"default" | "destructive" | "outline" | "outline-primary" | "outline-destructive" | "secondary" | "ghost" | "ghost-destructive" | "ghost-accent" | "link"` | `"default"` | Visual style of the button. |
| `size` | `"default" | "sm" | "lg" | "icon"` | `"default"` | Size of the button. |
| `asChild` | `boolean` | `false` | Render as child (e.g., anchor) while preserving styles. |
| `iconLeft` | `IconName` | `undefined` | Optional left icon name. |
| `iconRight` | `IconName` | `undefined` | Optional right icon name. |
| `isLoading` | `boolean` | `false` | Shows a loading spinner; overrides `iconLeft`. |
| `className` | `string` | `""` | Additional classes for layout/width. |
| `disabled` | `boolean` | `false` | Disables the button. |
| `onClick` | `(e: React.MouseEvent<HTMLButtonElement>) => void` | `undefined` | Click handler. |
| `children` | `React.ReactNode` | **required** | Button label or content. |
---
- **Loading**: When `isLoading` is `true`, a spinner is shown and `iconLeft` is hidden.
- **Icons**: Icon sizes adapt to the button size (`sm`, `default`, `lg`, `icon`).
- **As Child**: Use `asChild` to render the button as a link or custom element while keeping button styles.
- **Accessibility**: Keyboard-focus ring and proper semantics are included.
---
## Examples
### Default
```tsx
import { Button } from "laif-ds";
export function DefaultButton() {
return <Button>Button</Button>;
}
```
```tsx
import { Button, type ButtonProps } from "laif-ds";
const variants: ButtonProps["variant"][] = [
"default",
"destructive",
"outline",
"outline-primary",
"outline-destructive",
"secondary",
"ghost",
"ghost-accent",
"ghost-destructive",
"link",
];
const sizes: ButtonProps["size"][] = ["lg", "default", "sm", "icon"];
export function ButtonsGrid() {
return (
<div className="flex flex-col gap-4">
{variants.map((variant) => (
<div key={variant} className="flex items-center gap-2 flex-wrap">
{sizes.map((size) => (
size === "icon" ? (
<Button key={`${variant}-${size}`} variant={variant} size={size} iconLeft="BadgeInfo" />
) : (
<Button key={`${variant}-${size}`} variant={variant} size={size}>
{variant} - {size}
</Button>
)
))}
</div>
))}
</div>
);
}
```
```tsx
import { Button } from "laif-ds";
export function FullWidthButton() {
return (
<Button className="w-full">Full Width Button</Button>
);
}
```
```tsx
import { Button } from "laif-ds";
export function WithIcon() {
return <Button iconLeft="Check">Button with Icon</Button>;
}
```
```tsx
import { Button } from "laif-ds";
export function LoadingButton() {
return <Button isLoading>Loading Button</Button>;
}
```
---
- **Disabled**: Applies reduced opacity and prevents interactions.
- **Icon-only**: Use `size="icon"` for square icon buttons.
- **Theming**: Use variants to match semantic meaning (primary, destructive, etc.).