alouette
Version:
A modern, customizable design system built on top of NativeWind v5 with configurable defaults
152 lines (107 loc) • 4.04 kB
Markdown
---
name: alouette-actions
description: >
Buttons (Button, IconButton, ExternalLinkButton, InternalLinkButton) and
pressable surfaces (PressableBox, PressableListItem). variant is
contained|outlined|ghost, size is sm|md, accent defaults to brand. Button
label is the required text prop (not children); IconButton
requires aria-label. Interactive hover/focus/active/disabled states are built
in. Load when adding buttons or custom pressable elements.
type: core
library: alouette
library_version: "20.1.0"
requires:
- alouette-theming
sources:
- "christophehurpeau/alouette:packages/alouette/src/ui/actions/Button.tsx"
- "christophehurpeau/alouette:packages/alouette/src/ui/actions/IconButton.tsx"
- "christophehurpeau/alouette:packages/alouette/src/ui/data/PressableBox.tsx"
- "christophehurpeau/alouette:packages/alouette/src/ui/data/PressableListItem.tsx"
---
This skill builds on alouette-theming. Read it first for the accent model.
# alouette — Actions
Buttons and pressables carry interactive token states (hover/focus/active/
disabled) automatically. `variant` is `"contained" | "outlined" | "ghost"`;
`size` is `"sm" | "md"`; `accent` defaults to `"brand"`.
## Setup
```tsx
import { Button } from "alouette";
import { CheckRegularIcon } from "alouette-icons/phosphor-icons/CheckRegularIcon";
<Button text="Save" icon={<CheckRegularIcon />} onPress={save} />;
```
## Core Patterns
### Button variants and accents
```tsx
<Button text="Save" /> {/* contained, brand */}
<Button variant="outlined" text="Cancel" />
<Button variant="ghost" text="Dismiss" />
<Button accent="danger" text="Delete" />
<Button size="sm" text="Small" />
```
### Icon-only button
```tsx
import { IconButton } from "alouette";
import { XRegularIcon } from "alouette-icons/phosphor-icons/XRegularIcon";
<IconButton icon={<XRegularIcon />} aria-label="Close" onPress={close} />;
```
`size` is `"sm" | "md"` or a number (custom diameter in px); `iconSize="fill"`
makes the icon take 80% of the button.
### Pressable surfaces
`PressableBox` is a themed, pressable container (`variant`, `accent`,
`forceStyle`). `PressableListItem` is a row with a trailing caret.
```tsx
import { PressableBox, PressableListItem, Text } from "alouette";
<PressableBox onPress={open}>
<Text>Custom card</Text>
</PressableBox>
<PressableListItem onPress={open}>
<Text>Row label</Text>
</PressableListItem>;
```
### Link buttons
```tsx
import { ExternalLinkButton, InternalLinkButton } from "alouette";
<ExternalLinkButton href="https://example.com" text="Open" />
<InternalLinkButton href="/settings" text="Settings" />
```
For full external-link control (in-app browser vs new tab), see
alouette-external-links/SKILL.md.
## Common Mistakes
### HIGH Passing the button label as children instead of text
Wrong:
```tsx
<Button>Save</Button>
```
Correct:
```tsx
<Button text="Save" />
```
`Button` renders its label from the required `text` prop (plus an optional `icon`
prop); children are ignored, so `<Button>Save</Button>` shows no label.
Source: packages/alouette/src/ui/actions/Button.tsx
### HIGH Using non-existent variant names
Wrong:
```tsx
<Button variant="ghost-contained" text="Cancel" />
<Button variant="primary" text="Save" />
```
Correct:
```tsx
<Button variant="ghost" text="Cancel" />
<Button accent="brand" text="Save" />
```
`variant` is only `"contained" | "outlined" | "ghost"`; the accent is chosen via
the `accent` prop. (`ghost` is a variant value, not a separate boolean prop.)
Source: packages/alouette/src/ui/data/PressableBox.tsx, ui/actions/Button.tsx
### MEDIUM IconButton without aria-label
Wrong:
```tsx
<IconButton icon={<XRegularIcon />} onPress={close} />
```
Correct:
```tsx
<IconButton icon={<XRegularIcon />} aria-label="Close" onPress={close} />
```
`IconButton` types `aria-label` as required because it has no text label;
omitting it is an accessibility failure and a type error.
Source: packages/alouette/src/ui/actions/IconButton.tsx