@neynar/ui 1.0.1 → 1.0.3

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.
Files changed (68) hide show
  1. package/context7.json +17 -0
  2. package/llm/components/accordion.llm.md +205 -0
  3. package/llm/components/alert-dialog.llm.md +289 -0
  4. package/llm/components/alert.llm.md +310 -0
  5. package/llm/components/aspect-ratio.llm.md +110 -0
  6. package/llm/components/avatar.llm.md +282 -0
  7. package/llm/components/badge.llm.md +185 -0
  8. package/llm/components/blockquote.llm.md +86 -0
  9. package/llm/components/breadcrumb.llm.md +245 -0
  10. package/llm/components/button-group.llm.md +248 -0
  11. package/llm/components/button.llm.md +247 -0
  12. package/llm/components/calendar.llm.md +252 -0
  13. package/llm/components/card.llm.md +356 -0
  14. package/llm/components/carousel.llm.md +281 -0
  15. package/llm/components/chart.llm.md +278 -0
  16. package/llm/components/checkbox.llm.md +234 -0
  17. package/llm/components/code.llm.md +75 -0
  18. package/llm/components/collapsible.llm.md +271 -0
  19. package/llm/components/color-mode.llm.md +196 -0
  20. package/llm/components/combobox.llm.md +346 -0
  21. package/llm/components/command.llm.md +353 -0
  22. package/llm/components/context-menu.llm.md +368 -0
  23. package/llm/components/dialog.llm.md +283 -0
  24. package/llm/components/drawer.llm.md +326 -0
  25. package/llm/components/dropdown-menu.llm.md +404 -0
  26. package/llm/components/empty.llm.md +282 -0
  27. package/llm/components/field.llm.md +303 -0
  28. package/llm/components/first-light.llm.md +129 -0
  29. package/llm/components/hover-card.llm.md +278 -0
  30. package/llm/components/input-group.llm.md +334 -0
  31. package/llm/components/input-otp.llm.md +270 -0
  32. package/llm/components/input.llm.md +197 -0
  33. package/llm/components/item.llm.md +347 -0
  34. package/llm/components/kbd.llm.md +221 -0
  35. package/llm/components/label.llm.md +219 -0
  36. package/llm/components/menubar.llm.md +378 -0
  37. package/llm/components/navigation-menu.llm.md +320 -0
  38. package/llm/components/pagination.llm.md +337 -0
  39. package/llm/components/popover.llm.md +278 -0
  40. package/llm/components/progress.llm.md +259 -0
  41. package/llm/components/radio-group.llm.md +269 -0
  42. package/llm/components/resizable.llm.md +222 -0
  43. package/llm/components/scroll-area.llm.md +290 -0
  44. package/llm/components/select.llm.md +338 -0
  45. package/llm/components/separator.llm.md +129 -0
  46. package/llm/components/sheet.llm.md +275 -0
  47. package/llm/components/sidebar.llm.md +528 -0
  48. package/llm/components/skeleton.llm.md +140 -0
  49. package/llm/components/slider.llm.md +213 -0
  50. package/llm/components/sonner.llm.md +299 -0
  51. package/llm/components/spinner.llm.md +187 -0
  52. package/llm/components/switch.llm.md +258 -0
  53. package/llm/components/table.llm.md +334 -0
  54. package/llm/components/tabs.llm.md +245 -0
  55. package/llm/components/text.llm.md +108 -0
  56. package/llm/components/textarea.llm.md +236 -0
  57. package/llm/components/title.llm.md +88 -0
  58. package/llm/components/toggle-group.llm.md +228 -0
  59. package/llm/components/toggle.llm.md +235 -0
  60. package/llm/components/tooltip.llm.md +191 -0
  61. package/llm/contributing.llm.md +273 -0
  62. package/llm/hooks.llm.md +91 -0
  63. package/llm/index.llm.md +178 -0
  64. package/llm/theming.llm.md +381 -0
  65. package/llm/utilities.llm.md +97 -0
  66. package/llms-full.txt +15995 -0
  67. package/llms.txt +182 -0
  68. package/package.json +5 -1
