@neynar/ui 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/context7.json +17 -0
- package/llm/components/accordion.llm.md +205 -0
- package/llm/components/alert-dialog.llm.md +289 -0
- package/llm/components/alert.llm.md +310 -0
- package/llm/components/aspect-ratio.llm.md +110 -0
- package/llm/components/avatar.llm.md +282 -0
- package/llm/components/badge.llm.md +185 -0
- package/llm/components/blockquote.llm.md +86 -0
- package/llm/components/breadcrumb.llm.md +245 -0
- package/llm/components/button-group.llm.md +248 -0
- package/llm/components/button.llm.md +247 -0
- package/llm/components/calendar.llm.md +252 -0
- package/llm/components/card.llm.md +356 -0
- package/llm/components/carousel.llm.md +281 -0
- package/llm/components/chart.llm.md +278 -0
- package/llm/components/checkbox.llm.md +234 -0
- package/llm/components/code.llm.md +75 -0
- package/llm/components/collapsible.llm.md +271 -0
- package/llm/components/color-mode.llm.md +196 -0
- package/llm/components/combobox.llm.md +346 -0
- package/llm/components/command.llm.md +353 -0
- package/llm/components/context-menu.llm.md +368 -0
- package/llm/components/dialog.llm.md +283 -0
- package/llm/components/drawer.llm.md +326 -0
- package/llm/components/dropdown-menu.llm.md +404 -0
- package/llm/components/empty.llm.md +282 -0
- package/llm/components/field.llm.md +303 -0
- package/llm/components/first-light.llm.md +129 -0
- package/llm/components/hover-card.llm.md +278 -0
- package/llm/components/input-group.llm.md +334 -0
- package/llm/components/input-otp.llm.md +270 -0
- package/llm/components/input.llm.md +197 -0
- package/llm/components/item.llm.md +347 -0
- package/llm/components/kbd.llm.md +221 -0
- package/llm/components/label.llm.md +219 -0
- package/llm/components/menubar.llm.md +378 -0
- package/llm/components/navigation-menu.llm.md +320 -0
- package/llm/components/pagination.llm.md +337 -0
- package/llm/components/popover.llm.md +278 -0
- package/llm/components/progress.llm.md +259 -0
- package/llm/components/radio-group.llm.md +269 -0
- package/llm/components/resizable.llm.md +222 -0
- package/llm/components/scroll-area.llm.md +290 -0
- package/llm/components/select.llm.md +338 -0
- package/llm/components/separator.llm.md +129 -0
- package/llm/components/sheet.llm.md +275 -0
- package/llm/components/sidebar.llm.md +528 -0
- package/llm/components/skeleton.llm.md +140 -0
- package/llm/components/slider.llm.md +213 -0
- package/llm/components/sonner.llm.md +299 -0
- package/llm/components/spinner.llm.md +187 -0
- package/llm/components/switch.llm.md +258 -0
- package/llm/components/table.llm.md +334 -0
- package/llm/components/tabs.llm.md +245 -0
- package/llm/components/text.llm.md +108 -0
- package/llm/components/textarea.llm.md +236 -0
- package/llm/components/title.llm.md +88 -0
- package/llm/components/toggle-group.llm.md +228 -0
- package/llm/components/toggle.llm.md +235 -0
- package/llm/components/tooltip.llm.md +191 -0
- package/llm/contributing.llm.md +273 -0
- package/llm/hooks.llm.md +91 -0
- package/llm/index.llm.md +178 -0
- package/llm/theming.llm.md +381 -0
- package/llm/utilities.llm.md +97 -0
- package/llms-full.txt +15995 -0
- package/llms.txt +182 -0
- package/package.json +6 -2
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# ButtonGroup
|
|
2
|
+
|
|
3
|
+
Groups related buttons together with fused borders and shared styling for toolbars, split buttons, and bulk actions.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { ButtonGroup, ButtonGroupSeparator, ButtonGroupText } from "@neynar/ui/button-group"
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Anatomy
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
<ButtonGroup orientation="horizontal">
|
|
15
|
+
<Button>First</Button>
|
|
16
|
+
<ButtonGroupSeparator />
|
|
17
|
+
<Button>Second</Button>
|
|
18
|
+
<ButtonGroupText>Status</ButtonGroupText>
|
|
19
|
+
</ButtonGroup>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Components
|
|
23
|
+
|
|
24
|
+
| Component | Description |
|
|
25
|
+
|-----------|-------------|
|
|
26
|
+
| ButtonGroup | Root container with fused border styling |
|
|
27
|
+
| ButtonGroupSeparator | Visual divider between button sections |
|
|
28
|
+
| ButtonGroupText | Text/status display element within group |
|
|
29
|
+
|
|
30
|
+
## Props
|
|
31
|
+
|
|
32
|
+
### ButtonGroup
|
|
33
|
+
|
|
34
|
+
Extends all native `div` props plus:
|
|
35
|
+
|
|
36
|
+
| Prop | Type | Default | Description |
|
|
37
|
+
|------|------|---------|-------------|
|
|
38
|
+
| orientation | "horizontal" \| "vertical" | "horizontal" | Layout direction of buttons |
|
|
39
|
+
|
|
40
|
+
**Auto-behaviors:**
|
|
41
|
+
- Fuses borders between adjacent buttons
|
|
42
|
+
- Rounds only outer corners
|
|
43
|
+
- Handles focus visibility (z-index management)
|
|
44
|
+
- Supports Input and Select components
|
|
45
|
+
|
|
46
|
+
### ButtonGroupSeparator
|
|
47
|
+
|
|
48
|
+
Extends `Separator` component props:
|
|
49
|
+
|
|
50
|
+
| Prop | Type | Default | Description |
|
|
51
|
+
|------|------|---------|-------------|
|
|
52
|
+
| orientation | "horizontal" \| "vertical" | "vertical" | Separator direction |
|
|
53
|
+
|
|
54
|
+
**Note:** Typically inherits orientation from parent ButtonGroup context, but can be overridden.
|
|
55
|
+
|
|
56
|
+
### ButtonGroupText
|
|
57
|
+
|
|
58
|
+
Extends all native `div` props plus:
|
|
59
|
+
|
|
60
|
+
| Prop | Type | Default | Description |
|
|
61
|
+
|------|------|---------|-------------|
|
|
62
|
+
| render | React.Element \| function | - | Custom element or render function |
|
|
63
|
+
|
|
64
|
+
**Render prop example:**
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
<ButtonGroupText render={<span />}>
|
|
68
|
+
Custom text
|
|
69
|
+
</ButtonGroupText>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Data Attributes
|
|
73
|
+
|
|
74
|
+
| Attribute | Element | Description |
|
|
75
|
+
|-----------|---------|-------------|
|
|
76
|
+
| data-slot="button-group" | ButtonGroup | Identifies container |
|
|
77
|
+
| data-slot="button-group-text" | ButtonGroupText | Identifies text element |
|
|
78
|
+
| data-slot="button-group-separator" | ButtonGroupSeparator | Identifies separator |
|
|
79
|
+
| data-orientation | ButtonGroup | Current orientation value |
|
|
80
|
+
|
|
81
|
+
## Examples
|
|
82
|
+
|
|
83
|
+
### Basic Horizontal Group
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
<ButtonGroup>
|
|
87
|
+
<Button variant="outline">Left</Button>
|
|
88
|
+
<Button variant="outline">Center</Button>
|
|
89
|
+
<Button variant="outline">Right</Button>
|
|
90
|
+
</ButtonGroup>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Vertical Group with Icons
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
<ButtonGroup orientation="vertical">
|
|
97
|
+
<Button variant="secondary">
|
|
98
|
+
<KeyIcon data-icon="inline-start" />
|
|
99
|
+
API Keys
|
|
100
|
+
</Button>
|
|
101
|
+
<Button variant="secondary">
|
|
102
|
+
<MailIcon data-icon="inline-start" />
|
|
103
|
+
Webhooks
|
|
104
|
+
</Button>
|
|
105
|
+
<Button variant="secondary">
|
|
106
|
+
<SettingsIcon data-icon="inline-start" />
|
|
107
|
+
Settings
|
|
108
|
+
</Button>
|
|
109
|
+
</ButtonGroup>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Split Button Pattern
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
<ButtonGroup>
|
|
116
|
+
<Button variant="default">Save Changes</Button>
|
|
117
|
+
<Button variant="default" size="icon">
|
|
118
|
+
<ChevronDownIcon />
|
|
119
|
+
</Button>
|
|
120
|
+
</ButtonGroup>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### With Separators
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
<ButtonGroup>
|
|
127
|
+
<Button variant="outline" size="sm">
|
|
128
|
+
<CopyIcon data-icon="inline-start" />
|
|
129
|
+
Copy
|
|
130
|
+
</Button>
|
|
131
|
+
<Button variant="outline" size="sm">
|
|
132
|
+
<EditIcon data-icon="inline-start" />
|
|
133
|
+
Edit
|
|
134
|
+
</Button>
|
|
135
|
+
<ButtonGroupSeparator />
|
|
136
|
+
<Button variant="outline" size="sm">
|
|
137
|
+
<TrashIcon data-icon="inline-start" />
|
|
138
|
+
Delete
|
|
139
|
+
</Button>
|
|
140
|
+
</ButtonGroup>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Pagination with Text
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
<ButtonGroup>
|
|
147
|
+
<Button variant="outline" size="sm" disabled>
|
|
148
|
+
Previous
|
|
149
|
+
</Button>
|
|
150
|
+
<ButtonGroupText>1 of 10</ButtonGroupText>
|
|
151
|
+
<Button variant="outline" size="sm">
|
|
152
|
+
Next
|
|
153
|
+
</Button>
|
|
154
|
+
</ButtonGroup>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Bulk Actions with Status
|
|
158
|
+
|
|
159
|
+
```tsx
|
|
160
|
+
<ButtonGroup>
|
|
161
|
+
<ButtonGroupText>
|
|
162
|
+
<CheckIcon />
|
|
163
|
+
3 selected
|
|
164
|
+
</ButtonGroupText>
|
|
165
|
+
<Button variant="outline" size="sm">
|
|
166
|
+
<RefreshCwIcon data-icon="inline-start" />
|
|
167
|
+
Regenerate
|
|
168
|
+
</Button>
|
|
169
|
+
<Button variant="outline" size="sm">
|
|
170
|
+
<DownloadIcon data-icon="inline-start" />
|
|
171
|
+
Export
|
|
172
|
+
</Button>
|
|
173
|
+
<ButtonGroupSeparator />
|
|
174
|
+
<Button variant="outline" size="sm">
|
|
175
|
+
<TrashIcon data-icon="inline-start" />
|
|
176
|
+
Delete
|
|
177
|
+
</Button>
|
|
178
|
+
</ButtonGroup>
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Search Bar with Input
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
<ButtonGroup>
|
|
185
|
+
<Input placeholder="Search..." className="flex-1" />
|
|
186
|
+
<Button variant="outline" size="icon">
|
|
187
|
+
<SearchIcon />
|
|
188
|
+
</Button>
|
|
189
|
+
</ButtonGroup>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Filter Toggle Group
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
function FilterExample() {
|
|
196
|
+
const [filter, setFilter] = useState("all")
|
|
197
|
+
|
|
198
|
+
return (
|
|
199
|
+
<ButtonGroup>
|
|
200
|
+
<Button
|
|
201
|
+
variant={filter === "all" ? "secondary" : "outline"}
|
|
202
|
+
size="sm"
|
|
203
|
+
onClick={() => setFilter("all")}
|
|
204
|
+
>
|
|
205
|
+
All
|
|
206
|
+
</Button>
|
|
207
|
+
<Button
|
|
208
|
+
variant={filter === "active" ? "secondary" : "outline"}
|
|
209
|
+
size="sm"
|
|
210
|
+
onClick={() => setFilter("active")}
|
|
211
|
+
>
|
|
212
|
+
Active
|
|
213
|
+
</Button>
|
|
214
|
+
<Button
|
|
215
|
+
variant={filter === "inactive" ? "secondary" : "outline"}
|
|
216
|
+
size="sm"
|
|
217
|
+
onClick={() => setFilter("inactive")}
|
|
218
|
+
>
|
|
219
|
+
Inactive
|
|
220
|
+
</Button>
|
|
221
|
+
</ButtonGroup>
|
|
222
|
+
)
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## Keyboard
|
|
227
|
+
|
|
228
|
+
ButtonGroup inherits keyboard navigation from child components:
|
|
229
|
+
|
|
230
|
+
| Key | Action |
|
|
231
|
+
|-----|--------|
|
|
232
|
+
| Tab | Navigate to next focusable element |
|
|
233
|
+
| Shift+Tab | Navigate to previous focusable element |
|
|
234
|
+
| Space/Enter | Activate focused button |
|
|
235
|
+
|
|
236
|
+
## Accessibility
|
|
237
|
+
|
|
238
|
+
- Uses `role="group"` to semantically group related buttons
|
|
239
|
+
- Maintains proper focus order through natural DOM structure
|
|
240
|
+
- Focus visibility handled with z-index elevation on `:focus-visible`
|
|
241
|
+
- Child buttons maintain individual ARIA attributes and keyboard support
|
|
242
|
+
|
|
243
|
+
## Related
|
|
244
|
+
|
|
245
|
+
- [Button](./button.llm.md) - Individual button component
|
|
246
|
+
- [Separator](./separator.llm.md) - Standalone separator
|
|
247
|
+
- [Input](./input.llm.md) - Works with Input in search patterns
|
|
248
|
+
- [Select](./select.llm.md) - Works with Select in filter patterns
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# Button
|
|
2
|
+
|
|
3
|
+
Versatile button component with multiple visual variants, semantic colors, and flexible sizing.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Button } from "@neynar/ui/button"
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Anatomy
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
<Button variant="default" size="default">
|
|
15
|
+
Click me
|
|
16
|
+
</Button>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Props
|
|
20
|
+
|
|
21
|
+
### Button
|
|
22
|
+
|
|
23
|
+
Extends all standard HTML button attributes plus Base UI Button props.
|
|
24
|
+
|
|
25
|
+
| Prop | Type | Default | Description |
|
|
26
|
+
|------|------|---------|-------------|
|
|
27
|
+
| variant | "default" \| "outline" \| "secondary" \| "ghost" \| "destructive" \| "success" \| "warning" \| "info" \| "link" | "default" | Visual style variant |
|
|
28
|
+
| size | "default" \| "xs" \| "sm" \| "lg" \| "icon" \| "icon-xs" \| "icon-sm" \| "icon-lg" | "default" | Button size |
|
|
29
|
+
| disabled | boolean | false | Disables the button |
|
|
30
|
+
| render | ReactElement \| Function | - | Custom element to render as (maintains button semantics) |
|
|
31
|
+
| className | string | - | Additional CSS classes |
|
|
32
|
+
| focusableWhenDisabled | boolean | true | Whether button remains focusable when disabled |
|
|
33
|
+
| nativeButton | boolean | true | Whether component renders native `<button>` when using render prop |
|
|
34
|
+
|
|
35
|
+
All standard `<button>` HTML attributes are supported: `type`, `onClick`, `onFocus`, `aria-label`, etc.
|
|
36
|
+
|
|
37
|
+
### Icon Placement
|
|
38
|
+
|
|
39
|
+
Icons are placed using `data-icon` attributes on child elements:
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
// Icon at start
|
|
43
|
+
<Button>
|
|
44
|
+
<PlusIcon data-icon="inline-start" />
|
|
45
|
+
Create
|
|
46
|
+
</Button>
|
|
47
|
+
|
|
48
|
+
// Icon at end
|
|
49
|
+
<Button>
|
|
50
|
+
Continue
|
|
51
|
+
<ArrowRightIcon data-icon="inline-end" />
|
|
52
|
+
</Button>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The component automatically sizes icons to `size-4` (16px) except for `xs` sizes which use `size-3` (12px). Icons receive proper spacing via gap utilities.
|
|
56
|
+
|
|
57
|
+
### Render Prop
|
|
58
|
+
|
|
59
|
+
Use the `render` prop to compose the button with other elements while maintaining button semantics:
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
// Render as link
|
|
63
|
+
<Button render={<a href="/dashboard" />}>
|
|
64
|
+
Dashboard
|
|
65
|
+
</Button>
|
|
66
|
+
|
|
67
|
+
// Compose with Next.js Link
|
|
68
|
+
<Button render={<Link href="/login" />}>
|
|
69
|
+
Sign in
|
|
70
|
+
</Button>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Variants
|
|
74
|
+
|
|
75
|
+
### Visual Variants
|
|
76
|
+
|
|
77
|
+
| Variant | Use Case |
|
|
78
|
+
|---------|----------|
|
|
79
|
+
| default | Primary actions, most important button in a context |
|
|
80
|
+
| outline | Secondary actions, neutral emphasis with border |
|
|
81
|
+
| secondary | Alternative actions, less emphasis than default |
|
|
82
|
+
| ghost | Tertiary actions, minimal visual weight |
|
|
83
|
+
| link | Text-only actions that look like links |
|
|
84
|
+
|
|
85
|
+
### Semantic Variants
|
|
86
|
+
|
|
87
|
+
| Variant | Use Case |
|
|
88
|
+
|---------|----------|
|
|
89
|
+
| destructive | Delete, revoke, or other destructive actions |
|
|
90
|
+
| success | Confirm, approve, or positive actions |
|
|
91
|
+
| warning | Caution, proceed with care actions |
|
|
92
|
+
| info | Informational or help actions |
|
|
93
|
+
|
|
94
|
+
### Size Variants
|
|
95
|
+
|
|
96
|
+
| Size | Height | Use Case |
|
|
97
|
+
|------|--------|----------|
|
|
98
|
+
| xs | 24px (h-6) | Compact UIs, inline actions, tags |
|
|
99
|
+
| sm | 32px (h-8) | Dense tables, toolbars, secondary actions |
|
|
100
|
+
| default | 36px (h-9) | Standard buttons in forms and dialogs |
|
|
101
|
+
| lg | 40px (h-10) | Marketing pages, prominent CTAs |
|
|
102
|
+
|
|
103
|
+
### Icon-Only Sizes
|
|
104
|
+
|
|
105
|
+
| Size | Dimensions | Use Case |
|
|
106
|
+
|------|------------|----------|
|
|
107
|
+
| icon-xs | 24x24px | Compact icon buttons |
|
|
108
|
+
| icon-sm | 32x32px | Small icon buttons in toolbars |
|
|
109
|
+
| icon | 36x36px | Standard icon buttons |
|
|
110
|
+
| icon-lg | 40x40px | Large icon buttons for emphasis |
|
|
111
|
+
|
|
112
|
+
## Data Attributes
|
|
113
|
+
|
|
114
|
+
| Attribute | When Present |
|
|
115
|
+
|-----------|--------------|
|
|
116
|
+
| data-slot="button" | Always present (for styling context) |
|
|
117
|
+
| data-disabled | Button is disabled |
|
|
118
|
+
| data-focusable | Button remains focusable when disabled |
|
|
119
|
+
| aria-expanded | Button controls expandable content (auto-styled) |
|
|
120
|
+
| aria-invalid | Button is in invalid state (auto-styled with destructive ring) |
|
|
121
|
+
|
|
122
|
+
## Examples
|
|
123
|
+
|
|
124
|
+
### Basic Usage
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
<Button>Click me</Button>
|
|
128
|
+
<Button variant="outline">Cancel</Button>
|
|
129
|
+
<Button variant="destructive">Delete</Button>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### With Icons
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
// Icon at start
|
|
136
|
+
<Button>
|
|
137
|
+
<PlusIcon data-icon="inline-start" />
|
|
138
|
+
Create Key
|
|
139
|
+
</Button>
|
|
140
|
+
|
|
141
|
+
// Icon at end
|
|
142
|
+
<Button variant="secondary">
|
|
143
|
+
Continue
|
|
144
|
+
<SendIcon data-icon="inline-end" />
|
|
145
|
+
</Button>
|
|
146
|
+
|
|
147
|
+
// Icon only - requires aria-label
|
|
148
|
+
<Button size="icon" variant="ghost" aria-label="Settings">
|
|
149
|
+
<SettingsIcon />
|
|
150
|
+
</Button>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Loading State
|
|
154
|
+
|
|
155
|
+
```tsx
|
|
156
|
+
function SubmitButton() {
|
|
157
|
+
const [isLoading, setIsLoading] = useState(false)
|
|
158
|
+
|
|
159
|
+
return (
|
|
160
|
+
<Button disabled={isLoading}>
|
|
161
|
+
{isLoading ? (
|
|
162
|
+
<Loader2Icon data-icon="inline-start" className="animate-spin" />
|
|
163
|
+
) : (
|
|
164
|
+
<SendIcon data-icon="inline-start" />
|
|
165
|
+
)}
|
|
166
|
+
{isLoading ? "Sending..." : "Send"}
|
|
167
|
+
</Button>
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### API Key Management Context
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
function APIKeyActions() {
|
|
176
|
+
const [copied, setCopied] = useState(false)
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
<div className="flex gap-2">
|
|
180
|
+
<Button variant="outline" size="sm" onClick={() => setCopied(true)}>
|
|
181
|
+
<CopyIcon data-icon="inline-start" />
|
|
182
|
+
{copied ? "Copied!" : "Copy"}
|
|
183
|
+
</Button>
|
|
184
|
+
<Button variant="outline" size="sm">
|
|
185
|
+
<RefreshCwIcon data-icon="inline-start" />
|
|
186
|
+
Regenerate
|
|
187
|
+
</Button>
|
|
188
|
+
<Button variant="destructive" size="sm">
|
|
189
|
+
<TrashIcon data-icon="inline-start" />
|
|
190
|
+
Revoke
|
|
191
|
+
</Button>
|
|
192
|
+
</div>
|
|
193
|
+
)
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Form Actions
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
<div className="flex justify-end gap-2">
|
|
201
|
+
<Button variant="outline" type="button">Cancel</Button>
|
|
202
|
+
<Button type="submit">
|
|
203
|
+
<SendIcon data-icon="inline-start" />
|
|
204
|
+
Save Changes
|
|
205
|
+
</Button>
|
|
206
|
+
</div>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Keyboard
|
|
210
|
+
|
|
211
|
+
| Key | Action |
|
|
212
|
+
|-----|--------|
|
|
213
|
+
| Space | Activate button |
|
|
214
|
+
| Enter | Activate button |
|
|
215
|
+
| Tab | Move focus to/from button |
|
|
216
|
+
|
|
217
|
+
## Accessibility
|
|
218
|
+
|
|
219
|
+
- Rendered as native `<button>` element by default
|
|
220
|
+
- Supports `aria-label` for icon-only buttons (required for accessibility)
|
|
221
|
+
- Disabled buttons remain focusable by default (set `focusableWhenDisabled={false}` to change)
|
|
222
|
+
- Focus visible ring with 3px width for clear focus indication
|
|
223
|
+
- Supports `aria-invalid` state for form validation with red ring/border
|
|
224
|
+
- Screen readers announce button role and state automatically
|
|
225
|
+
|
|
226
|
+
## Styling Notes
|
|
227
|
+
|
|
228
|
+
### Icon Auto-Sizing
|
|
229
|
+
|
|
230
|
+
Icons are automatically sized based on button size:
|
|
231
|
+
- Default sizes: 16px (`size-4`)
|
|
232
|
+
- `xs` and `icon-xs`: 12px (`size-3`)
|
|
233
|
+
- Override with explicit class: `<Icon className="size-5" />`
|
|
234
|
+
|
|
235
|
+
### Button Group Context
|
|
236
|
+
|
|
237
|
+
When inside `data-slot="button-group"`, buttons automatically adjust border radius to connect seamlessly.
|
|
238
|
+
|
|
239
|
+
### Dark Mode
|
|
240
|
+
|
|
241
|
+
All variants include dark mode optimized colors that automatically adapt based on theme settings.
|
|
242
|
+
|
|
243
|
+
## Related
|
|
244
|
+
|
|
245
|
+
- **Button Group** - Group multiple buttons with connected borders
|
|
246
|
+
- **Toggle Button** - Button with on/off state
|
|
247
|
+
- **Dialog** - Use Button as DialogTrigger
|