@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,224 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Tag
|
|
3
|
+
description: A label/badge component for displaying metadata, status, or categorization information.
|
|
4
|
+
package: "@g4rcez/components"
|
|
5
|
+
export: "{ Tag }"
|
|
6
|
+
import: "import { Tag } from '@g4rcez/components/tag'"
|
|
7
|
+
category: core
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Tag
|
|
11
|
+
|
|
12
|
+
A versatile label/badge component for displaying metadata, status, or categorization information. Built with polymorphic capabilities and multiple visual variants.
|
|
13
|
+
|
|
14
|
+
## Import
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
import { Tag } from "@g4rcez/components/tag";
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Props
|
|
21
|
+
|
|
22
|
+
| Prop | Type | Default | Description |
|
|
23
|
+
|------|------|---------|-------------|
|
|
24
|
+
| `theme` | `"primary" \| "secondary" \| "info" \| "warn" \| "danger" \| "success" \| "muted" \| "neutral" \| "custom" \| "disabled" \| "loading"` | `"primary"` | Visual theme/variant of the tag |
|
|
25
|
+
| `size` | `"icon" \| "small" \| "default" \| "big" \| "tiny"` | `"default"` | Size of the tag |
|
|
26
|
+
| `icon` | `React.ReactNode` | - | Icon to display inside the tag |
|
|
27
|
+
| `indicator` | `"primary" \| "secondary" \| "info" \| "warn" \| "danger" \| "success" \| "muted" \| "neutral"` | - | Shows a small colored dot before the label |
|
|
28
|
+
| `loading` | `boolean` | `false` | Overrides theme with pulse animation |
|
|
29
|
+
| `as` | `React.ElementType` | `"span"` | HTML element to render as |
|
|
30
|
+
| `className` | `string` | - | Additional CSS classes |
|
|
31
|
+
| `children` | `React.ReactNode` | - | Tag content |
|
|
32
|
+
|
|
33
|
+
## Design Tokens
|
|
34
|
+
|
|
35
|
+
Tokens this component reads. Customize by overriding these CSS variables in your theme.
|
|
36
|
+
|
|
37
|
+
| Token | CSS Variable | Purpose |
|
|
38
|
+
|-------|-------------|---------|
|
|
39
|
+
| `bg-tag-primary-bg` | `--tag-primary-bg` | Background for primary theme |
|
|
40
|
+
| `text-tag-primary-text` | `--tag-primary-text` | Text color for primary theme |
|
|
41
|
+
| `bg-tag-secondary-bg` | `--tag-secondary-bg` | Background for secondary theme |
|
|
42
|
+
| `text-tag-secondary-text` | `--tag-secondary-text` | Text color for secondary theme |
|
|
43
|
+
| `bg-tag-info-bg` | `--tag-info-bg` | Background for info theme |
|
|
44
|
+
| `text-tag-info-text` | `--tag-info-text` | Text color for info theme |
|
|
45
|
+
| `bg-tag-warn-bg` | `--tag-warn-bg` | Background for warn theme |
|
|
46
|
+
| `text-tag-warn-text` | `--tag-warn-text` | Text color for warn theme |
|
|
47
|
+
| `bg-tag-danger-bg` | `--tag-danger-bg` | Background for danger theme |
|
|
48
|
+
| `text-tag-danger-text` | `--tag-danger-text` | Text color for danger theme |
|
|
49
|
+
| `bg-tag-success-bg` | `--tag-success-bg` | Background for success theme |
|
|
50
|
+
| `text-tag-success-text` | `--tag-success-text` | Text color for success theme |
|
|
51
|
+
| `bg-tag-muted-bg` | `--tag-muted-bg` | Background for muted theme |
|
|
52
|
+
| `text-tag-muted-text` | `--tag-muted-text` | Text color for muted theme |
|
|
53
|
+
| `bg-disabled` | `--disabled` | Background for disabled/loading states |
|
|
54
|
+
| `border-card-border` | `--card-border` | Border color for neutral theme |
|
|
55
|
+
| `rounded-pill` | `--radius-pill` | Pill border radius applied to all tags |
|
|
56
|
+
| `bg-primary` | `--primary` | Dot color for primary indicator |
|
|
57
|
+
| `bg-secondary` | `--secondary` | Dot color for secondary indicator |
|
|
58
|
+
| `bg-info` | `--info` | Dot color for info indicator |
|
|
59
|
+
| `bg-warn` | `--warn` | Dot color for warn indicator |
|
|
60
|
+
| `bg-danger` | `--danger` | Dot color for danger indicator |
|
|
61
|
+
| `bg-success` | `--success` | Dot color for success indicator |
|
|
62
|
+
| `bg-muted` | `--muted` | Dot color for muted indicator |
|
|
63
|
+
|
|
64
|
+
## Theme Variants
|
|
65
|
+
|
|
66
|
+
- `primary`: Primary brand color
|
|
67
|
+
- `secondary`: Secondary color scheme
|
|
68
|
+
- `info`: Informational styling
|
|
69
|
+
- `warn`: Warning/caution styling
|
|
70
|
+
- `danger`: Error/destructive styling
|
|
71
|
+
- `success`: Success/positive styling
|
|
72
|
+
- `muted`: Subtle/subdued styling
|
|
73
|
+
- `neutral`: Transparent with card border
|
|
74
|
+
- `custom`: No default styling — supply all classes via `className`
|
|
75
|
+
- `disabled`: Disabled appearance with reduced opacity
|
|
76
|
+
- `loading`: Pulse animation (also triggered by the `loading` boolean prop)
|
|
77
|
+
|
|
78
|
+
## Examples
|
|
79
|
+
|
|
80
|
+
### Basic Variants
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
<Tag theme="primary">Primary</Tag>
|
|
84
|
+
<Tag theme="secondary">Secondary</Tag>
|
|
85
|
+
<Tag theme="info">Info</Tag>
|
|
86
|
+
<Tag theme="warn">Warning</Tag>
|
|
87
|
+
<Tag theme="danger">Error</Tag>
|
|
88
|
+
<Tag theme="success">Success</Tag>
|
|
89
|
+
<Tag theme="muted">Muted</Tag>
|
|
90
|
+
<Tag theme="neutral">Neutral</Tag>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Sizes
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
<Tag size="small">Small</Tag>
|
|
97
|
+
<Tag size="default">Default</Tag>
|
|
98
|
+
<Tag size="big">Big</Tag>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### With Icons
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
import { StarIcon, CheckIcon } from "lucide-react";
|
|
105
|
+
|
|
106
|
+
<Tag icon={<StarIcon size={14} />} theme="warn">Featured</Tag>
|
|
107
|
+
<Tag icon={<CheckIcon size={14} />} theme="success">Completed</Tag>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### With Indicators
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
<Tag indicator="success">Online</Tag>
|
|
114
|
+
<Tag indicator="danger">Offline</Tag>
|
|
115
|
+
<Tag indicator="warn">Pending</Tag>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Status Tags
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
const statusMap: Record<string, { theme: "success" | "warn" | "muted" | "danger" }> = {
|
|
122
|
+
active: { theme: "success" },
|
|
123
|
+
pending: { theme: "warn" },
|
|
124
|
+
inactive: { theme: "muted" },
|
|
125
|
+
error: { theme: "danger" },
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const StatusTag = ({ status }: { status: string }) => {
|
|
129
|
+
const config = statusMap[status] ?? statusMap.inactive;
|
|
130
|
+
return (
|
|
131
|
+
<Tag theme={config.theme} indicator={config.theme}>
|
|
132
|
+
{status.charAt(0).toUpperCase() + status.slice(1)}
|
|
133
|
+
</Tag>
|
|
134
|
+
);
|
|
135
|
+
};
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Loading State
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
<Tag loading theme="primary">Processing...</Tag>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Polymorphic Usage
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
<Tag as="button" onClick={() => void 0} theme="primary">
|
|
148
|
+
Clickable Tag
|
|
149
|
+
</Tag>
|
|
150
|
+
|
|
151
|
+
<Tag as="a" href="/category/react" theme="info">
|
|
152
|
+
React
|
|
153
|
+
</Tag>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Content Categorization
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
const categories = [
|
|
160
|
+
{ name: "React", theme: "info" },
|
|
161
|
+
{ name: "TypeScript", theme: "primary" },
|
|
162
|
+
{ name: "CSS", theme: "success" },
|
|
163
|
+
];
|
|
164
|
+
|
|
165
|
+
<div className="flex gap-2 flex-wrap">
|
|
166
|
+
{categories.map((cat) => (
|
|
167
|
+
<Tag key={cat.name} theme={cat.theme as any}>
|
|
168
|
+
{cat.name}
|
|
169
|
+
</Tag>
|
|
170
|
+
))}
|
|
171
|
+
</div>
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Notification Badge
|
|
175
|
+
|
|
176
|
+
```tsx
|
|
177
|
+
import { BellIcon } from "lucide-react";
|
|
178
|
+
|
|
179
|
+
<div className="relative">
|
|
180
|
+
<BellIcon size={24} />
|
|
181
|
+
<Tag
|
|
182
|
+
size="small"
|
|
183
|
+
theme="danger"
|
|
184
|
+
className="absolute -top-2 -right-2 min-w-[20px] h-5 text-xs"
|
|
185
|
+
>
|
|
186
|
+
3
|
|
187
|
+
</Tag>
|
|
188
|
+
</div>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Do
|
|
192
|
+
|
|
193
|
+
- Use `theme="success"` for positive states and `theme="danger"` for errors — keep it consistent
|
|
194
|
+
- Keep tag labels short and scannable
|
|
195
|
+
- Use `indicator` to add extra color meaning without extra text
|
|
196
|
+
- Use `as="button"` when the tag performs an action (e.g., removing a filter)
|
|
197
|
+
- Use design-token classes for wrapper elements (`bg-muted`, `border-border`)
|
|
198
|
+
|
|
199
|
+
## Don't
|
|
200
|
+
|
|
201
|
+
- Don't pass raw Tailwind color classes (`bg-blue-500`, `text-white`) — use `theme` prop instead
|
|
202
|
+
- Don't use arbitrary Tailwind values (`bg-[#abc]`, `bg-[--my-var]`) — override CSS variables in your `@theme` block
|
|
203
|
+
- Don't use too many different themes on one screen — excessive color variety is distracting
|
|
204
|
+
- Don't use `Tag` as a replacement for `Button` on primary actions
|
|
205
|
+
- Don't combine `icon` and `indicator` on a small tag — it becomes too visually busy
|
|
206
|
+
|
|
207
|
+
## Accessibility
|
|
208
|
+
|
|
209
|
+
- Uses semantic HTML via the `as` prop (defaults to `<span>`)
|
|
210
|
+
- The indicator dot is `aria-hidden="true"` — it is purely decorative
|
|
211
|
+
- When used as a `button` or `a`, standard keyboard navigation applies
|
|
212
|
+
- Ensure color meaning is supplemented by text — do not rely on color alone
|
|
213
|
+
|
|
214
|
+
## Data Attributes
|
|
215
|
+
|
|
216
|
+
- `data-component="tag"`: Identifies the component for styling/testing
|
|
217
|
+
- `data-theme`: Current theme variant value
|
|
218
|
+
|
|
219
|
+
## Notes
|
|
220
|
+
|
|
221
|
+
- The `loading` prop overrides the `theme` value and applies the loading animation
|
|
222
|
+
- Once `loading` becomes `false`, the original `theme` is restored
|
|
223
|
+
- The component forwards refs to the underlying element
|
|
224
|
+
- All standard HTML attributes for the target element are forwarded
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: TaskList
|
|
3
|
+
description: Fieldset container that triggers a celebratory animation when all child tasks are checked.
|
|
4
|
+
package: "@g4rcez/components"
|
|
5
|
+
export: "{ TaskList }"
|
|
6
|
+
import: "import { TaskList } from '@g4rcez/components/task-list'"
|
|
7
|
+
category: form
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# TaskList
|
|
11
|
+
|
|
12
|
+
Fieldset container that triggers a celebratory animation when all child tasks are checked.
|
|
13
|
+
|
|
14
|
+
## Import
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
import { TaskList } from "@g4rcez/components/task-list";
|
|
18
|
+
import { Checkbox } from "@g4rcez/components/checkbox";
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Props
|
|
22
|
+
|
|
23
|
+
Accepts all standard HTML `<fieldset>` attributes.
|
|
24
|
+
|
|
25
|
+
| Prop | Type | Default | Description |
|
|
26
|
+
|------|------|---------|-------------|
|
|
27
|
+
| `children` | `React.ReactNode` | — | `Checkbox` components with the `asTask` prop. |
|
|
28
|
+
| `className` | `string` | — | Additional CSS classes for the `<fieldset>`. |
|
|
29
|
+
|
|
30
|
+
## Design Tokens
|
|
31
|
+
|
|
32
|
+
`TaskList` itself is a plain `<fieldset>` and inherits ambient tokens from its children. No component-scoped tokens are consumed directly. Style the container using semantic tokens:
|
|
33
|
+
|
|
34
|
+
| Token | CSS Variable | Purpose |
|
|
35
|
+
|-------|-------------|---------|
|
|
36
|
+
| `border-border` | `--border` | Optional border around the task group |
|
|
37
|
+
| `bg-background` | `--background` | Container background |
|
|
38
|
+
| `text-foreground` | `--foreground` | Task label text |
|
|
39
|
+
|
|
40
|
+
## Examples
|
|
41
|
+
|
|
42
|
+
### Basic task list
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import { TaskList } from "@g4rcez/components/task-list";
|
|
46
|
+
import { Checkbox } from "@g4rcez/components/checkbox";
|
|
47
|
+
|
|
48
|
+
export default function OnboardingChecklist() {
|
|
49
|
+
return (
|
|
50
|
+
<TaskList className="flex flex-col gap-sm border border-border rounded-card p-4">
|
|
51
|
+
<Checkbox asTask>Complete initial setup</Checkbox>
|
|
52
|
+
<Checkbox asTask>Upload profile picture</Checkbox>
|
|
53
|
+
<Checkbox asTask>Verify email address</Checkbox>
|
|
54
|
+
</TaskList>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Dynamic tasks from state
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
import { useState } from "react";
|
|
63
|
+
import { TaskList } from "@g4rcez/components/task-list";
|
|
64
|
+
import { Checkbox } from "@g4rcez/components/checkbox";
|
|
65
|
+
|
|
66
|
+
type Task = { id: string; text: string; done: boolean };
|
|
67
|
+
|
|
68
|
+
export default function DynamicTaskList({ tasks }: { tasks: Task[] }) {
|
|
69
|
+
const [items, setItems] = useState(tasks);
|
|
70
|
+
|
|
71
|
+
const toggle = (id: string) =>
|
|
72
|
+
setItems((prev) =>
|
|
73
|
+
prev.map((t) => (t.id === id ? { ...t, done: !t.done } : t))
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<TaskList className="flex flex-col gap-sm">
|
|
78
|
+
{items.map((task) => (
|
|
79
|
+
<Checkbox
|
|
80
|
+
key={task.id}
|
|
81
|
+
asTask
|
|
82
|
+
checked={task.done}
|
|
83
|
+
onChange={() => toggle(task.id)}
|
|
84
|
+
>
|
|
85
|
+
{task.text}
|
|
86
|
+
</Checkbox>
|
|
87
|
+
))}
|
|
88
|
+
</TaskList>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Grouped tasks with a legend
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
import { TaskList } from "@g4rcez/components/task-list";
|
|
97
|
+
import { Checkbox } from "@g4rcez/components/checkbox";
|
|
98
|
+
|
|
99
|
+
export default function ProjectSubtasks() {
|
|
100
|
+
return (
|
|
101
|
+
<TaskList className="flex flex-col gap-sm rounded-card border border-border p-4">
|
|
102
|
+
<legend className="px-1 text-sm font-medium text-foreground">
|
|
103
|
+
Phase 1 — Design
|
|
104
|
+
</legend>
|
|
105
|
+
<Checkbox asTask>Create wireframes</Checkbox>
|
|
106
|
+
<Checkbox asTask>Review with stakeholders</Checkbox>
|
|
107
|
+
<Checkbox asTask>Export design tokens</Checkbox>
|
|
108
|
+
</TaskList>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Do
|
|
114
|
+
|
|
115
|
+
- Use `asTask` on every `Checkbox` inside `TaskList` so they are counted for the completion animation.
|
|
116
|
+
- Group closely related tasks — the animation is most meaningful when all items belong to one milestone.
|
|
117
|
+
- Provide adequate vertical spacing between items (`gap-sm`, `gap-base`) for readability.
|
|
118
|
+
- Use design-token classes for wrappers (`bg-background`, `border-border`, `rounded-card`).
|
|
119
|
+
|
|
120
|
+
## Don't
|
|
121
|
+
|
|
122
|
+
- Don't use `TaskList` for checkboxes that are not tasks (e.g., bulk-selection rows in a table).
|
|
123
|
+
- Don't pack too many unrelated tasks into a single list; split them into smaller groups.
|
|
124
|
+
- Don't pass raw Tailwind color classes (`bg-gray-100`, `border-gray-300`) — use design tokens instead.
|
|
125
|
+
- Don't use arbitrary Tailwind values (`bg-[#abc]`) — override CSS variables in your `@theme` block instead.
|
|
126
|
+
|
|
127
|
+
## Accessibility
|
|
128
|
+
|
|
129
|
+
- Renders a semantic `<fieldset>` to group related inputs — pair with a `<legend>` for a fully accessible group label.
|
|
130
|
+
- Inherits all accessibility features of the underlying `Checkbox` component.
|
|
131
|
+
- The completion animation (scale + rotate) is visual-only and does not alter keyboard or screen-reader behavior.
|
|
132
|
+
|
|
133
|
+
## Data Attributes
|
|
134
|
+
|
|
135
|
+
| Attribute | Element | Value | Description |
|
|
136
|
+
|-----------|---------|-------|-------------|
|
|
137
|
+
| `data-component` | `fieldset` | `"task-list"` | Identifies the component. |
|
|
138
|
+
| `data-task` | child `input` | `"true"` | Must be present on child checkbox inputs for them to be counted in the completion check. Set automatically via `asTask`. |
|
|
139
|
+
|
|
140
|
+
## Notes
|
|
141
|
+
|
|
142
|
+
- The animation is powered by `motion/react`. When all `input[data-task=true]` elements inside the fieldset are checked, a staggered scale + rotate animation fires starting from the last-checked item's index.
|
|
143
|
+
- `TaskList` attaches a single `change` event listener on the `<fieldset>` (event delegation) — no per-item wiring is required.
|
|
144
|
+
- The animation runs once per "all complete" event; unchecking an item and re-checking to completion will replay it.
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Textarea
|
|
3
|
+
description: Auto-growing multi-line text input built on the InputField foundation.
|
|
4
|
+
package: "@g4rcez/components"
|
|
5
|
+
export: "{ Textarea }"
|
|
6
|
+
import: "import { Textarea } from '@g4rcez/components'"
|
|
7
|
+
category: form
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Textarea
|
|
11
|
+
|
|
12
|
+
Auto-growing multi-line text input built on the InputField foundation.
|
|
13
|
+
|
|
14
|
+
## Import
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
import { Textarea } from "@g4rcez/components";
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Props
|
|
21
|
+
|
|
22
|
+
Inherits all `InputField` props and standard HTML `<textarea>` attributes, plus:
|
|
23
|
+
|
|
24
|
+
| Prop | Type | Default | Description |
|
|
25
|
+
|------|------|---------|-------------|
|
|
26
|
+
| `title` | `Label` | — | Label for the textarea. |
|
|
27
|
+
| `error` | `string` | — | Error message displayed below the field. |
|
|
28
|
+
| `loading` | `boolean` | `false` | Disables the field and signals a pending state. |
|
|
29
|
+
| `rows` | `number` | `2` | Initial number of visible text rows. |
|
|
30
|
+
| `next` | `string` | — | ID of the next element to focus when Enter is pressed (requires `enterKeyHint="next"`). |
|
|
31
|
+
| `placeholder` | `string` | — | Placeholder text. |
|
|
32
|
+
| `required` | `boolean` | — | Marks the field as required. |
|
|
33
|
+
| `className` | `string` | — | Additional CSS classes for the `<textarea>` element. |
|
|
34
|
+
|
|
35
|
+
## Design Tokens
|
|
36
|
+
|
|
37
|
+
Tokens this component reads. Customize by overriding these CSS variables in your theme.
|
|
38
|
+
|
|
39
|
+
| Token | CSS Variable | Purpose |
|
|
40
|
+
|-------|-------------|---------|
|
|
41
|
+
| `placeholder-input-mask` | `--input-mask` | Placeholder text color |
|
|
42
|
+
| `placeholder-input-mask-error` (via `group-error`) | `--input-mask-error` | Placeholder tint in error state |
|
|
43
|
+
| `text-foreground` | `--foreground` | Input text color |
|
|
44
|
+
| `text-danger` (via `group-error`) | `--danger` | Text color in error state |
|
|
45
|
+
| `bg-transparent` | — | Input background (inherits from field wrapper) |
|
|
46
|
+
| `focus:ring-primary` | `--primary` | Focus ring |
|
|
47
|
+
| `group-focus-within:border-primary` | `--primary` | Border highlight on focus |
|
|
48
|
+
| `group-hover:border-primary` | `--primary` | Border highlight on hover |
|
|
49
|
+
| `h-input-height` | `--input-height` | Base height token (overridden by `rows` in practice) |
|
|
50
|
+
| `px-input-x` | `--input-x` | Horizontal padding |
|
|
51
|
+
| `py-input-y` | `--input-y` | Vertical padding |
|
|
52
|
+
|
|
53
|
+
## Examples
|
|
54
|
+
|
|
55
|
+
### Basic usage
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
import { Textarea } from "@g4rcez/components";
|
|
59
|
+
|
|
60
|
+
export default function BioField() {
|
|
61
|
+
return (
|
|
62
|
+
<Textarea
|
|
63
|
+
title="Bio"
|
|
64
|
+
name="bio"
|
|
65
|
+
placeholder="Tell us about yourself…"
|
|
66
|
+
rows={4}
|
|
67
|
+
onChange={(e) => console.log(e.target.value)}
|
|
68
|
+
/>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### With validation error
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
import { Textarea } from "@g4rcez/components";
|
|
77
|
+
|
|
78
|
+
export default function MessageField() {
|
|
79
|
+
return (
|
|
80
|
+
<Textarea
|
|
81
|
+
title="Message"
|
|
82
|
+
name="message"
|
|
83
|
+
required
|
|
84
|
+
error="Message is required and must be at least 10 characters."
|
|
85
|
+
placeholder="Enter your message…"
|
|
86
|
+
/>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Monospace styling for code
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
import { Textarea } from "@g4rcez/components";
|
|
95
|
+
|
|
96
|
+
export default function CssSnippetField() {
|
|
97
|
+
return (
|
|
98
|
+
<Textarea
|
|
99
|
+
title="CSS Snippet"
|
|
100
|
+
name="css"
|
|
101
|
+
className="font-mono text-sm"
|
|
102
|
+
rows={6}
|
|
103
|
+
placeholder="body { margin: 0; }"
|
|
104
|
+
/>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Focus-next navigation
|
|
110
|
+
|
|
111
|
+
```tsx
|
|
112
|
+
import { Textarea } from "@g4rcez/components";
|
|
113
|
+
import { Input } from "@g4rcez/components";
|
|
114
|
+
|
|
115
|
+
export default function MultiFieldForm() {
|
|
116
|
+
return (
|
|
117
|
+
<div className="flex flex-col gap-base">
|
|
118
|
+
<Textarea
|
|
119
|
+
title="Description"
|
|
120
|
+
name="description"
|
|
121
|
+
enterKeyHint="next"
|
|
122
|
+
next="submit-btn"
|
|
123
|
+
rows={3}
|
|
124
|
+
placeholder="Describe the issue…"
|
|
125
|
+
/>
|
|
126
|
+
<button id="submit-btn" type="submit" className="btn">
|
|
127
|
+
Submit
|
|
128
|
+
</button>
|
|
129
|
+
</div>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Do
|
|
135
|
+
|
|
136
|
+
- Provide a descriptive `title` to label the field.
|
|
137
|
+
- Set a sensible initial `rows` value based on the expected content length.
|
|
138
|
+
- Use `Textarea` whenever the user is expected to provide more than a single line of text.
|
|
139
|
+
- Use design-token classes on wrapper elements (`bg-background`, `text-foreground`, `border-border`).
|
|
140
|
+
|
|
141
|
+
## Don't
|
|
142
|
+
|
|
143
|
+
- Don't use `Textarea` for single-line inputs like names or emails — use `Input` instead.
|
|
144
|
+
- Don't fix the height with a `className` like `h-32` if you want the auto-resize behavior to work.
|
|
145
|
+
- Don't pass raw Tailwind color classes (`bg-gray-50`, `border-gray-300`) — use design tokens instead.
|
|
146
|
+
- Don't use arbitrary Tailwind values (`bg-[#abc]`) — override CSS variables in your `@theme` block instead.
|
|
147
|
+
|
|
148
|
+
## Accessibility
|
|
149
|
+
|
|
150
|
+
- Rendered inside an `InputField` which wraps the element with `<fieldset>` and a `<label>` linked via `id`/`for`.
|
|
151
|
+
- Supports `aria-required`, `aria-invalid`, `aria-disabled`, and `aria-readonly` via prop spread.
|
|
152
|
+
- Keyboard navigation follows standard `<textarea>` behavior (Tab to focus, Shift+Tab to leave).
|
|
153
|
+
- When `enterKeyHint="next"` and a `next` id is provided, pressing Enter moves focus to the target element.
|
|
154
|
+
|
|
155
|
+
## Data Attributes
|
|
156
|
+
|
|
157
|
+
| Attribute | Element | Value | Description |
|
|
158
|
+
|-----------|---------|-------|-------------|
|
|
159
|
+
| `data-component` | `InputField` root | `"textarea"` | Identifies the component. |
|
|
160
|
+
| `data-error` | `InputField` root | truthy string | Present when an error message is supplied. |
|
|
161
|
+
| `data-next` | `<textarea>` | element id | Target element id for Enter-key focus forwarding. |
|
|
162
|
+
|
|
163
|
+
## Notes
|
|
164
|
+
|
|
165
|
+
- Auto-resize is driven by a native `input` event listener that sets `style.height = "auto"` then `style.height = scrollHeight + "px"` — no JavaScript polling or ResizeObserver involved.
|
|
166
|
+
- The resize handle is set to `resize-y` by default; add `className="resize-none"` to disable it.
|
|
167
|
+
- Built via the shared `createFreeText` factory, which also powers the `Input` component — all `InputField` layout features (left/right slots, optional text, feedback, etc.) are available.
|