@g4rcez/components 3.0.0 → 3.0.1
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/dist/ai/SKILL.md +266 -0
- package/dist/ai/docs/Alert.md +167 -0
- package/dist/ai/docs/AnimatedList.md +205 -0
- package/dist/ai/docs/Autocomplete.md +225 -0
- package/dist/ai/docs/Button.md +182 -0
- package/dist/ai/docs/Calendar.md +219 -0
- package/dist/ai/docs/Card.md +174 -0
- package/dist/ai/docs/Checkbox.md +199 -0
- package/dist/ai/docs/CommandPalette.md +293 -0
- package/dist/ai/docs/DatePicker.md +171 -0
- package/dist/ai/docs/Dropdown.md +223 -0
- package/dist/ai/docs/Empty.md +163 -0
- package/dist/ai/docs/Expand.md +143 -0
- package/dist/ai/docs/FileUpload.md +225 -0
- package/dist/ai/docs/Form.md +107 -0
- package/dist/ai/docs/FormReset.md +117 -0
- package/dist/ai/docs/Heading.md +88 -0
- package/dist/ai/docs/Input.md +237 -0
- package/dist/ai/docs/InputField.md +170 -0
- package/dist/ai/docs/List.md +205 -0
- package/dist/ai/docs/Menu.md +166 -0
- package/dist/ai/docs/Modal.md +280 -0
- package/dist/ai/docs/MultiSelect.md +196 -0
- package/dist/ai/docs/Notifications.md +231 -0
- package/dist/ai/docs/PageCalendar.md +271 -0
- package/dist/ai/docs/Polymorph.md +159 -0
- package/dist/ai/docs/Progress.md +145 -0
- package/dist/ai/docs/Radiobox.md +128 -0
- package/dist/ai/docs/RenderOnView.md +138 -0
- package/dist/ai/docs/Resizable.md +159 -0
- package/dist/ai/docs/Select.md +284 -0
- package/dist/ai/docs/Shortcut.md +105 -0
- package/dist/ai/docs/Skeleton.md +166 -0
- package/dist/ai/docs/Slider.md +144 -0
- package/dist/ai/docs/Slot.md +173 -0
- package/dist/ai/docs/Spinner.md +118 -0
- package/dist/ai/docs/Stats.md +137 -0
- package/dist/ai/docs/Step.md +159 -0
- package/dist/ai/docs/Switch.md +167 -0
- package/dist/ai/docs/Table.md +298 -0
- package/dist/ai/docs/Tabs.md +191 -0
- package/dist/ai/docs/Tag.md +224 -0
- package/dist/ai/docs/TaskList.md +144 -0
- package/dist/ai/docs/Textarea.md +167 -0
- package/dist/ai/docs/Timeline.md +210 -0
- package/dist/ai/docs/Toolbar.md +132 -0
- package/dist/ai/docs/Tooltip.md +231 -0
- package/dist/ai/docs/TransferList.md +142 -0
- package/dist/ai/docs/Typography.md +187 -0
- package/dist/ai/docs/Wizard.md +213 -0
- package/dist/ai/docs/index.md +183 -0
- package/dist/components/core/tag.d.ts +1 -1
- package/dist/components/core/tag.d.ts.map +1 -1
- package/dist/components/display/list.d.ts.map +1 -1
- package/dist/components/floating/dropdown.d.ts +1 -0
- package/dist/components/floating/dropdown.d.ts.map +1 -1
- package/dist/components/floating/menu.d.ts.map +1 -1
- package/dist/config/default-translations.d.ts +4 -4
- package/dist/hooks/use-translations.d.ts +4 -4
- package/dist/hooks/use-translations.d.ts.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.js +28 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2463 -2458
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +12 -12
- package/dist/index.umd.js.map +1 -1
- package/package.json +4 -4
- package/dist/components/core/button.jsx +0 -79
- package/dist/components/core/heading.jsx +0 -4
- package/dist/components/core/polymorph.jsx +0 -5
- package/dist/components/core/render-on-view.jsx +0 -31
- package/dist/components/core/resizable.jsx +0 -51
- package/dist/components/core/slot.jsx +0 -156
- package/dist/components/core/tag.jsx +0 -51
- package/dist/components/core/typography.jsx +0 -22
- package/dist/components/display/alert.jsx +0 -58
- package/dist/components/display/calendar.jsx +0 -299
- package/dist/components/display/card.jsx +0 -43
- package/dist/components/display/empty.jsx +0 -11
- package/dist/components/display/list.jsx +0 -81
- package/dist/components/display/notifications.jsx +0 -126
- package/dist/components/display/progress.jsx +0 -11
- package/dist/components/display/shortcut.jsx +0 -23
- package/dist/components/display/skeleton.jsx +0 -12
- package/dist/components/display/spinner.jsx +0 -7
- package/dist/components/display/stats.jsx +0 -20
- package/dist/components/display/step.jsx +0 -131
- package/dist/components/display/tabs.jsx +0 -98
- package/dist/components/display/timeline.jsx +0 -25
- package/dist/components/floating/command-palette.jsx +0 -194
- package/dist/components/floating/dropdown.jsx +0 -53
- package/dist/components/floating/expand.jsx +0 -44
- package/dist/components/floating/menu.jsx +0 -147
- package/dist/components/floating/modal.jsx +0 -299
- package/dist/components/floating/toolbar.jsx +0 -5
- package/dist/components/floating/tooltip.jsx +0 -58
- package/dist/components/floating/wizard.jsx +0 -161
- package/dist/components/form/autocomplete.jsx +0 -279
- package/dist/components/form/checkbox.jsx +0 -12
- package/dist/components/form/date-picker.jsx +0 -115
- package/dist/components/form/file-upload.jsx +0 -133
- package/dist/components/form/form.jsx +0 -10
- package/dist/components/form/formReset.jsx +0 -17
- package/dist/components/form/free-text.jsx +0 -41
- package/dist/components/form/input-field.jsx +0 -56
- package/dist/components/form/input.jsx +0 -36
- package/dist/components/form/multi-select.jsx +0 -328
- package/dist/components/form/radiobox.jsx +0 -6
- package/dist/components/form/select.jsx +0 -42
- package/dist/components/form/slider.jsx +0 -45
- package/dist/components/form/switch.jsx +0 -46
- package/dist/components/form/task-list.jsx +0 -26
- package/dist/components/form/textarea.jsx +0 -12
- package/dist/components/form/transfer-list.jsx +0 -39
- package/dist/components/index.js +0 -45
- package/dist/components/page-calendar/calendar-header.jsx +0 -81
- package/dist/components/page-calendar/day-view.jsx +0 -87
- package/dist/components/page-calendar/event-pill.jsx +0 -25
- package/dist/components/page-calendar/index.js +0 -2
- package/dist/components/page-calendar/month-view.jsx +0 -47
- package/dist/components/page-calendar/page-calendar.jsx +0 -41
- package/dist/components/page-calendar/page-calendar.types.js +0 -1
- package/dist/components/page-calendar/page-calendar.utils.js +0 -71
- package/dist/components/page-calendar/week-view.jsx +0 -64
- package/dist/components/table/filter.jsx +0 -141
- package/dist/components/table/group.jsx +0 -68
- package/dist/components/table/index.jsx +0 -60
- package/dist/components/table/inner-table.jsx +0 -104
- package/dist/components/table/metadata.jsx +0 -36
- package/dist/components/table/pagination.jsx +0 -73
- package/dist/components/table/row.jsx +0 -58
- package/dist/components/table/sort.jsx +0 -105
- package/dist/components/table/table-lib.js +0 -83
- package/dist/components/table/table.context.jsx +0 -4
- package/dist/components/table/thead.jsx +0 -103
- package/dist/config/context.js +0 -12
- package/dist/config/default-translations.jsx +0 -83
- package/dist/config/default-tweaks.js +0 -4
- package/dist/constants.js +0 -2
- package/dist/hooks/use-click-outside.js +0 -17
- package/dist/hooks/use-color-parser.js +0 -9
- package/dist/hooks/use-components-provider.jsx +0 -19
- package/dist/hooks/use-debounce.js +0 -12
- package/dist/hooks/use-floating-ref.js +0 -6
- package/dist/hooks/use-form.js +0 -550
- package/dist/hooks/use-hover.js +0 -18
- package/dist/hooks/use-input-id.js +0 -5
- package/dist/hooks/use-is-coarse-device.js +0 -12
- package/dist/hooks/use-locale.js +0 -10
- package/dist/hooks/use-media-query.js +0 -25
- package/dist/hooks/use-on-event.js +0 -7
- package/dist/hooks/use-parent.js +0 -21
- package/dist/hooks/use-preferences.js +0 -23
- package/dist/hooks/use-previous.js +0 -9
- package/dist/hooks/use-reactive.js +0 -9
- package/dist/hooks/use-remove-scroll.js +0 -61
- package/dist/hooks/use-resize-observer.js +0 -17
- package/dist/hooks/use-stable-ref.js +0 -9
- package/dist/hooks/use-swipe.js +0 -17
- package/dist/hooks/use-translations.js +0 -9
- package/dist/hooks/use-tweaks.js +0 -9
- package/dist/hooks/use-window-size.js +0 -14
- package/dist/lib/combi-keys.js +0 -60
- package/dist/lib/dict.js +0 -39
- package/dist/lib/dom.js +0 -62
- package/dist/lib/fns.js +0 -46
- package/dist/lib/fzf.js +0 -117
- package/dist/lib/keyboard-area.js +0 -14
- package/dist/styles/common.js +0 -29
- package/dist/styles/dark.js +0 -214
- package/dist/styles/design-tokens.js +0 -69
- package/dist/styles/light.js +0 -214
- package/dist/styles/theme.js +0 -4
- package/dist/styles/theme.types.js +0 -1
- package/dist/types.js +0 -1
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Timeline
|
|
3
|
+
description: Vertical chronological event list with icon markers, body content, and optional right-side metadata.
|
|
4
|
+
package: "@g4rcez/components"
|
|
5
|
+
export: "{ Timeline }"
|
|
6
|
+
import: "import { Timeline, TimelineItem } from '@g4rcez/components/timeline'"
|
|
7
|
+
category: display
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Timeline
|
|
11
|
+
|
|
12
|
+
Vertical chronological event list with icon markers, body content, and optional right-side metadata.
|
|
13
|
+
|
|
14
|
+
## Import
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
import { Timeline, TimelineItem } from "@g4rcez/components/timeline";
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Components
|
|
21
|
+
|
|
22
|
+
### Timeline
|
|
23
|
+
|
|
24
|
+
The root container. Renders as a `<ul>` with `role="list"`. The vertical connector line on the last item is hidden automatically.
|
|
25
|
+
|
|
26
|
+
### TimelineItem
|
|
27
|
+
|
|
28
|
+
A single event entry. Renders as a `<li>` with `role="listitem"` and `pb-12` vertical spacing for the connector line.
|
|
29
|
+
|
|
30
|
+
### TimelineItem.Icon
|
|
31
|
+
|
|
32
|
+
The visual marker — a rounded circle, typically containing an icon. Renders as a `<header>`.
|
|
33
|
+
|
|
34
|
+
| Prop | Type | Default | Description |
|
|
35
|
+
|------|------|---------|-------------|
|
|
36
|
+
| `className` | `string` | — | Override icon container appearance |
|
|
37
|
+
| `children` | `React.ReactNode` | — | Icon element |
|
|
38
|
+
|
|
39
|
+
### TimelineItem.Body
|
|
40
|
+
|
|
41
|
+
The main content area. Polymorphic — defaults to `<section>`.
|
|
42
|
+
|
|
43
|
+
| Prop | Type | Default | Description |
|
|
44
|
+
|------|------|---------|-------------|
|
|
45
|
+
| `as` | `React.ElementType` | `"section"` | HTML element to render as |
|
|
46
|
+
| `className` | `string` | — | Additional classes |
|
|
47
|
+
| `children` | `React.ReactNode` | — | Event body content |
|
|
48
|
+
|
|
49
|
+
### TimelineItem.Right
|
|
50
|
+
|
|
51
|
+
Optional right-side slot for timestamps or auxiliary actions. Renders inside a `<footer>` wrapper. Polymorphic — defaults to `<button>`.
|
|
52
|
+
|
|
53
|
+
| Prop | Type | Default | Description |
|
|
54
|
+
|------|------|---------|-------------|
|
|
55
|
+
| `as` | `React.ElementType` | `"button"` | HTML element to render as |
|
|
56
|
+
| `children` | `React.ReactNode` | — | Right-side content |
|
|
57
|
+
|
|
58
|
+
## Design Tokens
|
|
59
|
+
|
|
60
|
+
Tokens this component reads. Customize by overriding these CSS variables in your theme.
|
|
61
|
+
|
|
62
|
+
| Token | CSS Variable | Purpose |
|
|
63
|
+
|-------|-------------|---------|
|
|
64
|
+
| `bg-card-border` | `--card-border` | Vertical connector line color |
|
|
65
|
+
| `bg-primary` | `--primary` | Icon container default background |
|
|
66
|
+
| `text-primary-foreground` | `--primary-foreground` | Icon default text/icon color |
|
|
67
|
+
|
|
68
|
+
## Examples
|
|
69
|
+
|
|
70
|
+
### Order Tracking Timeline
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
import { CheckIcon, PackageIcon, TruckIcon } from "lucide-react";
|
|
74
|
+
|
|
75
|
+
<Timeline>
|
|
76
|
+
<TimelineItem>
|
|
77
|
+
<TimelineItem.Icon>
|
|
78
|
+
<CheckIcon size={20} />
|
|
79
|
+
</TimelineItem.Icon>
|
|
80
|
+
<TimelineItem.Body>
|
|
81
|
+
<h4 className="font-bold">Order Placed</h4>
|
|
82
|
+
<p className="text-muted-foreground">Your order has been received and is being processed.</p>
|
|
83
|
+
</TimelineItem.Body>
|
|
84
|
+
<TimelineItem.Right as="time">10:00 AM</TimelineItem.Right>
|
|
85
|
+
</TimelineItem>
|
|
86
|
+
|
|
87
|
+
<TimelineItem>
|
|
88
|
+
<TimelineItem.Icon>
|
|
89
|
+
<PackageIcon size={20} />
|
|
90
|
+
</TimelineItem.Icon>
|
|
91
|
+
<TimelineItem.Body>
|
|
92
|
+
<h4 className="font-bold">Packed</h4>
|
|
93
|
+
<p className="text-muted-foreground">Your order has been packed and is ready for shipment.</p>
|
|
94
|
+
</TimelineItem.Body>
|
|
95
|
+
<TimelineItem.Right as="time">1:00 PM</TimelineItem.Right>
|
|
96
|
+
</TimelineItem>
|
|
97
|
+
|
|
98
|
+
<TimelineItem>
|
|
99
|
+
<TimelineItem.Icon>
|
|
100
|
+
<TruckIcon size={20} />
|
|
101
|
+
</TimelineItem.Icon>
|
|
102
|
+
<TimelineItem.Body>
|
|
103
|
+
<h4 className="font-bold">Shipped</h4>
|
|
104
|
+
<p className="text-muted-foreground">Your package is on its way.</p>
|
|
105
|
+
</TimelineItem.Body>
|
|
106
|
+
<TimelineItem.Right as="time">2:30 PM</TimelineItem.Right>
|
|
107
|
+
</TimelineItem>
|
|
108
|
+
</Timeline>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Simple Text Timeline
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
<Timeline>
|
|
115
|
+
<TimelineItem>
|
|
116
|
+
<TimelineItem.Body>
|
|
117
|
+
<strong>Step 1:</strong> Initial setup completed.
|
|
118
|
+
</TimelineItem.Body>
|
|
119
|
+
</TimelineItem>
|
|
120
|
+
<TimelineItem>
|
|
121
|
+
<TimelineItem.Body>
|
|
122
|
+
<strong>Step 2:</strong> Data migration started.
|
|
123
|
+
</TimelineItem.Body>
|
|
124
|
+
</TimelineItem>
|
|
125
|
+
</Timeline>
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Activity Feed
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
import { UserIcon, EditIcon, TrashIcon } from "lucide-react";
|
|
132
|
+
|
|
133
|
+
function ActivityFeed({ events }: { events: ActivityEvent[] }) {
|
|
134
|
+
const iconMap = {
|
|
135
|
+
create: UserIcon,
|
|
136
|
+
update: EditIcon,
|
|
137
|
+
delete: TrashIcon,
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
return (
|
|
141
|
+
<Timeline>
|
|
142
|
+
{events.map((event) => {
|
|
143
|
+
const Icon = iconMap[event.type];
|
|
144
|
+
return (
|
|
145
|
+
<TimelineItem key={event.id}>
|
|
146
|
+
<TimelineItem.Icon>
|
|
147
|
+
<Icon size={18} />
|
|
148
|
+
</TimelineItem.Icon>
|
|
149
|
+
<TimelineItem.Body>
|
|
150
|
+
<p className="font-medium">{event.user} {event.action}</p>
|
|
151
|
+
<p className="text-sm text-muted-foreground">{event.description}</p>
|
|
152
|
+
</TimelineItem.Body>
|
|
153
|
+
<TimelineItem.Right as="time" dateTime={event.iso}>
|
|
154
|
+
{event.relativeTime}
|
|
155
|
+
</TimelineItem.Right>
|
|
156
|
+
</TimelineItem>
|
|
157
|
+
);
|
|
158
|
+
})}
|
|
159
|
+
</Timeline>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Custom Icon Background
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
import { AlertCircleIcon } from "lucide-react";
|
|
168
|
+
|
|
169
|
+
<TimelineItem>
|
|
170
|
+
<TimelineItem.Icon className="bg-danger text-danger-foreground">
|
|
171
|
+
<AlertCircleIcon size={20} />
|
|
172
|
+
</TimelineItem.Icon>
|
|
173
|
+
<TimelineItem.Body>
|
|
174
|
+
<h4 className="font-bold text-danger-foreground">Deployment Failed</h4>
|
|
175
|
+
<p className="text-muted-foreground">Build step exited with code 1.</p>
|
|
176
|
+
</TimelineItem.Body>
|
|
177
|
+
</TimelineItem>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Do
|
|
181
|
+
|
|
182
|
+
- Use icons that clearly represent the status or type of event.
|
|
183
|
+
- Keep body content concise; link to a detail view for lengthy information.
|
|
184
|
+
- Maintain consistent chronological order (ascending or descending) throughout the list.
|
|
185
|
+
- Use semantic elements for timestamps — `as="time"` with a `dateTime` attribute.
|
|
186
|
+
- Use design-token classes for icon background overrides (`bg-success`, `bg-danger`).
|
|
187
|
+
|
|
188
|
+
## Don't
|
|
189
|
+
|
|
190
|
+
- Don't pass raw Tailwind color classes (`bg-green-500`, `text-red-600`) for icon backgrounds — use design tokens instead.
|
|
191
|
+
- Don't use arbitrary Tailwind values (`bg-[#abc]`) — override CSS variables in your `@theme` block.
|
|
192
|
+
- Don't cram too much information into a single `TimelineItem`; link to detail pages.
|
|
193
|
+
- Don't use `Timeline` for non-sequential data — use `List` or `Table` for unordered collections.
|
|
194
|
+
|
|
195
|
+
## Accessibility
|
|
196
|
+
|
|
197
|
+
- `Timeline` uses `<ul role="list">` and each `TimelineItem` uses `<li role="listitem">` for semantic list structure.
|
|
198
|
+
- The vertical connector `<span>` between items carries `aria-hidden="true"` since it is purely decorative.
|
|
199
|
+
- The last item's connector line is hidden via a CSS selector (`[&>li:last-child>span[aria-hidden=true]]:hidden`), removing it from layout without JS.
|
|
200
|
+
|
|
201
|
+
## Data Attributes
|
|
202
|
+
|
|
203
|
+
- `data-component="timeline"` — applied to the `<ul>` container.
|
|
204
|
+
- `data-component="timeline-item"` — applied to each `<li>` entry.
|
|
205
|
+
|
|
206
|
+
## Notes
|
|
207
|
+
|
|
208
|
+
- `TimelineItem.Right` defaults to `as="button"` — change to `as="time"` or `as="span"` if the right slot is non-interactive.
|
|
209
|
+
- Vertical spacing between entries is controlled by `pb-12` on `TimelineItem`; the connector line fills this gap.
|
|
210
|
+
- `TimelineItem` can be used without `TimelineItem.Icon` — the connector line still renders from the left edge.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Toolbar
|
|
3
|
+
description: Sticky floating toolbar for surfacing persistent actions at the bottom of a scrollable area.
|
|
4
|
+
package: "@g4rcez/components"
|
|
5
|
+
export: "{ Toolbar }"
|
|
6
|
+
import: "import { Toolbar } from '@g4rcez/components'"
|
|
7
|
+
category: floating
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Toolbar
|
|
11
|
+
|
|
12
|
+
Sticky floating toolbar for surfacing persistent actions at the bottom of a scrollable area.
|
|
13
|
+
|
|
14
|
+
## Import
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
import { Toolbar } from "@g4rcez/components";
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Props
|
|
21
|
+
|
|
22
|
+
| Prop | Type | Default | Description |
|
|
23
|
+
|------|------|---------|-------------|
|
|
24
|
+
| `children` | `React.ReactNode` | — | Items displayed inside the toolbar |
|
|
25
|
+
| `root` | `HTMLElement` | — | Optional root element reference for scrolling context |
|
|
26
|
+
|
|
27
|
+
## Design Tokens
|
|
28
|
+
|
|
29
|
+
Tokens this component reads. Customize by overriding these CSS variables in your theme.
|
|
30
|
+
|
|
31
|
+
| Token | CSS Variable | Purpose |
|
|
32
|
+
|-------|-------------|---------|
|
|
33
|
+
| `bg-background` | `--background` | Toolbar surface background |
|
|
34
|
+
| `border-card-border` | `--card-border` | Toolbar border |
|
|
35
|
+
| `rounded-lg` | — | Toolbar corner radius |
|
|
36
|
+
|
|
37
|
+
## Examples
|
|
38
|
+
|
|
39
|
+
### Form Actions Toolbar
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import { Toolbar } from "@g4rcez/components";
|
|
43
|
+
import { Button } from "@g4rcez/components/button";
|
|
44
|
+
|
|
45
|
+
<Toolbar>
|
|
46
|
+
<Button theme="ghost-muted">Cancel</Button>
|
|
47
|
+
<Button theme="primary">Save Changes</Button>
|
|
48
|
+
</Toolbar>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Rich Text Editor Toolbar
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react";
|
|
55
|
+
import { Toolbar } from "@g4rcez/components";
|
|
56
|
+
import { Button } from "@g4rcez/components/button";
|
|
57
|
+
import { Tooltip } from "@g4rcez/components/tooltip";
|
|
58
|
+
|
|
59
|
+
<Toolbar>
|
|
60
|
+
<Tooltip title="Bold">
|
|
61
|
+
<Button size="icon" theme="ghost-neutral">
|
|
62
|
+
<BoldIcon size={16} />
|
|
63
|
+
</Button>
|
|
64
|
+
</Tooltip>
|
|
65
|
+
<Tooltip title="Italic">
|
|
66
|
+
<Button size="icon" theme="ghost-neutral">
|
|
67
|
+
<ItalicIcon size={16} />
|
|
68
|
+
</Button>
|
|
69
|
+
</Tooltip>
|
|
70
|
+
<Tooltip title="Underline">
|
|
71
|
+
<Button size="icon" theme="ghost-neutral">
|
|
72
|
+
<UnderlineIcon size={16} />
|
|
73
|
+
</Button>
|
|
74
|
+
</Tooltip>
|
|
75
|
+
<div className="mx-2 h-6 w-px bg-card-border" />
|
|
76
|
+
<Button theme="primary" size="small">Publish</Button>
|
|
77
|
+
</Toolbar>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Batch Action Toolbar
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
import { TrashIcon, DownloadIcon } from "lucide-react";
|
|
84
|
+
import { Toolbar } from "@g4rcez/components";
|
|
85
|
+
import { Button } from "@g4rcez/components/button";
|
|
86
|
+
|
|
87
|
+
function BatchToolbar({ selectedCount }: { selectedCount: number }) {
|
|
88
|
+
if (selectedCount === 0) return null;
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<Toolbar>
|
|
92
|
+
<span className="text-sm text-muted-foreground">
|
|
93
|
+
{selectedCount} selected
|
|
94
|
+
</span>
|
|
95
|
+
<Button theme="ghost-neutral" size="small">
|
|
96
|
+
<DownloadIcon size={16} />
|
|
97
|
+
Export
|
|
98
|
+
</Button>
|
|
99
|
+
<Button theme="danger" size="small">
|
|
100
|
+
<TrashIcon size={16} />
|
|
101
|
+
Delete
|
|
102
|
+
</Button>
|
|
103
|
+
</Toolbar>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Do
|
|
109
|
+
|
|
110
|
+
- Keep the toolbar small — it overlays content and should not obscure more than a thin strip at the bottom.
|
|
111
|
+
- Reserve the toolbar for primary actions users may need at any scroll position.
|
|
112
|
+
- Provide sufficient spacing between touch targets for mobile usability.
|
|
113
|
+
- Use design-token classes for any custom styling inside the toolbar (`bg-background`, `border-card-border`, `text-foreground`).
|
|
114
|
+
|
|
115
|
+
## Don't
|
|
116
|
+
|
|
117
|
+
- Don't use `Toolbar` for secondary or rarely used actions — keep the surface focused.
|
|
118
|
+
- Don't cram too many items into the toolbar; it will wrap awkwardly on narrow viewports.
|
|
119
|
+
- Don't pass raw Tailwind color classes (`bg-gray-100`, `border-gray-300`) — use design-token classes.
|
|
120
|
+
- Don't use arbitrary Tailwind values (`bg-[#abc]`) — override CSS variables in your `@theme` block.
|
|
121
|
+
|
|
122
|
+
## Accessibility
|
|
123
|
+
|
|
124
|
+
- Wrap the toolbar in a `<div role="toolbar" aria-label="Page actions">` when it contains only icon buttons, so assistive technologies can announce the region.
|
|
125
|
+
- Ensure each icon-only button inside the toolbar has an accessible name via `aria-label` or a `Tooltip` with `focus={true}`.
|
|
126
|
+
- Tab key navigates through items in the toolbar naturally.
|
|
127
|
+
|
|
128
|
+
## Notes
|
|
129
|
+
|
|
130
|
+
- The component is a thin wrapper around `motion.div` from `motion/react` with `sticky bottom-4` positioning.
|
|
131
|
+
- The `root` prop is accepted but not yet used in the current implementation — it is reserved for future scrolling context support.
|
|
132
|
+
- Because the toolbar is `sticky` (not `fixed`), it flows with the document and sticks at the bottom of its scrolling container, not the viewport.
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Tooltip
|
|
3
|
+
description: Polymorphic tooltip with hover, focus, and click triggers; supports cursor-following and rich content.
|
|
4
|
+
package: "@g4rcez/components"
|
|
5
|
+
export: "{ Tooltip }"
|
|
6
|
+
import: "import { Tooltip } from '@g4rcez/components/tooltip'"
|
|
7
|
+
category: floating
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Tooltip
|
|
11
|
+
|
|
12
|
+
Polymorphic tooltip with hover, focus, and click triggers; supports cursor-following and rich content.
|
|
13
|
+
|
|
14
|
+
## Import
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
import { Tooltip } from "@g4rcez/components/tooltip";
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Props
|
|
21
|
+
|
|
22
|
+
| Prop | Type | Default | Description |
|
|
23
|
+
|------|------|---------|-------------|
|
|
24
|
+
| `title` | `Label` | — | Tooltip trigger element — the element the user interacts with |
|
|
25
|
+
| `children` | `React.ReactNode` | — | Tooltip popup content |
|
|
26
|
+
| `open` | `boolean` | — | Controlled open state |
|
|
27
|
+
| `enabled` | `boolean` | `true` | Enable or disable the tooltip entirely |
|
|
28
|
+
| `hover` | `boolean` | `true` | Show tooltip on hover |
|
|
29
|
+
| `focus` | `boolean` | `true` | Show tooltip on focus |
|
|
30
|
+
| `popover` | `boolean` | `true` | Show tooltip on click |
|
|
31
|
+
| `placement` | `Placement` | auto | Preferred placement; falls back via `autoPlacement` |
|
|
32
|
+
| `followCursor` | `boolean` | `false` | Tooltip follows the mouse cursor position |
|
|
33
|
+
| `onChange` | `(open: boolean) => void` | — | Open state change handler |
|
|
34
|
+
| `as` | `React.ElementType` | `"span"` | HTML element to render the trigger wrapper as |
|
|
35
|
+
|
|
36
|
+
> Note: `title` is the **trigger** and `children` is the **popup content**. This is the inverse of the HTML `title` attribute convention — the prop name matches how the component API evolved.
|
|
37
|
+
|
|
38
|
+
## Design Tokens
|
|
39
|
+
|
|
40
|
+
Tokens this component reads. Customize by overriding these CSS variables in your theme.
|
|
41
|
+
|
|
42
|
+
| Token | CSS Variable | Purpose |
|
|
43
|
+
|-------|-------------|---------|
|
|
44
|
+
| `bg-tooltip-background` | `--tooltip-background` | Tooltip popup background |
|
|
45
|
+
| `text-tooltip-foreground` | `--tooltip-foreground` | Tooltip popup text color |
|
|
46
|
+
| `border-tooltip-border` | `--tooltip-border` | Tooltip popup border and arrow stroke |
|
|
47
|
+
| `fill-tooltip-background` | `--tooltip-background` | Arrow fill color |
|
|
48
|
+
| `z-tooltip` | `--z-tooltip` | Z-index of the tooltip popup |
|
|
49
|
+
| `shadow-shadow-floating` | `--shadow-floating` | Tooltip drop shadow |
|
|
50
|
+
|
|
51
|
+
## Placement Options
|
|
52
|
+
|
|
53
|
+
Supports all Floating UI placements: `"top"`, `"top-start"`, `"top-end"`, `"bottom"`, `"bottom-start"`, `"bottom-end"`, `"left"`, `"left-start"`, `"left-end"`, `"right"`, `"right-start"`, `"right-end"`. When `placement` is omitted, `autoPlacement` picks the best available side.
|
|
54
|
+
|
|
55
|
+
## Examples
|
|
56
|
+
|
|
57
|
+
### Basic Hover Tooltip
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
import { Tooltip } from "@g4rcez/components/tooltip";
|
|
61
|
+
|
|
62
|
+
<Tooltip title={<button className="px-4 py-2 bg-primary text-primary-foreground rounded-button">Hover me</button>}>
|
|
63
|
+
This is a helpful tooltip
|
|
64
|
+
</Tooltip>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Icon Button with Label
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
import { SaveIcon } from "lucide-react";
|
|
71
|
+
import { Tooltip } from "@g4rcez/components/tooltip";
|
|
72
|
+
import { Button } from "@g4rcez/components/button";
|
|
73
|
+
|
|
74
|
+
<Tooltip title={<Button size="icon" theme="ghost-neutral"><SaveIcon size={16} /></Button>}>
|
|
75
|
+
Save (Ctrl+S)
|
|
76
|
+
</Tooltip>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Interaction Modes
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
import { Tooltip } from "@g4rcez/components/tooltip";
|
|
83
|
+
|
|
84
|
+
{/* Hover only */}
|
|
85
|
+
<Tooltip
|
|
86
|
+
title={<button className="px-4 py-2 rounded-button border border-border text-foreground">Hover Only</button>}
|
|
87
|
+
focus={false}
|
|
88
|
+
popover={false}
|
|
89
|
+
>
|
|
90
|
+
Shown on hover
|
|
91
|
+
</Tooltip>
|
|
92
|
+
|
|
93
|
+
{/* Focus only — keyboard accessible */}
|
|
94
|
+
<Tooltip
|
|
95
|
+
title={<input placeholder="Focus me with tab" className="px-3 py-2 rounded-button border border-border bg-background text-foreground" />}
|
|
96
|
+
hover={false}
|
|
97
|
+
popover={false}
|
|
98
|
+
>
|
|
99
|
+
Shown on focus
|
|
100
|
+
</Tooltip>
|
|
101
|
+
|
|
102
|
+
{/* Click only — acts like a popover */}
|
|
103
|
+
<Tooltip
|
|
104
|
+
title={<button className="px-4 py-2 bg-primary text-primary-foreground rounded-button">Click me</button>}
|
|
105
|
+
hover={false}
|
|
106
|
+
focus={false}
|
|
107
|
+
>
|
|
108
|
+
Shown on click
|
|
109
|
+
</Tooltip>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Cursor-Following Tooltip
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
import { Tooltip } from "@g4rcez/components/tooltip";
|
|
116
|
+
|
|
117
|
+
<Tooltip
|
|
118
|
+
followCursor
|
|
119
|
+
placement="top-start"
|
|
120
|
+
title={
|
|
121
|
+
<div className="w-full h-32 rounded-card border border-border bg-muted flex items-center justify-center">
|
|
122
|
+
<span className="text-muted-foreground">Move your mouse over this area</span>
|
|
123
|
+
</div>
|
|
124
|
+
}
|
|
125
|
+
>
|
|
126
|
+
Follows your cursor
|
|
127
|
+
</Tooltip>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Controlled Tooltip
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
import { useState } from "react";
|
|
134
|
+
import { Tooltip } from "@g4rcez/components/tooltip";
|
|
135
|
+
|
|
136
|
+
function ControlledTooltip() {
|
|
137
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
138
|
+
|
|
139
|
+
return (
|
|
140
|
+
<>
|
|
141
|
+
<Tooltip
|
|
142
|
+
title={<button className="px-4 py-2 rounded-button border border-border text-foreground">Target</button>}
|
|
143
|
+
open={isOpen}
|
|
144
|
+
onChange={setIsOpen}
|
|
145
|
+
hover={false}
|
|
146
|
+
focus={false}
|
|
147
|
+
popover={false}
|
|
148
|
+
>
|
|
149
|
+
Externally controlled
|
|
150
|
+
</Tooltip>
|
|
151
|
+
|
|
152
|
+
<div className="mt-4 flex gap-2">
|
|
153
|
+
<button onClick={() => setIsOpen(true)} className="px-3 py-1 bg-primary text-primary-foreground rounded-button text-sm">
|
|
154
|
+
Show
|
|
155
|
+
</button>
|
|
156
|
+
<button onClick={() => setIsOpen(false)} className="px-3 py-1 bg-muted text-foreground rounded-button text-sm">
|
|
157
|
+
Hide
|
|
158
|
+
</button>
|
|
159
|
+
</div>
|
|
160
|
+
</>
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Polymorphic — Render as Different Elements
|
|
166
|
+
|
|
167
|
+
```tsx
|
|
168
|
+
import { Tooltip } from "@g4rcez/components/tooltip";
|
|
169
|
+
|
|
170
|
+
{/* Render as <div> */}
|
|
171
|
+
<Tooltip
|
|
172
|
+
as="div"
|
|
173
|
+
title={<span className="p-3 bg-muted rounded-button inline-block text-foreground">Div with tooltip</span>}
|
|
174
|
+
>
|
|
175
|
+
Tooltip on a div
|
|
176
|
+
</Tooltip>
|
|
177
|
+
|
|
178
|
+
{/* Wrap a paragraph */}
|
|
179
|
+
<Tooltip
|
|
180
|
+
as="p"
|
|
181
|
+
title={<span className="text-primary cursor-pointer">Hover this paragraph</span>}
|
|
182
|
+
>
|
|
183
|
+
Paragraph tooltip
|
|
184
|
+
</Tooltip>
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Form Field Help Tooltip
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
import { InfoIcon } from "lucide-react";
|
|
191
|
+
import { Tooltip } from "@g4rcez/components/tooltip";
|
|
192
|
+
|
|
193
|
+
<label className="block text-sm font-medium text-foreground mb-1">
|
|
194
|
+
Username
|
|
195
|
+
<Tooltip
|
|
196
|
+
title={<InfoIcon className="inline ml-1 text-muted-foreground cursor-help" size={14} />}
|
|
197
|
+
>
|
|
198
|
+
3–20 characters; letters, numbers, and underscores only
|
|
199
|
+
</Tooltip>
|
|
200
|
+
</label>
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Do
|
|
204
|
+
|
|
205
|
+
- Always keep `focus={true}` (default) so keyboard users can access tooltips via Tab navigation.
|
|
206
|
+
- Keep tooltip content short — one or two sentences at most.
|
|
207
|
+
- Use `followCursor` for large interactive areas (charts, canvases) to keep the tip near the pointer.
|
|
208
|
+
- Use design-token classes for any custom elements inside the tooltip popup (`text-tooltip-foreground`, `bg-muted`, etc.).
|
|
209
|
+
|
|
210
|
+
## Don't
|
|
211
|
+
|
|
212
|
+
- Don't put essential information only in a tooltip — users on touch devices may never see it.
|
|
213
|
+
- Don't use tooltips for long text or complex layouts — use `Modal` or `Dropdown` instead.
|
|
214
|
+
- Don't pass raw Tailwind color classes (`bg-gray-900`, `text-white`) inside tooltip content — use design-token classes.
|
|
215
|
+
- Don't use arbitrary Tailwind values (`bg-[#abc]`, `z-[9999]`) — override CSS variables in your `@theme` block.
|
|
216
|
+
- Don't use tooltips on elements that are already self-explanatory.
|
|
217
|
+
|
|
218
|
+
## Accessibility
|
|
219
|
+
|
|
220
|
+
- By default all three triggers are active (`hover`, `focus`, `popover`); disable `focus` only when the trigger itself provides equivalent keyboard affordance.
|
|
221
|
+
- The tooltip popup receives `role="tooltip"` via Floating UI's `useRole`.
|
|
222
|
+
- `useDismiss` closes the tooltip when focus moves away or `Escape` is pressed.
|
|
223
|
+
- Safe-polygon hover handling keeps the tooltip open while the pointer moves toward interactive content (`popover={true}` enables this).
|
|
224
|
+
- The `as` prop lets you place the reference on a semantically correct element without extra wrapper divs.
|
|
225
|
+
|
|
226
|
+
## Notes
|
|
227
|
+
|
|
228
|
+
- The `open` prop syncs to internal state via `useEffect`; when provided, external changes override internal toggle state.
|
|
229
|
+
- `autoPlacement` middleware runs alongside `flip` — placement is fully automatic when `placement` is omitted.
|
|
230
|
+
- Hover delay is controlled by the shared `FLOATING_DELAY` constant; there is no per-instance delay prop.
|
|
231
|
+
- The component is polymorphic via the `Polymorph` core component for the popup and `as` for the trigger wrapper.
|