@@ -0,0 +1,228 @@
1
+ # ToggleGroup
2
+
3
+ A group of toggle buttons that share state, commonly used for formatting toolbars, view switchers, and filter controls.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { ToggleGroup, ToggleGroupItem } from "@neynar/ui/toggle-group"
9
+ ```
10
+
11
+ ## Anatomy
12
+
13
+ ```tsx
14
+ <ToggleGroup>
15
+ <ToggleGroupItem value="option1">Option 1</ToggleGroupItem>
16
+ <ToggleGroupItem value="option2">Option 2</ToggleGroupItem>
17
+ <ToggleGroupItem value="option3">Option 3</ToggleGroupItem>
18
+ </ToggleGroup>
19
+ ```
20
+
21
+ ## Components
22
+
23
+ | Component | Description |
24
+ |-----------|-------------|
25
+ | ToggleGroup | Root container that manages shared state and layout |
26
+ | ToggleGroupItem | Individual toggle button within the group |
27
+
28
+ ## Props
29
+
30
+ ### ToggleGroup
31
+
32
+ Inherits all props from `@base-ui/react/toggle-group` plus variant styling props.
33
+
34
+ | Prop | Type | Default | Description |
35
+ |------|------|---------|-------------|
36
+ | value | `any[]` | - | Controlled state: array of pressed item values |
37
+ | defaultValue | `any[]` | - | Uncontrolled initial state |
38
+ | onValueChange | `(value: any[]) => void` | - | Called when selection changes |
39
+ | multiple | `boolean` | `true` | Allow multiple items to be pressed |
40
+ | variant | `"default" \| "outline"` | - | Visual style inherited by all items |
41
+ | size | `"default" \| "sm" \| "lg"` | - | Size variant inherited by all items |
42
+ | spacing | `number` | `0` | Gap between items (0 = joined buttons) |
43
+ | orientation | `"horizontal" \| "vertical"` | `"horizontal"` | Layout direction |
44
+ | disabled | `boolean` | `false` | Disable all toggles in the group |
45
+ | loopFocus | `boolean` | `true` | Wrap focus when reaching end with arrow keys |
46
+
47
+ **Note:** By default, `multiple={true}` allows multiple selections. Set `multiple={false}` for single selection mode.
48
+
49
+ ### ToggleGroupItem
50
+
51
+ Inherits variant and size from parent ToggleGroup context unless explicitly overridden.
52
+
53
+ | Prop | Type | Default | Description |
54
+ |------|------|---------|-------------|
55
+ | value | `string` | - | **Required.** Unique identifier for this item |
56
+ | variant | `"default" \| "outline"` | Inherits from group | Override group variant |
57
+ | size | `"default" \| "sm" \| "lg"` | Inherits from group | Override group size |
58
+ | aria-label | `string` | - | Required for icon-only buttons |
59
+
60
+ ## Data Attributes
61
+
62
+ ### ToggleGroup
63
+
64
+ | Attribute | When Present |
65
+ |-----------|--------------|
66
+ | data-orientation | Always: `"horizontal"` or `"vertical"` |
67
+ | data-disabled | Group is disabled |
68
+ | data-multiple | Multiple selection is enabled |
69
+ | data-spacing | Always: spacing value |
70
+ | data-variant | Always: variant name |
71
+ | data-size | Always: size name |
72
+
73
+ ### ToggleGroupItem
74
+
75
+ | Attribute | When Present |
76
+ |-----------|--------------|
77
+ | data-pressed | Item is in pressed state |
78
+ | data-disabled | Item is disabled |
79
+
80
+ ## Variants
81
+
82
+ ### Visual Variants
83
+
84
+ | Variant | Appearance |
85
+ |---------|------------|
86
+ | default | Transparent background, fills on press |
87
+ | outline | Border with shadow, subtle background on press |
88
+
89
+ ### Sizes
90
+
91
+ | Size | Height | Min Width | Padding |
92
+ |------|--------|-----------|---------|
93
+ | sm | 32px | 32px | 6px |
94
+ | default | 36px | 36px | 8px |
95
+ | lg | 40px | 40px | 10px |
96
+
97
+ ## Examples
98
+
99
+ ### Single Selection (Time Range Picker)
100
+
101
+ ```tsx
102
+ function TimeRangePicker() {
103
+ const [range, setRange] = useState(["7d"])
104
+
105
+ return (
106
+ <ToggleGroup
107
+ value={range}
108
+ onValueChange={(value) => {
109
+ if (value) setRange(value)
110
+ }}
111
+ variant="outline"
112
+ spacing={0}
113
+ >
114
+ <ToggleGroupItem value="1d">1D</ToggleGroupItem>
115
+ <ToggleGroupItem value="7d">7D</ToggleGroupItem>
116
+ <ToggleGroupItem value="30d">30D</ToggleGroupItem>
117
+ <ToggleGroupItem value="90d">90D</ToggleGroupItem>
118
+ </ToggleGroup>
119
+ )
120
+ }
121
+ ```
122
+
123
+ ### Multiple Selection (Text Formatting)
124
+
125
+ ```tsx
126
+ function TextFormatting() {
127
+ return (
128
+ <ToggleGroup variant="outline" spacing={0}>
129
+ <ToggleGroupItem value="bold" aria-label="Bold">
130
+ <BoldIcon />
131
+ </ToggleGroupItem>
132
+ <ToggleGroupItem value="italic" aria-label="Italic">
133
+ <ItalicIcon />
134
+ </ToggleGroupItem>
135
+ <ToggleGroupItem value="underline" aria-label="Underline">
136
+ <UnderlineIcon />
137
+ </ToggleGroupItem>
138
+ </ToggleGroup>
139
+ )
140
+ }
141
+ ```
142
+
143
+ ### View Switcher (Icon-Only)
144
+
145
+ ```tsx
146
+ function ViewSwitcher() {
147
+ const [view, setView] = useState(["grid"])
148
+
149
+ return (
150
+ <ToggleGroup
151
+ value={view}
152
+ onValueChange={(value) => {
153
+ if (value) setView(value)
154
+ }}
155
+ variant="outline"
156
+ spacing={0}
157
+ >
158
+ <ToggleGroupItem value="grid" aria-label="Grid view">
159
+ <GridIcon />
160
+ </ToggleGroupItem>
161
+ <ToggleGroupItem value="list" aria-label="List view">
162
+ <ListIcon />
163
+ </ToggleGroupItem>
164
+ </ToggleGroup>
165
+ )
166
+ }
167
+ ```
168
+
169
+ ### Vertical Layout with Spacing
170
+
171
+ ```tsx
172
+ <ToggleGroup orientation="vertical" spacing={2} variant="outline">
173
+ <ToggleGroupItem value="option1">Option 1</ToggleGroupItem>
174
+ <ToggleGroupItem value="option2">Option 2</ToggleGroupItem>
175
+ <ToggleGroupItem value="option3">Option 3</ToggleGroupItem>
176
+ </ToggleGroup>
177
+ ```
178
+
179
+ ### Separated Buttons (Spacing > 0)
180
+
181
+ ```tsx
182
+ <ToggleGroup variant="outline" spacing={4}>
183
+ <ToggleGroupItem value="filter1">Active</ToggleGroupItem>
184
+ <ToggleGroupItem value="filter2">Pending</ToggleGroupItem>
185
+ <ToggleGroupItem value="filter3">Archived</ToggleGroupItem>
186
+ </ToggleGroup>
187
+ ```
188
+
189
+ ## Keyboard Navigation
190
+
191
+ | Key | Action |
192
+ |-----|--------|
193
+ | Tab | Focus the group (first/last item based on direction) |
194
+ | ArrowRight / ArrowDown | Move focus to next item |
195
+ | ArrowLeft / ArrowUp | Move focus to previous item |
196
+ | Space / Enter | Toggle the focused item |
197
+ | Home | Focus first item |
198
+ | End | Focus last item |
199
+
200
+ Arrow key direction depends on `orientation`: horizontal uses Left/Right, vertical uses Up/Down.
201
+
202
+ ## Accessibility
203
+
204
+ - Uses `role="group"` for the container
205
+ - Each toggle uses `aria-pressed` to indicate state
206
+ - Icon-only buttons **must** include `aria-label`
207
+ - Keyboard navigation follows ARIA authoring practices
208
+ - Focus management automatically handles arrow key navigation
209
+
210
+ ## Styling Notes
211
+
212
+ ### Joined Buttons (spacing=0)
213
+
214
+ When `spacing={0}`, items are visually joined:
215
+ - First item keeps left border radius (or top for vertical)
216
+ - Middle items have no border radius
217
+ - Last item keeps right border radius (or bottom for vertical)
218
+ - Outline variant: middle items share borders (no duplicate borders)
219
+
220
+ ### Context Inheritance
221
+
222
+ Items automatically inherit `variant` and `size` from the parent ToggleGroup via React context. You can override these per-item if needed.
223
+
224
+ ## Related
225
+
226
+ - [Toggle](./toggle.llm.md) - Single toggle button
227
+ - [Button](./button.llm.md) - Standard button component
228
+ - [RadioGroup](./radio-group.llm.md) - Radio button groups
@@ -0,0 +1,235 @@
1
+ # Toggle
2
+
3
+ Two-state button that can be pressed (on) or unpressed (off).
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { Toggle } from "@neynar/ui/toggle"
9
+ ```
10
+
11
+ ## Anatomy
12
+
13
+ ```tsx
14
+ <Toggle>
15
+ <Icon />
16
+ Label
17
+ </Toggle>
18
+ ```
19
+
20
+ ## Props
21
+
22
+ ### Toggle
23
+
24
+ Extends `@base-ui/react/toggle` Props with additional variant styling.
25
+
26
+ | Prop | Type | Default | Description |
27
+ |------|------|---------|-------------|
28
+ | pressed | boolean | - | Controlled pressed state |
29
+ | defaultPressed | boolean | false | Uncontrolled default pressed state |
30
+ | onPressedChange | (pressed: boolean) => void | - | Called when pressed state changes |
31
+ | disabled | boolean | false | Whether toggle is disabled |
32
+ | variant | "default" \| "outline" | "default" | Visual style variant |
33
+ | size | "sm" \| "default" \| "lg" | "default" | Toggle size |
34
+ | children | ReactNode | - | Toggle content (icon, text, or both) |
35
+ | className | string | - | Additional CSS classes |
36
+ | render | ReactElement \| function | - | Custom render prop |
37
+
38
+ ### Variant Details
39
+
40
+ **variant="default"**: Transparent background, shows pressed state with muted background.
41
+
42
+ **variant="outline"**: Border with shadow, more prominent visual separation.
43
+
44
+ ## Data Attributes
45
+
46
+ | Attribute | When Present |
47
+ |-----------|--------------|
48
+ | data-pressed | Toggle is in pressed state |
49
+ | data-disabled | Toggle is disabled |
50
+ | aria-pressed | "true" or "false" based on state |
51
+
52
+ ## Variants
53
+
54
+ | Variant | Options |
55
+ |---------|---------|
56
+ | variant | default, outline |
57
+ | size | sm, default, lg |
58
+
59
+ ## Examples
60
+
61
+ ### Basic Toggle
62
+
63
+ ```tsx
64
+ function BasicExample() {
65
+ const [pressed, setPressed] = useState(false)
66
+
67
+ return (
68
+ <Toggle
69
+ pressed={pressed}
70
+ onPressedChange={setPressed}
71
+ >
72
+ Toggle me
73
+ </Toggle>
74
+ )
75
+ }
76
+ ```
77
+
78
+ ### Icon-Only Toggle
79
+
80
+ ```tsx
81
+ import { BoldIcon } from "lucide-react"
82
+
83
+ function IconToggle() {
84
+ return (
85
+ <Toggle aria-label="Toggle bold">
86
+ <BoldIcon />
87
+ </Toggle>
88
+ )
89
+ }
90
+ ```
91
+
92
+ ### Icon with Text
93
+
94
+ ```tsx
95
+ import { GridIcon, ListIcon } from "lucide-react"
96
+
97
+ function ViewModeToggle() {
98
+ const [viewMode, setViewMode] = useState<"grid" | "list">("grid")
99
+
100
+ return (
101
+ <div className="flex gap-2">
102
+ <Toggle
103
+ pressed={viewMode === "grid"}
104
+ onPressedChange={(pressed) =>
105
+ pressed && setViewMode("grid")
106
+ }
107
+ aria-label="Grid view"
108
+ >
109
+ <GridIcon />
110
+ Grid
111
+ </Toggle>
112
+ <Toggle
113
+ pressed={viewMode === "list"}
114
+ onPressedChange={(pressed) =>
115
+ pressed && setViewMode("list")
116
+ }
117
+ aria-label="List view"
118
+ >
119
+ <ListIcon />
120
+ List
121
+ </Toggle>
122
+ </div>
123
+ )
124
+ }
125
+ ```
126
+
127
+ ### Formatting Toolbar
128
+
129
+ ```tsx
130
+ import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react"
131
+
132
+ function FormattingToolbar() {
133
+ const [formatting, setFormatting] = useState({
134
+ bold: false,
135
+ italic: false,
136
+ underline: false,
137
+ })
138
+
139
+ return (
140
+ <div className="flex gap-2">
141
+ <Toggle
142
+ size="sm"
143
+ variant="outline"
144
+ pressed={formatting.bold}
145
+ onPressedChange={(pressed) =>
146
+ setFormatting((prev) => ({ ...prev, bold: pressed }))
147
+ }
148
+ aria-label="Toggle bold"
149
+ >
150
+ <BoldIcon />
151
+ </Toggle>
152
+ <Toggle
153
+ size="sm"
154
+ variant="outline"
155
+ pressed={formatting.italic}
156
+ onPressedChange={(pressed) =>
157
+ setFormatting((prev) => ({ ...prev, italic: pressed }))
158
+ }
159
+ aria-label="Toggle italic"
160
+ >
161
+ <ItalicIcon />
162
+ </Toggle>
163
+ <Toggle
164
+ size="sm"
165
+ variant="outline"
166
+ pressed={formatting.underline}
167
+ onPressedChange={(pressed) =>
168
+ setFormatting((prev) => ({ ...prev, underline: pressed }))
169
+ }
170
+ aria-label="Toggle underline"
171
+ >
172
+ <UnderlineIcon />
173
+ </Toggle>
174
+ </div>
175
+ )
176
+ }
177
+ ```
178
+
179
+ ### Theme Toggle
180
+
181
+ ```tsx
182
+ import { SunIcon, MoonIcon } from "lucide-react"
183
+
184
+ function ThemeToggle() {
185
+ const [theme, setTheme] = useState<"light" | "dark">("light")
186
+
187
+ return (
188
+ <div className="flex gap-2">
189
+ <Toggle
190
+ variant="outline"
191
+ pressed={theme === "light"}
192
+ onPressedChange={(pressed) =>
193
+ pressed && setTheme("light")
194
+ }
195
+ aria-label="Light theme"
196
+ >
197
+ <SunIcon />
198
+ Light
199
+ </Toggle>
200
+ <Toggle
201
+ variant="outline"
202
+ pressed={theme === "dark"}
203
+ onPressedChange={(pressed) =>
204
+ pressed && setTheme("dark")
205
+ }
206
+ aria-label="Dark theme"
207
+ >
208
+ <MoonIcon />
209
+ Dark
210
+ </Toggle>
211
+ </div>
212
+ )
213
+ }
214
+ ```
215
+
216
+ ## Keyboard
217
+
218
+ | Key | Action |
219
+ |-----|--------|
220
+ | Space | Toggle pressed state |
221
+ | Enter | Toggle pressed state |
222
+
223
+ ## Accessibility
224
+
225
+ - Renders semantic `<button>` element with `aria-pressed` attribute
226
+ - Icons automatically sized to 16px (size-4) unless custom size class provided
227
+ - Always provide `aria-label` when using icon-only toggles
228
+ - Disabled state prevents all interaction and reduces opacity
229
+ - Focus visible ring indicates keyboard focus
230
+
231
+ ## Related
232
+
233
+ - [Button](./button.llm.md) - For actions instead of state toggles
234
+ - [Checkbox](./checkbox.llm.md) - For form selections
235
+ - [Switch](./switch.llm.md) - For on/off settings
@@ -0,0 +1,191 @@
1
+ # Tooltip
2
+
3
+ Displays contextual information on hover or focus.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { Tooltip, TooltipTrigger, TooltipContent } from "@neynar/ui/tooltip"
9
+ ```
10
+
11
+ ## Anatomy
12
+
13
+ ```tsx
14
+ <Tooltip>
15
+ <TooltipTrigger>Hover me</TooltipTrigger>
16
+ <TooltipContent>Helpful information</TooltipContent>
17
+ </Tooltip>
18
+ ```
19
+
20
+ ## Components
21
+
22
+ | Component | Description |
23
+ |-----------|-------------|
24
+ | Tooltip | Root container, manages open state automatically |
25
+ | TooltipTrigger | Element that shows tooltip on hover/focus |
26
+ | TooltipContent | Popup content with automatic portal, positioning, and arrow |
27
+ | TooltipProvider | Optional provider for configuring shared delay (auto-included in Tooltip) |
28
+
29
+ ## Props
30
+
31
+ ### Tooltip
32
+
33
+ | Prop | Type | Default | Description |
34
+ |------|------|---------|-------------|
35
+ | defaultOpen | boolean | - | Whether tooltip is initially open (uncontrolled) |
36
+ | open | boolean | - | Controlled open state |
37
+ | onOpenChange | (open: boolean) => void | - | Called when open state changes |
38
+ | trackCursorAxis | 'none' \| 'both' \| 'x' \| 'y' | 'none' | Which axis the tooltip should track the cursor on |
39
+
40
+ ### TooltipTrigger
41
+
42
+ Standard trigger props with `render` prop support. Use `render` to customize:
43
+
44
+ ```tsx
45
+ <TooltipTrigger render={<Button variant="ghost" size="icon" />}>
46
+ <SettingsIcon />
47
+ </TooltipTrigger>
48
+ ```
49
+
50
+ ### TooltipContent
51
+
52
+ Automatically renders portal with positioner and arrow.
53
+
54
+ | Prop | Type | Default | Description |
55
+ |------|------|---------|-------------|
56
+ | side | 'top' \| 'bottom' \| 'left' \| 'right' | 'top' | Which side to position tooltip |
57
+ | sideOffset | number | 4 | Distance from trigger in pixels |
58
+ | align | 'start' \| 'center' \| 'end' | 'center' | How to align tooltip relative to side |
59
+ | alignOffset | number | 0 | Offset along alignment axis in pixels |
60
+ | className | string | - | Additional CSS classes |
61
+
62
+ ### TooltipProvider
63
+
64
+ Only needed when sharing state across multiple tooltips. Tooltip automatically includes provider.
65
+
66
+ | Prop | Type | Default | Description |
67
+ |------|------|---------|-------------|
68
+ | delay | number | 0 | Delay in ms before showing tooltips |
69
+
70
+ ## Data Attributes (for styling)
71
+
72
+ | Attribute | When Present |
73
+ |-----------|--------------|
74
+ | data-open | Tooltip is open |
75
+ | data-closed | Tooltip is closed |
76
+ | data-side | Current side: 'top' \| 'bottom' \| 'left' \| 'right' |
77
+ | data-align | Current alignment: 'start' \| 'center' \| 'end' |
78
+ | data-starting-style | Tooltip is animating in |
79
+ | data-ending-style | Tooltip is animating out |
80
+ | data-instant | Animations should be instant |
81
+
82
+ ## Examples
83
+
84
+ ### Basic Usage
85
+
86
+ ```tsx
87
+ <Tooltip>
88
+ <TooltipTrigger>
89
+ <Button variant="outline">Hover me</Button>
90
+ </TooltipTrigger>
91
+ <TooltipContent>
92
+ <p>This is a tooltip</p>
93
+ </TooltipContent>
94
+ </Tooltip>
95
+ ```
96
+
97
+ ### Icon Button with Tooltip
98
+
99
+ ```tsx
100
+ <Tooltip>
101
+ <TooltipTrigger>
102
+ <Button variant="ghost" size="icon">
103
+ <SettingsIcon />
104
+ </Button>
105
+ </TooltipTrigger>
106
+ <TooltipContent>
107
+ <p>Settings</p>
108
+ </TooltipContent>
109
+ </Tooltip>
110
+ ```
111
+
112
+ ### Placement Options
113
+
114
+ ```tsx
115
+ <Tooltip>
116
+ <TooltipTrigger>
117
+ <Button>Show below</Button>
118
+ </TooltipTrigger>
119
+ <TooltipContent side="bottom" align="start">
120
+ <p>Positioned at bottom-start</p>
121
+ </TooltipContent>
122
+ </Tooltip>
123
+ ```
124
+
125
+ ### With Keyboard Shortcut
126
+
127
+ ```tsx
128
+ <Tooltip>
129
+ <TooltipTrigger>
130
+ <Button variant="outline">Save</Button>
131
+ </TooltipTrigger>
132
+ <TooltipContent>
133
+ <div className="flex items-center gap-2">
134
+ <span>Save document</span>
135
+ <kbd className="bg-background text-foreground rounded border px-1.5 py-0.5 font-mono text-xs">
136
+ ⌘S
137
+ </kbd>
138
+ </div>
139
+ </TooltipContent>
140
+ </Tooltip>
141
+ ```
142
+
143
+ ### Help Icon with Detailed Info
144
+
145
+ ```tsx
146
+ <Tooltip>
147
+ <TooltipTrigger>
148
+ <button className="text-muted-foreground hover:text-foreground inline-flex items-center transition-colors">
149
+ <HelpCircleIcon className="size-4" />
150
+ </button>
151
+ </TooltipTrigger>
152
+ <TooltipContent side="top">
153
+ <p className="max-w-xs">
154
+ Track your API requests, rate limits, and usage patterns across all your applications.
155
+ </p>
156
+ </TooltipContent>
157
+ </Tooltip>
158
+ ```
159
+
160
+ ### Always Open (Controlled)
161
+
162
+ ```tsx
163
+ <Tooltip defaultOpen>
164
+ <TooltipTrigger>
165
+ <Button variant="outline">Always visible</Button>
166
+ </TooltipTrigger>
167
+ <TooltipContent>
168
+ <p>This tooltip is always visible</p>
169
+ </TooltipContent>
170
+ </Tooltip>
171
+ ```
172
+
173
+ ## Keyboard
174
+
175
+ | Key | Action |
176
+ |-----|--------|
177
+ | Tab | Move focus to/from trigger |
178
+ | Escape | Close tooltip |
179
+
180
+ ## Accessibility
181
+
182
+ - Automatically adds ARIA attributes for screen readers
183
+ - Tooltip appears on hover and focus for keyboard users
184
+ - Content announced to screen readers when opened
185
+ - Works with disabled elements (tooltip still shows)
186
+ - Arrow provides visual relationship between trigger and content
187
+
188
+ ## Related
189
+
190
+ - [Popover](./popover.llm.md) - For interactive content requiring click to open
191
+ - [HoverCard](./hover-card.llm.md) - For rich preview content on hover