@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,171 @@
1
+ ---
2
+ title: DatePicker
3
+ description: Date input with locale-aware masked entry and a floating calendar dropdown for visual selection.
4
+ package: "@g4rcez/components"
5
+ export: "{ DatePicker }"
6
+ import: "import { DatePicker } from '@g4rcez/components/date-picker'"
7
+ category: form
8
+ ---
9
+
10
+ # DatePicker
11
+
12
+ Date input with locale-aware masked entry and a floating calendar dropdown for visual selection.
13
+
14
+ ## Import
15
+
16
+ ```tsx
17
+ import { DatePicker } from "@g4rcez/components/date-picker";
18
+ ```
19
+
20
+ ## Props
21
+
22
+ `DatePicker` inherits all `Input` and `Calendar` props. Notable additions:
23
+
24
+ | Prop | Type | Default | Description |
25
+ |------|------|---------|-------------|
26
+ | `date` | `Date` | - | Controlled selected date |
27
+ | `type` | `"date" \| "datetime"` | `"date"` | Whether to include time (hour + minute) selection |
28
+ | `floating` | `boolean` | `true` | Show the calendar in a floating `Dropdown`; set to `false` to embed it inline |
29
+ | `clickToClose` | `boolean` | `false` | Close the calendar immediately after a date is picked |
30
+ | `locale` | `Locales` | system locale | Locale for mask generation and calendar display |
31
+ | `markToday` | `boolean` | `true` | Highlight today in the calendar |
32
+ | `disabledDate` | `(date: Date) => boolean` | - | Callback that returns `true` for dates that should be unselectable |
33
+ | `onChange` | `(date: Date \| undefined) => void` | - | Called with the new `Date` when input is valid, or `undefined` when cleared |
34
+ | `title` | `string` | - | Field label |
35
+ | `error` | `string` | - | Error message shown below the field |
36
+ | `required` | `boolean` | `true` | Marks field as required (default is `true` for DatePicker) |
37
+ | `name` | `string` | - | Form field name — also the `id` of the hidden `<input type="date">` |
38
+
39
+ ## Design Tokens
40
+
41
+ Tokens this component reads. Customize by overriding these CSS variables in your theme.
42
+
43
+ | Token | CSS Variable | Purpose |
44
+ |-------|-------------|---------|
45
+ | `h-input-height` | `--input-height` | Input height |
46
+ | `px-input-x` | `--input-x` | Horizontal input padding |
47
+ | `py-input-y` | `--input-y` | Vertical input padding |
48
+ | `border-input-border` | `--input-border` | Default border color |
49
+ | `text-foreground` | `--foreground` | Input text color |
50
+ | `text-primary` | `--primary` | Focus ring and border on focus/hover |
51
+ | `text-danger` | `--danger` | Error state text and border |
52
+ | `placeholder-input-mask` | `--input-mask` | Placeholder text color |
53
+ | `bg-floating-background` | `--floating-background` | Calendar dropdown background |
54
+ | `border-floating-border` | `--floating-border` | Calendar dropdown border |
55
+
56
+ ## Examples
57
+
58
+ ### Basic date picker
59
+
60
+ ```tsx
61
+ import { DatePicker } from "@g4rcez/components/date-picker";
62
+
63
+ <DatePicker
64
+ name="birthdate"
65
+ title="Date of birth"
66
+ />
67
+ ```
68
+
69
+ ### Date and time
70
+
71
+ ```tsx
72
+ <DatePicker
73
+ name="appointment"
74
+ title="Appointment time"
75
+ type="datetime"
76
+ clickToClose
77
+ />
78
+ ```
79
+
80
+ ### Disabling past dates
81
+
82
+ ```tsx
83
+ import { isBefore, startOfDay } from "date-fns";
84
+
85
+ <DatePicker
86
+ name="event_date"
87
+ title="Event date"
88
+ disabledDate={(date) => isBefore(date, startOfDay(new Date()))}
89
+ />
90
+ ```
91
+
92
+ ### Controlled value
93
+
94
+ ```tsx
95
+ const [date, setDate] = useState<Date | undefined>();
96
+
97
+ <DatePicker
98
+ name="due_date"
99
+ title="Due date"
100
+ date={date}
101
+ onChange={setDate}
102
+ />
103
+ ```
104
+
105
+ ### Inline calendar (no dropdown)
106
+
107
+ ```tsx
108
+ <DatePicker
109
+ name="check_in"
110
+ title="Check-in"
111
+ floating={false}
112
+ />
113
+ ```
114
+
115
+ ### Inside a form
116
+
117
+ ```tsx
118
+ import { Form } from "@g4rcez/components/form";
119
+ import { Button } from "@g4rcez/components/button";
120
+
121
+ function BookingForm() {
122
+ const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
123
+ const data = new FormData(e.currentTarget);
124
+ console.log(data.get("check_in"), data.get("check_out"));
125
+ };
126
+
127
+ return (
128
+ <Form onSubmit={handleSubmit} className="flex flex-col gap-base">
129
+ <DatePicker name="check_in" title="Check-in" />
130
+ <DatePicker name="check_out" title="Check-out" />
131
+ <Button theme="primary" type="submit">Book</Button>
132
+ </Form>
133
+ );
134
+ }
135
+ ```
136
+
137
+ ## Do
138
+
139
+ - Use `disabledDate` to prevent invalid date selection (e.g., past dates for future bookings).
140
+ - Use `type="datetime"` when both date and time are required for the use case.
141
+ - Provide a clear `title` label.
142
+ - Rely on `locale` for locale-aware mask and calendar generation rather than hardcoding a format.
143
+
144
+ ## Don't
145
+
146
+ - Don't pass raw Tailwind color classes (`bg-blue-500`, `text-white`, `border-gray-300`) — use theme props or design tokens instead.
147
+ - Don't use arbitrary Tailwind values (`bg-[#abc]`, `bg-[--my-var]`) — override CSS variables in your `@theme` block instead.
148
+ - Don't use `DatePicker` when only a year or only a month is needed — a `Select` is more appropriate.
149
+ - Don't assume users will always use the calendar; the masked text input must also be keyboard-friendly.
150
+
151
+ ## Accessibility
152
+
153
+ - The calendar icon button includes an `aria-describedby` referencing a visually-hidden `<span>` with a translatable label.
154
+ - The underlying `Input` component handles `aria-disabled`, `aria-readonly`, and `aria-busy`.
155
+ - The calendar (`Calendar` component) is fully keyboard-navigable.
156
+ - The input is masked to prevent invalid character entry, reducing validation friction.
157
+ - Follows the standard `fieldset > label` structure from `InputField`.
158
+
159
+ ## Data Attributes
160
+
161
+ - `data-component="date-picker"` — on the visible `Input`.
162
+ - `data-value` — ISO string representation of the selected date (set on the visible input).
163
+ - `data-target` — mirrors the `name` prop; used to link the shadow input to the hidden field.
164
+ - `data-origin` — on the hidden `<input type="date">`: its `name` value, used by `formReset`.
165
+
166
+ ## Notes
167
+
168
+ - The component renders two inputs: a visible masked `Input` for user interaction and a hidden `<input type="date">` (with `name`) for native form submission.
169
+ - The input mask is generated dynamically from `Intl.DateTimeFormat.formatToParts`, so it automatically reflects the locale's date order (e.g., MM/DD/YYYY vs DD/MM/YYYY).
170
+ - Date parsing uses `date-fns`. The `placeholder` is derived from the same locale format string.
171
+ - When `floating={true}` (default), the calendar is rendered in a `Dropdown` using `@floating-ui/react` positioned to the right of the input.
@@ -0,0 +1,223 @@
1
+ ---
2
+ title: Dropdown
3
+ description: Floating dropdown panel with an optional title, arrow pointer, and automatic collision-aware positioning.
4
+ package: "@g4rcez/components"
5
+ export: "{ Dropdown }"
6
+ import: "import { Dropdown } from '@g4rcez/components/dropdown'"
7
+ category: floating
8
+ ---
9
+
10
+ # Dropdown
11
+
12
+ Floating dropdown panel with an optional title, arrow pointer, and automatic collision-aware positioning.
13
+
14
+ ## Import
15
+
16
+ ```tsx
17
+ import { Dropdown } from "@g4rcez/components/dropdown";
18
+ ```
19
+
20
+ ## Props
21
+
22
+ | Prop | Type | Default | Description |
23
+ |------|------|---------|-------------|
24
+ | `trigger` | `React.ReactElement \| React.ReactNode` | — | Element that toggles the dropdown on click |
25
+ | `open` | `boolean` | — | Controlled open state |
26
+ | `arrow` | `boolean` | `false` | Show an arrow pointer pointing at the trigger |
27
+ | `title` | `React.ReactNode \| string` | — | Header title rendered inside the panel |
28
+ | `restoreFocus` | `boolean` | `true` | Restore focus to the trigger when the panel closes |
29
+ | `returnFocus` | `boolean` | `true` | Return focus to the trigger element |
30
+ | `onChange` | `(nextValue: boolean) => void` | — | Callback fired when the open state changes |
31
+ | `buttonProps` | `React.HTMLProps<"button">` | — | Additional props forwarded to the trigger `<button>` |
32
+ | `children` | `React.ReactNode` | — | Panel content |
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-floating-background` | `--floating-background` | Panel surface background |
41
+ | `border-floating-border` | `--floating-border` | Panel border and arrow stroke |
42
+ | `fill-floating-background` | `--floating-background` | Arrow fill color |
43
+ | `z-floating` | `--z-floating` | Z-index for the floating panel |
44
+ | `shadow-shadow-floating` | `--shadow-floating` | Panel drop shadow |
45
+ | `rounded-lg` | — | Panel corner radius |
46
+
47
+ ## Examples
48
+
49
+ ### Simple Action Menu
50
+
51
+ ```tsx
52
+ import { Dropdown } from "@g4rcez/components/dropdown";
53
+ import { Button } from "@g4rcez/components/button";
54
+
55
+ function SimpleDropdown() {
56
+ return (
57
+ <Dropdown
58
+ trigger={<Button theme="primary">Actions</Button>}
59
+ >
60
+ <div className="flex min-w-48 flex-col py-1">
61
+ <button className="w-full px-4 py-2 text-left text-foreground hover:bg-floating-hover">
62
+ Edit
63
+ </button>
64
+ <button className="w-full px-4 py-2 text-left text-foreground hover:bg-floating-hover">
65
+ Duplicate
66
+ </button>
67
+ <hr className="border-border my-1" />
68
+ <button className="w-full px-4 py-2 text-left text-danger hover:bg-floating-hover">
69
+ Delete
70
+ </button>
71
+ </div>
72
+ </Dropdown>
73
+ );
74
+ }
75
+ ```
76
+
77
+ ### Dropdown with Title and Arrow
78
+
79
+ ```tsx
80
+ import { UserIcon, ChevronDownIcon } from "lucide-react";
81
+ import { Dropdown } from "@g4rcez/components/dropdown";
82
+
83
+ function AccountDropdown() {
84
+ return (
85
+ <Dropdown
86
+ trigger={
87
+ <button className="flex items-center gap-2 px-3 py-2 rounded-button border border-border text-foreground">
88
+ <UserIcon size={16} />
89
+ Account
90
+ <ChevronDownIcon size={16} />
91
+ </button>
92
+ }
93
+ title="Account Options"
94
+ arrow
95
+ >
96
+ <div className="flex min-w-48 flex-col py-1">
97
+ <button className="w-full px-4 py-2 text-left text-foreground hover:bg-floating-hover">
98
+ Profile Settings
99
+ </button>
100
+ <button className="w-full px-4 py-2 text-left text-foreground hover:bg-floating-hover">
101
+ Billing
102
+ </button>
103
+ <button className="w-full px-4 py-2 text-left text-foreground hover:bg-floating-hover">
104
+ Sign Out
105
+ </button>
106
+ </div>
107
+ </Dropdown>
108
+ );
109
+ }
110
+ ```
111
+
112
+ ### Controlled Dropdown
113
+
114
+ ```tsx
115
+ import { useState } from "react";
116
+ import { Dropdown } from "@g4rcez/components/dropdown";
117
+
118
+ function ControlledDropdown() {
119
+ const [isOpen, setIsOpen] = useState(false);
120
+
121
+ return (
122
+ <Dropdown
123
+ trigger={
124
+ <button className="px-4 py-2 rounded-button bg-muted text-foreground">
125
+ {isOpen ? "Close" : "Open"} Menu
126
+ </button>
127
+ }
128
+ open={isOpen}
129
+ onChange={setIsOpen}
130
+ >
131
+ <div className="min-w-48 p-4">
132
+ <p className="text-foreground">Controlled dropdown content</p>
133
+ <button
134
+ onClick={() => setIsOpen(false)}
135
+ className="mt-2 px-3 py-1 bg-primary text-primary-foreground rounded-button text-sm"
136
+ >
137
+ Close
138
+ </button>
139
+ </div>
140
+ </Dropdown>
141
+ );
142
+ }
143
+ ```
144
+
145
+ ### Filter Dropdown with Form Content
146
+
147
+ ```tsx
148
+ import { FilterIcon } from "lucide-react";
149
+ import { Dropdown } from "@g4rcez/components/dropdown";
150
+
151
+ function FilterDropdown() {
152
+ const [status, setStatus] = useState("");
153
+
154
+ return (
155
+ <Dropdown
156
+ trigger={
157
+ <button className="flex items-center gap-2 px-3 py-2 rounded-button border border-border text-foreground">
158
+ <FilterIcon size={16} />
159
+ Filters
160
+ {status && <span className="h-2 w-2 rounded-full bg-primary" />}
161
+ </button>
162
+ }
163
+ title="Filter Options"
164
+ >
165
+ <div className="min-w-64 space-y-4 p-4">
166
+ <div>
167
+ <label className="block text-sm font-medium text-foreground mb-1">
168
+ Status
169
+ </label>
170
+ <select
171
+ value={status}
172
+ onChange={(e) => setStatus(e.target.value)}
173
+ className="w-full px-3 py-2 rounded-button border border-border bg-background text-foreground"
174
+ >
175
+ <option value="">All</option>
176
+ <option value="active">Active</option>
177
+ <option value="inactive">Inactive</option>
178
+ </select>
179
+ </div>
180
+ <div className="flex gap-2 pt-2">
181
+ <button
182
+ onClick={() => setStatus("")}
183
+ className="px-3 py-1 text-sm rounded-button border border-border text-foreground"
184
+ >
185
+ Clear
186
+ </button>
187
+ <button className="px-3 py-1 text-sm rounded-button bg-primary text-primary-foreground">
188
+ Apply
189
+ </button>
190
+ </div>
191
+ </div>
192
+ </Dropdown>
193
+ );
194
+ }
195
+ ```
196
+
197
+ ## Do
198
+
199
+ - Use design-token classes for dropdown item hover states (`hover:bg-floating-hover`, `text-foreground`) instead of raw color utilities.
200
+ - Provide a `title` to help users understand the panel's context.
201
+ - Use the `arrow` prop when the trigger is small and spatial context helps the user.
202
+ - Group related items with separators for panels with more than 5 items.
203
+
204
+ ## Don't
205
+
206
+ - Don't pass raw Tailwind color classes (`bg-blue-500`, `text-white`, `hover:bg-gray-100`) — use design-token classes.
207
+ - Don't use arbitrary values (`bg-[#abc]`, `z-[9999]`) — override CSS variables in your `@theme` block.
208
+ - Don't put more than 10–15 items in a single dropdown; consider `CommandPalette` or `Modal` instead.
209
+ - Don't place critical destructive actions in a dropdown without a confirmation step.
210
+
211
+ ## Accessibility
212
+
213
+ - The trigger is wrapped in a `<button>` element; pass `aria-label` via `buttonProps` when the trigger has no visible text.
214
+ - The panel receives `aria-labelledby` pointing at the heading generated from `title`.
215
+ - `FloatingFocusManager` traps focus within the panel and restores it to the trigger on close.
216
+ - Clicking outside or pressing `Escape` closes the panel (handled by `useDismiss`).
217
+ - Tab navigation works naturally within the panel content.
218
+
219
+ ## Notes
220
+
221
+ - Built on `@floating-ui/react` with `flip`, `shift`, and `offset(10)` middleware. The panel flips to the opposite side if there is insufficient space.
222
+ - When a child element has `data-floating="true"`, focus leaving to that element will not close the dropdown — useful for nested portals.
223
+ - The `open` prop is synced to local state via `useEffect`; controlled and uncontrolled usage are both supported.
@@ -0,0 +1,163 @@
1
+ ---
2
+ title: Empty
3
+ description: Empty state placeholder displayed when a collection or data set contains no items.
4
+ package: "@g4rcez/components"
5
+ export: "{ Empty }"
6
+ import: "import { Empty } from '@g4rcez/components'"
7
+ category: display
8
+ ---
9
+
10
+ # Empty
11
+
12
+ Empty state placeholder displayed when a collection or data set contains no items.
13
+
14
+ ## Import
15
+
16
+ ```tsx
17
+ import { Empty } from "@g4rcez/components";
18
+ ```
19
+
20
+ ## Props
21
+
22
+ | Prop | Type | Default | Description |
23
+ |------|------|---------|-------------|
24
+ | `Icon` | `React.FC<LucideProps>` | `FileIcon` | Lucide icon component to display |
25
+ | `message` | `string` | Localized "No data available" | Descriptive empty state message |
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
+ | `text-disabled` | `--disabled` | Icon and message text color |
34
+
35
+ ## Examples
36
+
37
+ ### Default Empty State
38
+
39
+ ```tsx
40
+ <Empty />
41
+ ```
42
+
43
+ ### Custom Message and Icon
44
+
45
+ ```tsx
46
+ import { SearchXIcon } from "lucide-react";
47
+
48
+ <Empty Icon={SearchXIcon} message="No results found" />
49
+ ```
50
+
51
+ ### In a Data Table
52
+
53
+ ```tsx
54
+ import { DatabaseIcon } from "lucide-react";
55
+
56
+ function DataTable({ data }: { data: Item[] }) {
57
+ if (data.length === 0) {
58
+ return (
59
+ <div className="py-12">
60
+ <Empty Icon={DatabaseIcon} message="No records found" />
61
+ </div>
62
+ );
63
+ }
64
+
65
+ return <table>{/* table content */}</table>;
66
+ }
67
+ ```
68
+
69
+ ### In a List
70
+
71
+ ```tsx
72
+ import { InboxIcon } from "lucide-react";
73
+
74
+ function TaskList({ tasks }: { tasks: Task[] }) {
75
+ return (
76
+ <div className="space-y-4">
77
+ <h2>My Tasks</h2>
78
+
79
+ {tasks.length === 0 ? (
80
+ <Empty Icon={InboxIcon} message="No tasks yet" />
81
+ ) : (
82
+ <ul>
83
+ {tasks.map((task) => (
84
+ <TaskItem key={task.id} task={task} />
85
+ ))}
86
+ </ul>
87
+ )}
88
+ </div>
89
+ );
90
+ }
91
+ ```
92
+
93
+ ### With an Action
94
+
95
+ ```tsx
96
+ import { Button } from "@g4rcez/components/button";
97
+ import { FolderPlusIcon } from "lucide-react";
98
+
99
+ function EmptyProjectsList() {
100
+ return (
101
+ <div className="text-center py-12">
102
+ <Empty
103
+ Icon={FolderPlusIcon}
104
+ message="You haven't created any projects yet"
105
+ />
106
+ <div className="mt-6">
107
+ <Button theme="primary" onClick={handleCreate}>
108
+ Create Your First Project
109
+ </Button>
110
+ </div>
111
+ </div>
112
+ );
113
+ }
114
+ ```
115
+
116
+ ### Contextual Icons
117
+
118
+ ```tsx
119
+ import {
120
+ ShoppingCartIcon,
121
+ HeartIcon,
122
+ BellIcon,
123
+ MailIcon,
124
+ } from "lucide-react";
125
+
126
+ // Cart
127
+ <Empty Icon={ShoppingCartIcon} message="Your cart is empty" />
128
+
129
+ // Favorites
130
+ <Empty Icon={HeartIcon} message="No favorites yet" />
131
+
132
+ // Notifications
133
+ <Empty Icon={BellIcon} message="No notifications" />
134
+
135
+ // Messages
136
+ <Empty Icon={MailIcon} message="No messages" />
137
+ ```
138
+
139
+ ## Do
140
+
141
+ - Provide a clear, encouraging message that tells users what is missing.
142
+ - Use an icon that is contextually relevant to the missing content type.
143
+ - Pair `Empty` with an action button when the user can resolve the empty state.
144
+ - Wrap `Empty` in a padded container for visual breathing room.
145
+
146
+ ## Don't
147
+
148
+ - Don't pass raw Tailwind color classes (`text-gray-400`) for the icon — the component uses `text-disabled` from the design system.
149
+ - Don't use arbitrary Tailwind values (`text-[#abc]`) — override CSS variables in your `@theme` block instead.
150
+ - Don't use `Empty` for transient loading states — use `Skeleton` or `Spinner` instead.
151
+ - Don't leave a blank space when data is missing; always provide visual feedback.
152
+ - Don't use overly technical language in the empty state message.
153
+
154
+ ## Accessibility
155
+
156
+ - The icon renders at `size={64}` using a Lucide component which includes accessible SVG markup.
157
+ - The message uses a `<p>` element for semantic text.
158
+ - Both icon and text use `text-disabled` ensuring sufficient contrast against the background.
159
+
160
+ ## Notes
161
+
162
+ - The default message is sourced from the active locale translations via `useTranslations()`, so it localizes automatically when the app locale changes.
163
+ - To override the default message permanently, pass an explicit `message` prop.
@@ -0,0 +1,143 @@
1
+ ---
2
+ title: Expand
3
+ description: A button that expands in-place into a floating container using shared-element layout animations.
4
+ package: "@g4rcez/components"
5
+ export: "{ Expand }"
6
+ import: "import { Expand } from '@g4rcez/components/expand'"
7
+ category: floating
8
+ ---
9
+
10
+ # Expand
11
+
12
+ A button that expands in-place into a floating container using shared-element layout animations.
13
+
14
+ ## Import
15
+
16
+ ```tsx
17
+ import { Expand } from "@g4rcez/components/expand";
18
+ ```
19
+
20
+ ## Props
21
+
22
+ `Expand` accepts all `Button` props plus the following:
23
+
24
+ | Prop | Type | Default | Description |
25
+ |------|------|---------|-------------|
26
+ | `trigger` | `Label` | — | Content displayed on the button before expansion |
27
+ | `open` | `boolean` | `false` | Controlled open state |
28
+ | `disabled` | `boolean` | `false` | When `true`, the button cannot be expanded |
29
+ | `children` | `React.ReactNode` | — | Content shown inside the expanded floating container |
30
+
31
+ Inherits all `Button` props: `theme`, `size`, `rounded`, `className`, etc.
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-background` | `--background` | Default expanded panel background (applied by consumer) |
40
+ | `border-border` | `--border` | Default expanded panel border (applied by consumer) |
41
+
42
+ The `Expand` component itself only renders the trigger button and an animated wrapper; visual tokens for the expanded content are your responsibility via `children` className.
43
+
44
+ ## Examples
45
+
46
+ ### Action FAB
47
+
48
+ ```tsx
49
+ import { PlusIcon } from "lucide-react";
50
+ import { Expand } from "@g4rcez/components/expand";
51
+
52
+ <Expand
53
+ trigger={<PlusIcon size={16} />}
54
+ theme="primary"
55
+ size="icon"
56
+ rounded="circle"
57
+ >
58
+ <div className="w-64 rounded-card border border-border bg-background p-4 shadow-shadow-floating">
59
+ <h3 className="font-bold mb-2 text-foreground">Create New</h3>
60
+ <ul className="space-y-2">
61
+ <li>
62
+ <button className="w-full rounded-button p-2 text-left text-foreground hover:bg-muted">
63
+ Project
64
+ </button>
65
+ </li>
66
+ <li>
67
+ <button className="w-full rounded-button p-2 text-left text-foreground hover:bg-muted">
68
+ Task
69
+ </button>
70
+ </li>
71
+ </ul>
72
+ </div>
73
+ </Expand>
74
+ ```
75
+
76
+ ### Expand with Label
77
+
78
+ ```tsx
79
+ import { Expand } from "@g4rcez/components/expand";
80
+ import { Button } from "@g4rcez/components/button";
81
+
82
+ <Expand trigger="Open Menu">
83
+ <div className="rounded-card border border-border bg-background p-4 shadow-shadow-floating">
84
+ <p className="text-foreground">Expanded content goes here.</p>
85
+ <Button theme="primary" className="mt-2">Action</Button>
86
+ </div>
87
+ </Expand>
88
+ ```
89
+
90
+ ### Controlled Expand
91
+
92
+ ```tsx
93
+ import { useState } from "react";
94
+ import { Expand } from "@g4rcez/components/expand";
95
+
96
+ function ControlledExpand() {
97
+ const [open, setOpen] = useState(false);
98
+
99
+ return (
100
+ <Expand
101
+ trigger="Options"
102
+ open={open}
103
+ theme="ghost-neutral"
104
+ >
105
+ <div className="rounded-card border border-border bg-background p-4 shadow-shadow-floating">
106
+ <button
107
+ onClick={() => setOpen(false)}
108
+ className="text-sm text-foreground"
109
+ >
110
+ Close
111
+ </button>
112
+ </div>
113
+ </Expand>
114
+ );
115
+ }
116
+ ```
117
+
118
+ ## Do
119
+
120
+ - Use `Expand` when you want the expanded panel to appear to "grow out of" the trigger button — the shared-element transition reinforces spatial context.
121
+ - Apply design-token classes on the expanded content (`bg-background`, `border-border`, `shadow-shadow-floating`) for consistent theming.
122
+ - Provide accessible `trigger` text or an icon with a `sr-only` label.
123
+
124
+ ## Don't
125
+
126
+ - Don't use `Expand` when a standard `Dropdown` or `Modal` would feel more familiar to the user — the animation is distinctive and should be reserved for intentional moments.
127
+ - Don't nest multiple `Expand` components inside each other; layout animations can conflict.
128
+ - Don't pass raw Tailwind color classes (`bg-gray-50`, `border-gray-200`) inside the expanded content — use design-token classes.
129
+ - Don't use arbitrary Tailwind values (`bg-[#abc]`, `shadow-[--my-shadow]`) — override CSS variables in your `@theme` block.
130
+
131
+ ## Accessibility
132
+
133
+ - The trigger renders as a focusable `<button>` via the `Button` component.
134
+ - `FloatingFocusManager` with `visuallyHiddenDismiss` and `closeOnFocusOut` manages focus correctly when the panel opens.
135
+ - Pressing `Escape` closes the expanded panel (`useDismiss` with `escapeKey: true`).
136
+ - Clicking outside also closes the panel (`outsidePress: true`).
137
+
138
+ ## Notes
139
+
140
+ - Uses `motion/react` (`layoutId`) to animate a seamless transition between the collapsed button and the expanded container.
141
+ - The expanded container is absolutely positioned at `-left-1/4 -top-3/4` by default. Override via `className` on the children wrapper if needed.
142
+ - The `disabled` prop is forwarded to `useClick` — when `true`, the click interaction is enabled (the prop name is semantically inverted in the hook call, so pass `disabled={true}` to prevent expansion).
143
+ - Rendered inside a `FloatingPortal` scoped to the component's own root `<div>` so it stays visually attached.