@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.
Files changed (176) hide show
  1. package/dist/ai/SKILL.md +266 -0
  2. package/dist/ai/docs/Alert.md +167 -0
  3. package/dist/ai/docs/AnimatedList.md +205 -0
  4. package/dist/ai/docs/Autocomplete.md +225 -0
  5. package/dist/ai/docs/Button.md +182 -0
  6. package/dist/ai/docs/Calendar.md +219 -0
  7. package/dist/ai/docs/Card.md +174 -0
  8. package/dist/ai/docs/Checkbox.md +199 -0
  9. package/dist/ai/docs/CommandPalette.md +293 -0
  10. package/dist/ai/docs/DatePicker.md +171 -0
  11. package/dist/ai/docs/Dropdown.md +223 -0
  12. package/dist/ai/docs/Empty.md +163 -0
  13. package/dist/ai/docs/Expand.md +143 -0
  14. package/dist/ai/docs/FileUpload.md +225 -0
  15. package/dist/ai/docs/Form.md +107 -0
  16. package/dist/ai/docs/FormReset.md +117 -0
  17. package/dist/ai/docs/Heading.md +88 -0
  18. package/dist/ai/docs/Input.md +237 -0
  19. package/dist/ai/docs/InputField.md +170 -0
  20. package/dist/ai/docs/List.md +205 -0
  21. package/dist/ai/docs/Menu.md +166 -0
  22. package/dist/ai/docs/Modal.md +280 -0
  23. package/dist/ai/docs/MultiSelect.md +196 -0
  24. package/dist/ai/docs/Notifications.md +231 -0
  25. package/dist/ai/docs/PageCalendar.md +271 -0
  26. package/dist/ai/docs/Polymorph.md +159 -0
  27. package/dist/ai/docs/Progress.md +145 -0
  28. package/dist/ai/docs/Radiobox.md +128 -0
  29. package/dist/ai/docs/RenderOnView.md +138 -0
  30. package/dist/ai/docs/Resizable.md +159 -0
  31. package/dist/ai/docs/Select.md +284 -0
  32. package/dist/ai/docs/Shortcut.md +105 -0
  33. package/dist/ai/docs/Skeleton.md +166 -0
  34. package/dist/ai/docs/Slider.md +144 -0
  35. package/dist/ai/docs/Slot.md +173 -0
  36. package/dist/ai/docs/Spinner.md +118 -0
  37. package/dist/ai/docs/Stats.md +137 -0
  38. package/dist/ai/docs/Step.md +159 -0
  39. package/dist/ai/docs/Switch.md +167 -0
  40. package/dist/ai/docs/Table.md +298 -0
  41. package/dist/ai/docs/Tabs.md +191 -0
  42. package/dist/ai/docs/Tag.md +224 -0
  43. package/dist/ai/docs/TaskList.md +144 -0
  44. package/dist/ai/docs/Textarea.md +167 -0
  45. package/dist/ai/docs/Timeline.md +210 -0
  46. package/dist/ai/docs/Toolbar.md +132 -0
  47. package/dist/ai/docs/Tooltip.md +231 -0
  48. package/dist/ai/docs/TransferList.md +142 -0
  49. package/dist/ai/docs/Typography.md +187 -0
  50. package/dist/ai/docs/Wizard.md +213 -0
  51. package/dist/ai/docs/index.md +183 -0
  52. package/dist/components/core/tag.d.ts +1 -1
  53. package/dist/components/core/tag.d.ts.map +1 -1
  54. package/dist/components/display/list.d.ts.map +1 -1
  55. package/dist/components/floating/dropdown.d.ts +1 -0
  56. package/dist/components/floating/dropdown.d.ts.map +1 -1
  57. package/dist/components/floating/menu.d.ts.map +1 -1
  58. package/dist/config/default-translations.d.ts +4 -4
  59. package/dist/hooks/use-translations.d.ts +4 -4
  60. package/dist/hooks/use-translations.d.ts.map +1 -1
  61. package/dist/index.css +1 -1
  62. package/dist/index.js +28 -20
  63. package/dist/index.js.map +1 -1
  64. package/dist/index.mjs +2463 -2458
  65. package/dist/index.mjs.map +1 -1
  66. package/dist/index.umd.js +12 -12
  67. package/dist/index.umd.js.map +1 -1
  68. package/package.json +4 -4
  69. package/dist/components/core/button.jsx +0 -79
  70. package/dist/components/core/heading.jsx +0 -4
  71. package/dist/components/core/polymorph.jsx +0 -5
  72. package/dist/components/core/render-on-view.jsx +0 -31
  73. package/dist/components/core/resizable.jsx +0 -51
  74. package/dist/components/core/slot.jsx +0 -156
  75. package/dist/components/core/tag.jsx +0 -51
  76. package/dist/components/core/typography.jsx +0 -22
  77. package/dist/components/display/alert.jsx +0 -58
  78. package/dist/components/display/calendar.jsx +0 -299
  79. package/dist/components/display/card.jsx +0 -43
  80. package/dist/components/display/empty.jsx +0 -11
  81. package/dist/components/display/list.jsx +0 -81
  82. package/dist/components/display/notifications.jsx +0 -126
  83. package/dist/components/display/progress.jsx +0 -11
  84. package/dist/components/display/shortcut.jsx +0 -23
  85. package/dist/components/display/skeleton.jsx +0 -12
  86. package/dist/components/display/spinner.jsx +0 -7
  87. package/dist/components/display/stats.jsx +0 -20
  88. package/dist/components/display/step.jsx +0 -131
  89. package/dist/components/display/tabs.jsx +0 -98
  90. package/dist/components/display/timeline.jsx +0 -25
  91. package/dist/components/floating/command-palette.jsx +0 -194
  92. package/dist/components/floating/dropdown.jsx +0 -53
  93. package/dist/components/floating/expand.jsx +0 -44
  94. package/dist/components/floating/menu.jsx +0 -147
  95. package/dist/components/floating/modal.jsx +0 -299
  96. package/dist/components/floating/toolbar.jsx +0 -5
  97. package/dist/components/floating/tooltip.jsx +0 -58
  98. package/dist/components/floating/wizard.jsx +0 -161
  99. package/dist/components/form/autocomplete.jsx +0 -279
  100. package/dist/components/form/checkbox.jsx +0 -12
  101. package/dist/components/form/date-picker.jsx +0 -115
  102. package/dist/components/form/file-upload.jsx +0 -133
  103. package/dist/components/form/form.jsx +0 -10
  104. package/dist/components/form/formReset.jsx +0 -17
  105. package/dist/components/form/free-text.jsx +0 -41
  106. package/dist/components/form/input-field.jsx +0 -56
  107. package/dist/components/form/input.jsx +0 -36
  108. package/dist/components/form/multi-select.jsx +0 -328
  109. package/dist/components/form/radiobox.jsx +0 -6
  110. package/dist/components/form/select.jsx +0 -42
  111. package/dist/components/form/slider.jsx +0 -45
  112. package/dist/components/form/switch.jsx +0 -46
  113. package/dist/components/form/task-list.jsx +0 -26
  114. package/dist/components/form/textarea.jsx +0 -12
  115. package/dist/components/form/transfer-list.jsx +0 -39
  116. package/dist/components/index.js +0 -45
  117. package/dist/components/page-calendar/calendar-header.jsx +0 -81
  118. package/dist/components/page-calendar/day-view.jsx +0 -87
  119. package/dist/components/page-calendar/event-pill.jsx +0 -25
  120. package/dist/components/page-calendar/index.js +0 -2
  121. package/dist/components/page-calendar/month-view.jsx +0 -47
  122. package/dist/components/page-calendar/page-calendar.jsx +0 -41
  123. package/dist/components/page-calendar/page-calendar.types.js +0 -1
  124. package/dist/components/page-calendar/page-calendar.utils.js +0 -71
  125. package/dist/components/page-calendar/week-view.jsx +0 -64
  126. package/dist/components/table/filter.jsx +0 -141
  127. package/dist/components/table/group.jsx +0 -68
  128. package/dist/components/table/index.jsx +0 -60
  129. package/dist/components/table/inner-table.jsx +0 -104
  130. package/dist/components/table/metadata.jsx +0 -36
  131. package/dist/components/table/pagination.jsx +0 -73
  132. package/dist/components/table/row.jsx +0 -58
  133. package/dist/components/table/sort.jsx +0 -105
  134. package/dist/components/table/table-lib.js +0 -83
  135. package/dist/components/table/table.context.jsx +0 -4
  136. package/dist/components/table/thead.jsx +0 -103
  137. package/dist/config/context.js +0 -12
  138. package/dist/config/default-translations.jsx +0 -83
  139. package/dist/config/default-tweaks.js +0 -4
  140. package/dist/constants.js +0 -2
  141. package/dist/hooks/use-click-outside.js +0 -17
  142. package/dist/hooks/use-color-parser.js +0 -9
  143. package/dist/hooks/use-components-provider.jsx +0 -19
  144. package/dist/hooks/use-debounce.js +0 -12
  145. package/dist/hooks/use-floating-ref.js +0 -6
  146. package/dist/hooks/use-form.js +0 -550
  147. package/dist/hooks/use-hover.js +0 -18
  148. package/dist/hooks/use-input-id.js +0 -5
  149. package/dist/hooks/use-is-coarse-device.js +0 -12
  150. package/dist/hooks/use-locale.js +0 -10
  151. package/dist/hooks/use-media-query.js +0 -25
  152. package/dist/hooks/use-on-event.js +0 -7
  153. package/dist/hooks/use-parent.js +0 -21
  154. package/dist/hooks/use-preferences.js +0 -23
  155. package/dist/hooks/use-previous.js +0 -9
  156. package/dist/hooks/use-reactive.js +0 -9
  157. package/dist/hooks/use-remove-scroll.js +0 -61
  158. package/dist/hooks/use-resize-observer.js +0 -17
  159. package/dist/hooks/use-stable-ref.js +0 -9
  160. package/dist/hooks/use-swipe.js +0 -17
  161. package/dist/hooks/use-translations.js +0 -9
  162. package/dist/hooks/use-tweaks.js +0 -9
  163. package/dist/hooks/use-window-size.js +0 -14
  164. package/dist/lib/combi-keys.js +0 -60
  165. package/dist/lib/dict.js +0 -39
  166. package/dist/lib/dom.js +0 -62
  167. package/dist/lib/fns.js +0 -46
  168. package/dist/lib/fzf.js +0 -117
  169. package/dist/lib/keyboard-area.js +0 -14
  170. package/dist/styles/common.js +0 -29
  171. package/dist/styles/dark.js +0 -214
  172. package/dist/styles/design-tokens.js +0 -69
  173. package/dist/styles/light.js +0 -214
  174. package/dist/styles/theme.js +0 -4
  175. package/dist/styles/theme.types.js +0 -1
  176. package/dist/types.js +0 -1
@@ -0,0 +1,284 @@
1
+ ---
2
+ title: Select
3
+ description: Styled native select component with validation, loading state, and form integration.
4
+ package: "@g4rcez/components"
5
+ export: "{ Select }"
6
+ import: "import { Select } from '@g4rcez/components/select'"
7
+ category: form
8
+ ---
9
+
10
+ # Select
11
+
12
+ Styled native select component with validation, loading state, and form integration.
13
+
14
+ ## Import
15
+
16
+ ```tsx
17
+ import { Select } from "@g4rcez/components/select";
18
+ ```
19
+
20
+ ## Props
21
+
22
+ | Prop | Type | Default | Description |
23
+ |------|------|---------|-------------|
24
+ | `options` | `OptionProps[]` | — | Array of option objects. |
25
+ | `selectContainer` | `string` | `""` | Additional CSS classes for the select container. |
26
+ | `required` | `boolean` | `true` | Whether the field is required. |
27
+ | `error` | `string` | — | Error message to display. |
28
+ | `loading` | `boolean` | `false` | Shows a loading indicator and disables the field. |
29
+ | `disabled` | `boolean` | `false` | Disables the select. |
30
+ | `placeholder` | `string` | — | Placeholder shown as a disabled hidden option. |
31
+ | `value` | `string` | — | Controlled selected value. |
32
+ | `onChange` | `(e: ChangeEvent<HTMLSelectElement>) => void` | — | Change handler. |
33
+ | `...inputFieldProps` | `InputFieldProps` | — | All `InputField` props (title, left, right, feedback, etc.). |
34
+
35
+ ### OptionProps
36
+
37
+ | Prop | Type | Description |
38
+ |------|------|-------------|
39
+ | `value` | `string` | Option value (required). |
40
+ | `label` | `string` | Display text (falls back to `value` if omitted). |
41
+ | `disabled` | `boolean` | Disables this individual option. |
42
+ | `data-dynamic` | `string` | Marks a dynamically generated option. |
43
+ | `data-*` | `string` | Any custom data attributes forwarded to the `<option>`. |
44
+
45
+ ## Design Tokens
46
+
47
+ Tokens this component reads. Customize by overriding these CSS variables in your theme.
48
+
49
+ | Token | CSS Variable | Purpose |
50
+ |-------|-------------|---------|
51
+ | `text-foreground` | `--foreground` | Selected option text color |
52
+ | `text-input-placeholder` | `--input-placeholder` | Color when no option is selected |
53
+ | `placeholder-input-placeholder` | `--input-placeholder` | Placeholder styling |
54
+ | `bg-input-mask-error` (via `group-error`) | `--input-mask-error` | Placeholder tint in error state |
55
+ | `text-danger` (via `group-error`) | `--danger` | Text color in error state |
56
+ | `hover:text-primary` | `--primary` | Caret icon hover color |
57
+ | `h-input-height` | `--input-height` | Control height (2.5 rem) |
58
+ | `px-input-x` | `--input-x` | Horizontal padding |
59
+ | `py-input-y` | `--input-y` | Vertical padding |
60
+
61
+ ## Examples
62
+
63
+ ### Basic usage
64
+
65
+ ```tsx
66
+ import { useState } from "react";
67
+ import { Select } from "@g4rcez/components/select";
68
+
69
+ export default function FruitPicker() {
70
+ const [value, setValue] = useState("");
71
+
72
+ return (
73
+ <Select
74
+ title="Fruit"
75
+ options={[
76
+ { value: "apple", label: "Apple" },
77
+ { value: "banana", label: "Banana" },
78
+ { value: "orange", label: "Orange" },
79
+ ]}
80
+ placeholder="Select a fruit"
81
+ value={value}
82
+ onChange={(e) => setValue(e.target.value)}
83
+ />
84
+ );
85
+ }
86
+ ```
87
+
88
+ ### With validation error
89
+
90
+ ```tsx
91
+ import { useState } from "react";
92
+ import { Select } from "@g4rcez/components/select";
93
+
94
+ export default function CountrySelect() {
95
+ const [country, setCountry] = useState("");
96
+ const [error, setError] = useState("");
97
+
98
+ return (
99
+ <Select
100
+ title="Country"
101
+ options={[
102
+ { value: "us", label: "United States" },
103
+ { value: "ca", label: "Canada" },
104
+ { value: "uk", label: "United Kingdom" },
105
+ ]}
106
+ placeholder="Select country"
107
+ value={country}
108
+ error={error}
109
+ required
110
+ onChange={(e) => {
111
+ setCountry(e.target.value);
112
+ setError(e.target.value ? "" : "Please select a country");
113
+ }}
114
+ />
115
+ );
116
+ }
117
+ ```
118
+
119
+ ### With disabled options
120
+
121
+ ```tsx
122
+ import { Select } from "@g4rcez/components/select";
123
+
124
+ export default function StatusSelect() {
125
+ return (
126
+ <Select
127
+ title="Status"
128
+ options={[
129
+ { value: "active", label: "Active" },
130
+ { value: "pending", label: "Pending" },
131
+ { value: "legacy", label: "Legacy (deprecated)", disabled: true },
132
+ { value: "inactive", label: "Inactive" },
133
+ ]}
134
+ placeholder="Select status"
135
+ />
136
+ );
137
+ }
138
+ ```
139
+
140
+ ### Async options with loading state
141
+
142
+ ```tsx
143
+ import { useEffect, useState } from "react";
144
+ import { Select } from "@g4rcez/components/select";
145
+
146
+ export default function AsyncSelect() {
147
+ const [options, setOptions] = useState<{ value: string; label: string }[]>([]);
148
+ const [loading, setLoading] = useState(false);
149
+ const [value, setValue] = useState("");
150
+
151
+ useEffect(() => {
152
+ setLoading(true);
153
+ fetchOptions().then((data) => {
154
+ setOptions(data);
155
+ setLoading(false);
156
+ });
157
+ }, []);
158
+
159
+ return (
160
+ <Select
161
+ title="Region"
162
+ options={options}
163
+ placeholder={loading ? "Loading..." : "Select a region"}
164
+ value={value}
165
+ loading={loading}
166
+ disabled={loading}
167
+ onChange={(e) => setValue(e.target.value)}
168
+ />
169
+ );
170
+ }
171
+ ```
172
+
173
+ ### Form integration with `useForm`
174
+
175
+ ```tsx
176
+ import { Select } from "@g4rcez/components/select";
177
+ import { useForm } from "@g4rcez/components/form";
178
+
179
+ export default function UserForm() {
180
+ const form = useForm(schema, "userForm");
181
+
182
+ return (
183
+ <form {...form.props}>
184
+ <Select
185
+ {...form.select("role")}
186
+ options={[
187
+ { value: "admin", label: "Administrator" },
188
+ { value: "editor", label: "Editor" },
189
+ { value: "viewer", label: "Viewer" },
190
+ ]}
191
+ placeholder="Select role"
192
+ />
193
+ </form>
194
+ );
195
+ }
196
+ ```
197
+
198
+ ### Cascading selects
199
+
200
+ ```tsx
201
+ import { useState } from "react";
202
+ import { Select } from "@g4rcez/components/select";
203
+
204
+ const subcategories: Record<string, { value: string; label: string }[]> = {
205
+ electronics: [
206
+ { value: "phones", label: "Phones" },
207
+ { value: "laptops", label: "Laptops" },
208
+ ],
209
+ clothing: [
210
+ { value: "shirts", label: "Shirts" },
211
+ { value: "pants", label: "Pants" },
212
+ ],
213
+ };
214
+
215
+ export default function CascadingSelect() {
216
+ const [category, setCategory] = useState("");
217
+ const [subcategory, setSubcategory] = useState("");
218
+
219
+ return (
220
+ <div className="flex flex-col gap-base">
221
+ <Select
222
+ title="Category"
223
+ options={[
224
+ { value: "electronics", label: "Electronics" },
225
+ { value: "clothing", label: "Clothing" },
226
+ ]}
227
+ placeholder="Select category"
228
+ value={category}
229
+ onChange={(e) => {
230
+ setCategory(e.target.value);
231
+ setSubcategory("");
232
+ }}
233
+ />
234
+
235
+ {category && (
236
+ <Select
237
+ title="Subcategory"
238
+ options={subcategories[category] ?? []}
239
+ placeholder="Select subcategory"
240
+ value={subcategory}
241
+ onChange={(e) => setSubcategory(e.target.value)}
242
+ />
243
+ )}
244
+ </div>
245
+ );
246
+ }
247
+ ```
248
+
249
+ ## Do
250
+
251
+ - Use descriptive `label` values for each option.
252
+ - Order options logically (alphabetically or by usage frequency).
253
+ - Provide a `placeholder` so users know what to select.
254
+ - Use `loading` and `disabled` together while fetching options asynchronously.
255
+ - Use design-token classes for wrapper elements (`bg-background`, `text-foreground`, `border-border`).
256
+
257
+ ## Don't
258
+
259
+ - Don't use `Select` for only 2–3 options — prefer `Radiobox` or `Switch` for better visibility.
260
+ - Don't use `Select` for large searchable lists — use `Autocomplete` instead.
261
+ - Don't use long option labels that may truncate on small viewports.
262
+ - Don't pass raw Tailwind color classes (`bg-blue-500`, `text-white`, `border-gray-300`) — use design tokens instead.
263
+ - Don't use arbitrary Tailwind values (`bg-[#abc]`, `bg-[--my-var]`) — override CSS variables in your `@theme` block instead.
264
+
265
+ ## Accessibility
266
+
267
+ - Uses a native `<select>` element for full keyboard support and screen-reader compatibility.
268
+ - The `placeholder` renders as a `disabled hidden` option so it is never submitted.
269
+ - A `ChevronDownIcon` caret is rendered inside a `<label>` pointing to the select id, giving it a larger click target.
270
+ - `data-selected` is set to `"false"` until the user selects an option, which toggles the placeholder color class.
271
+
272
+ ## Data Attributes
273
+
274
+ | Attribute | Element | Value | Description |
275
+ |-----------|---------|-------|-------------|
276
+ | `data-component` | `InputField` root | `"select"` | Identifies the component. |
277
+ | `data-selected` | `<select>` | `"true" \| "false"` | Whether a non-placeholder option is selected. |
278
+
279
+ ## Notes
280
+
281
+ - Built on `InputField` for layout, label, error, and loading handling.
282
+ - Supports all standard HTML `<select>` attributes via prop spread.
283
+ - `required` defaults to `true` — pass `required={false}` when the field is optional.
284
+ - Custom data attributes on `OptionProps` (e.g., `data-price`) are forwarded to each `<option>` and accessible via `e.target.selectedOptions[0].dataset`.
@@ -0,0 +1,105 @@
1
+ ---
2
+ title: Shortcut
3
+ description: Inline keyboard shortcut display with automatic OS-specific key symbol mapping.
4
+ package: "@g4rcez/components"
5
+ export: "{ Shortcut }"
6
+ import: "import { Shortcut } from '@g4rcez/components'"
7
+ category: display
8
+ ---
9
+
10
+ # Shortcut
11
+
12
+ Inline keyboard shortcut display with automatic OS-specific key symbol mapping.
13
+
14
+ ## Import
15
+
16
+ ```tsx
17
+ import { Shortcut } from "@g4rcez/components";
18
+ ```
19
+
20
+ ## Props
21
+
22
+ | Prop | Type | Default | Description |
23
+ |------|------|---------|-------------|
24
+ | `value` | `string` | — | Shortcut string to display, e.g. `"Mod + K"` or `"Shift + Alt + P"` |
25
+
26
+ ## Design Tokens
27
+
28
+ The `Shortcut` component inherits text color and size from its parent. No component-scoped tokens.
29
+
30
+ ## OS Mapping
31
+
32
+ The component automatically maps keys based on the user's operating system:
33
+
34
+ | Key token | macOS | Other |
35
+ |-----------|-------|-------|
36
+ | `Mod` | `⌘` (CommandIcon, `size={12}`) | `Ctrl` |
37
+ | `Alt` | `⌥` (OptionIcon, `size={12}`) | `Alt` |
38
+
39
+ All other key tokens are rendered as-is.
40
+
41
+ ## Examples
42
+
43
+ ### Basic Usage
44
+
45
+ ```tsx
46
+ <Shortcut value="Mod + K" />
47
+ ```
48
+
49
+ ### In a Tooltip
50
+
51
+ ```tsx
52
+ <Tooltip title="Save changes">
53
+ <div className="flex gap-2 items-center">
54
+ Save <Shortcut value="Mod + S" />
55
+ </div>
56
+ </Tooltip>
57
+ ```
58
+
59
+ ### In a Command Palette Item
60
+
61
+ ```tsx
62
+ <div className="flex items-center justify-between w-full">
63
+ <span>Open command palette</span>
64
+ <Shortcut value="Mod + K" />
65
+ </div>
66
+ ```
67
+
68
+ ### Complex Multi-Key Shortcuts
69
+
70
+ ```tsx
71
+ <Shortcut value="Shift + Alt + P" />
72
+ <Shortcut value="Mod + Shift + L" />
73
+ ```
74
+
75
+ ### In a Menu Item
76
+
77
+ ```tsx
78
+ <div className="flex items-center justify-between px-4 py-2">
79
+ <span className="text-foreground">New File</span>
80
+ <Shortcut value="Mod + N" />
81
+ </div>
82
+ ```
83
+
84
+ ## Do
85
+
86
+ - Use `"Mod"` instead of `"Ctrl"` or `"Cmd"` to get automatic platform-specific rendering.
87
+ - Use `"Alt"` for the Option/Alt key — it also gets platform-specific rendering on macOS.
88
+ - Place `Shortcut` next to the label of the action it accelerates (button, menu item, tooltip).
89
+
90
+ ## Don't
91
+
92
+ - Don't hardcode platform symbols like `⌘` or `Ctrl` directly — let `Shortcut` handle the mapping.
93
+ - Don't pass arbitrary Tailwind values (`text-[--my-var]`) for text color — let the component inherit from its parent.
94
+ - Don't use `Shortcut` for descriptive text longer than a typical keyboard combination.
95
+
96
+ ## Accessibility
97
+
98
+ - Each key segment renders inside a `<kbd>` element with an `aria-label` equal to the raw key name (e.g. `aria-label="Mod"`), so screen readers announce the semantic name regardless of the visual symbol.
99
+ - Icon-based keys (`CommandIcon`, `OptionIcon`) also carry their own `aria-label` attribute.
100
+
101
+ ## Notes
102
+
103
+ - The component renders a `<span>` with `flex items-center gap-1 text-sm`.
104
+ - Keys are split on `"+"` and trimmed, so `"Mod + K"`, `"Mod+K"`, and `"Mod +K"` all produce the same output.
105
+ - The OS check uses `isMac()` from the internal `combi-keys` utility, which reads `navigator.userAgent`.
@@ -0,0 +1,166 @@
1
+ ---
2
+ title: Skeleton
3
+ description: Animated loading placeholder components for content that is being fetched.
4
+ package: "@g4rcez/components"
5
+ export: "{ Skeleton, SkeletonCell, SkeletonList }"
6
+ import: "import { Skeleton, SkeletonCell, SkeletonList } from '@g4rcez/components'"
7
+ category: display
8
+ ---
9
+
10
+ # Skeleton
11
+
12
+ Animated loading placeholder components for content that is being fetched.
13
+
14
+ ## Import
15
+
16
+ ```tsx
17
+ import { Skeleton, SkeletonCell, SkeletonList } from "@g4rcez/components";
18
+ ```
19
+
20
+ ## Components
21
+
22
+ ### SkeletonCell
23
+
24
+ A pre-built table-cell skeleton with `h-6 w-10/12 animate-pulse rounded bg-muted`. Renders as a plain `<div>` (no props).
25
+
26
+ ### Skeleton
27
+
28
+ A configurable block skeleton.
29
+
30
+ | Prop | Type | Default | Description |
31
+ |------|------|---------|-------------|
32
+ | `className` | `string` | — | Override or extend dimensions and shape |
33
+ | `as` | `React.ElementType` | `"span"` | Polymorphic root element |
34
+ | `style` | `CSSProperties` | — | Inline styles (e.g. dynamic `width`) |
35
+
36
+ Default appearance: `block h-8 w-32 animate-pulse rounded bg-muted`.
37
+
38
+ ### SkeletonList
39
+
40
+ A vertical list of randomized-width `Skeleton` lines.
41
+
42
+ | Prop | Type | Default | Description |
43
+ |------|------|---------|-------------|
44
+ | `rows` | `number` | — | Number of skeleton lines to render |
45
+ | `className` | `string` | — | Additional classes for the `<ul>` container |
46
+
47
+ ## Design Tokens
48
+
49
+ Tokens this component reads. Customize by overriding these CSS variables in your theme.
50
+
51
+ | Token | CSS Variable | Purpose |
52
+ |-------|-------------|---------|
53
+ | `bg-muted` | `--muted` | Pulse animation background for all skeleton variants |
54
+
55
+ ## Examples
56
+
57
+ ### Table Loading Skeleton
58
+
59
+ ```tsx
60
+ function TableSkeleton() {
61
+ return (
62
+ <table className="w-full">
63
+ <tbody>
64
+ {Array.from({ length: 5 }).map((_, index) => (
65
+ <tr key={index} className="border-b border-border">
66
+ <td className="py-3 px-4"><SkeletonCell /></td>
67
+ <td className="py-3 px-4"><SkeletonCell /></td>
68
+ <td className="py-3 px-4"><SkeletonCell /></td>
69
+ </tr>
70
+ ))}
71
+ </tbody>
72
+ </table>
73
+ );
74
+ }
75
+ ```
76
+
77
+ ### Card Loading Skeleton
78
+
79
+ ```tsx
80
+ function CardSkeleton() {
81
+ return (
82
+ <div className="rounded-card border border-card-border bg-card-background p-6 space-y-4">
83
+ <Skeleton className="h-4 w-3/4" />
84
+ <div className="space-y-2">
85
+ <SkeletonCell />
86
+ <SkeletonCell />
87
+ <Skeleton className="h-2 w-1/2" />
88
+ </div>
89
+ <div className="flex gap-2">
90
+ <Skeleton className="h-8 w-20" />
91
+ <Skeleton className="h-8 w-16" />
92
+ </div>
93
+ </div>
94
+ );
95
+ }
96
+ ```
97
+
98
+ ### List Loading Skeleton
99
+
100
+ ```tsx
101
+ <SkeletonList rows={5} className="px-4" />
102
+ ```
103
+
104
+ ### Conditional Skeleton
105
+
106
+ ```tsx
107
+ function DataSection({ data, loading }: { data?: Item; loading: boolean }) {
108
+ return (
109
+ <div>
110
+ {loading ? (
111
+ <Skeleton className="h-6 w-full" />
112
+ ) : (
113
+ <p>{data?.name}</p>
114
+ )}
115
+ </div>
116
+ );
117
+ }
118
+ ```
119
+
120
+ ### Avatar + Text Row Skeleton
121
+
122
+ ```tsx
123
+ function UserRowSkeleton() {
124
+ return (
125
+ <div className="flex items-center gap-3">
126
+ <Skeleton className="size-10 rounded-full" />
127
+ <div className="flex-1 space-y-1">
128
+ <SkeletonCell />
129
+ <Skeleton className="h-2 w-1/3" />
130
+ </div>
131
+ </div>
132
+ );
133
+ }
134
+ ```
135
+
136
+ ## Do
137
+
138
+ - Design skeletons that closely match the dimensions of the real content to minimize layout shift.
139
+ - Use `animate-pulse` (applied by default) to signal that the system is active.
140
+ - Use `SkeletonList` for simple vertically stacked text content.
141
+ - Wrap skeleton containers with `aria-live="polite"` so screen readers announce when real content loads.
142
+
143
+ ## Don't
144
+
145
+ - Don't pass raw Tailwind color classes (`bg-gray-200`, `bg-slate-300`) as `className` — use `bg-muted` or other design-token classes instead.
146
+ - Don't use arbitrary Tailwind values (`bg-[#ddd]`) — override CSS variables in your `@theme` block.
147
+ - Don't show skeletons for very short loading states (under ~300 ms) — it causes visual flicker.
148
+ - Don't make skeletons too detailed; simple geometric shapes are most effective.
149
+ - Don't use skeletons for error states — show `Empty` or `Alert` instead.
150
+
151
+ ## Accessibility
152
+
153
+ - Skeleton components are purely decorative; they carry no ARIA roles.
154
+ - Add `aria-live="polite"` to the container that transitions from skeleton to real content so assistive technologies announce the change.
155
+ - Consider `aria-label="Loading content"` on the skeleton container for additional context.
156
+
157
+ ```tsx
158
+ <div aria-live="polite">
159
+ {loading ? <SkeletonCell /> : <ActualContent />}
160
+ </div>
161
+ ```
162
+
163
+ ## Notes
164
+
165
+ - `SkeletonList` generates random widths at mount time (via `Math.random()`) so each row looks distinct. Widths are stable across re-renders thanks to `useRef`.
166
+ - `Skeleton` uses `as="span"` by default, making it safe to use inside inline contexts. Change `as` to `"div"` or `"li"` as needed.
@@ -0,0 +1,144 @@
1
+ ---
2
+ title: Slider
3
+ description: Accessible range input for selecting one or more numeric values along a scale.
4
+ package: "@g4rcez/components"
5
+ export: "{ Slider }"
6
+ import: "import { Slider } from '@g4rcez/components'"
7
+ category: form
8
+ ---
9
+
10
+ # Slider
11
+
12
+ Accessible range input for selecting one or more numeric values along a scale.
13
+
14
+ ## Import
15
+
16
+ ```tsx
17
+ import { Slider } from "@g4rcez/components";
18
+ ```
19
+
20
+ ## Props
21
+
22
+ `Slider` accepts all props from `@base-ui/react/slider` Root, plus:
23
+
24
+ | Prop | Type | Default | Description |
25
+ |------|------|---------|-------------|
26
+ | `tooltip` | `boolean` | `false` | Shows a tooltip with the current value above the thumb while dragging. |
27
+ | `value` | `number[]` | — | Controlled value(s). |
28
+ | `defaultValue` | `number[]` | `[0]` | Initial value(s) for uncontrolled usage. |
29
+ | `min` | `number` | `0` | Minimum value. |
30
+ | `max` | `number` | `100` | Maximum value. |
31
+ | `step` | `number` | `1` | Increment between selectable values. |
32
+ | `className` | `string` | — | Additional classes applied to the control track wrapper. |
33
+
34
+ ## Design Tokens
35
+
36
+ Tokens this component reads. Customize by overriding these CSS variables in your theme.
37
+
38
+ | Token | CSS Variable | Purpose |
39
+ |-------|-------------|---------|
40
+ | `bg-background` | `--background` | Track background (unfilled area) |
41
+ | `bg-primary` | `--primary` | Indicator fill (filled area) |
42
+ | `border-input-border` | `--input-border` | Thumb border color |
43
+ | `bg-input-switch` | `--input-switch` | Thumb fill color (checked/active) |
44
+ | `focus-within:ring-primary` | `--primary` | Focus ring on thumb |
45
+
46
+ ## Variants
47
+
48
+ ### Single thumb
49
+
50
+ One value in `defaultValue` renders a single draggable thumb.
51
+
52
+ ### Range (dual thumb)
53
+
54
+ Two values in `defaultValue` render two thumbs that define a range.
55
+
56
+ ## Examples
57
+
58
+ ### Single value
59
+
60
+ ```tsx
61
+ import { Slider } from "@g4rcez/components";
62
+
63
+ export default function VolumeControl() {
64
+ return (
65
+ <Slider
66
+ min={0}
67
+ max={100}
68
+ defaultValue={[50]}
69
+ onChange={(value) => console.log(value)}
70
+ />
71
+ );
72
+ }
73
+ ```
74
+
75
+ ### Range slider
76
+
77
+ ```tsx
78
+ import { Slider } from "@g4rcez/components";
79
+
80
+ export default function PriceRangeFilter() {
81
+ return (
82
+ <Slider
83
+ min={0}
84
+ max={1000}
85
+ defaultValue={[200, 800]}
86
+ tooltip
87
+ />
88
+ );
89
+ }
90
+ ```
91
+
92
+ ### Controlled with tooltip and custom step
93
+
94
+ ```tsx
95
+ import { useState } from "react";
96
+ import { Slider } from "@g4rcez/components";
97
+
98
+ export default function SteppedSlider() {
99
+ const [value, setValue] = useState([0.5]);
100
+
101
+ return (
102
+ <div className="flex flex-col gap-base">
103
+ <Slider
104
+ min={0}
105
+ max={1}
106
+ step={0.1}
107
+ value={value}
108
+ tooltip
109
+ onValueChange={setValue}
110
+ />
111
+ <span className="text-sm text-muted-foreground">
112
+ Current: {value[0].toFixed(1)}
113
+ </span>
114
+ </div>
115
+ );
116
+ }
117
+ ```
118
+
119
+ ## Do
120
+
121
+ - Provide visible labels or descriptive context indicating what the slider controls.
122
+ - Use `tooltip` for precise numeric adjustments where the exact value matters.
123
+ - Use `step` to restrict selection to valid increments (e.g., `step={10}` for percentages in tens).
124
+ - Use design-token classes for any wrapper elements (`bg-background`, `text-foreground`).
125
+
126
+ ## Don't
127
+
128
+ - Don't use `Slider` for very large or effectively infinite ranges where a text `Input` would be more efficient.
129
+ - Don't use `Slider` for selecting from a small discrete set (e.g., 3 named options) — use `Radiobox` or `Select`.
130
+ - Don't pass raw Tailwind color classes (`bg-blue-500`, `border-gray-300`) — use design tokens instead.
131
+ - Don't use arbitrary Tailwind values (`bg-[#abc]`) — override CSS variables in your `@theme` block instead.
132
+
133
+ ## Accessibility
134
+
135
+ - Fully accessible via keyboard: Arrow keys increment/decrement the focused thumb.
136
+ - Each thumb exposes `aria-valuenow`, `aria-valuemin`, and `aria-valuemax`.
137
+ - Touch targets for thumbs are sized generously (`size-5`) for mobile usability.
138
+ - Compatible with screen readers through the underlying `@base-ui/react/slider`.
139
+
140
+ ## Notes
141
+
142
+ - Built on `@base-ui/react/slider` — most structural ARIA and keyboard behavior comes from that primitive.
143
+ - The `Thumb` sub-component observes `aria-valuenow` mutations via a `MutationObserver` to keep the tooltip value in sync without additional state.
144
+ - Locale-aware: the `useLocale` hook is used internally for number formatting in tooltips.