maquina-components 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/README.md +77 -0
- data/app/assets/stylesheets/calendar.css +222 -0
- data/app/assets/stylesheets/combobox.css +218 -0
- data/app/assets/stylesheets/date_picker.css +172 -0
- data/app/assets/stylesheets/toast.css +433 -0
- data/app/assets/tailwind/maquina_components_engine/engine.css +16 -14
- data/app/helpers/maquina_components/calendar_helper.rb +196 -0
- data/app/helpers/maquina_components/combobox_helper.rb +300 -0
- data/app/helpers/maquina_components/icons_helper.rb +220 -0
- data/app/helpers/maquina_components/table_helper.rb +9 -10
- data/app/helpers/maquina_components/toast_helper.rb +115 -0
- data/app/javascript/controllers/calendar_controller.js +394 -0
- data/app/javascript/controllers/combobox_controller.js +325 -0
- data/app/javascript/controllers/date_picker_controller.js +261 -0
- data/app/javascript/controllers/toast_controller.js +115 -0
- data/app/javascript/controllers/toaster_controller.js +226 -0
- data/app/views/components/_calendar.html.erb +121 -0
- data/app/views/components/_combobox.html.erb +13 -0
- data/app/views/components/_date_picker.html.erb +102 -0
- data/app/views/components/_toast.html.erb +53 -0
- data/app/views/components/_toaster.html.erb +17 -0
- data/app/views/components/calendar/_header.html.erb +22 -0
- data/app/views/components/calendar/_week.html.erb +53 -0
- data/app/views/components/combobox/_content.html.erb +17 -0
- data/app/views/components/combobox/_empty.html.erb +9 -0
- data/app/views/components/combobox/_group.html.erb +8 -0
- data/app/views/components/combobox/_input.html.erb +18 -0
- data/app/views/components/combobox/_label.html.erb +8 -0
- data/app/views/components/combobox/_list.html.erb +8 -0
- data/app/views/components/combobox/_option.html.erb +24 -0
- data/app/views/components/combobox/_separator.html.erb +6 -0
- data/app/views/components/combobox/_trigger.html.erb +22 -0
- data/app/views/components/toast/_action.html.erb +14 -0
- data/app/views/components/toast/_description.html.erb +8 -0
- data/app/views/components/toast/_title.html.erb +8 -0
- data/lib/maquina_components/version.rb +1 -1
- metadata +33 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1449d3d6edf1341e73d321b0821c1e3e355659022865465949ebf2202426d7b5
|
|
4
|
+
data.tar.gz: ffbe3396ad981086e0979756e401942410a66e2257db71a0e21a3d7a674658ed
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ec918743d27c761eb32bdce4c3a7f79e02668ea649c6ee3cdf676408c8666866e5d1dddeb72ec725d8a1a0f738273091553d75214cadf0a3c18a1c6932795131
|
|
7
|
+
data.tar.gz: 2ba3990b4ed9dfb77e03bf5f9734a355f48ee9a3903afb41cd1b8e00c5f022a17b3db790e774a9d4868b8d8bd663969d278f24fc5678441c37579662d693930f
|
data/README.md
CHANGED
|
@@ -152,8 +152,17 @@ bin/rails generate maquina_components:install --skip-helper
|
|
|
152
152
|
|
|
153
153
|
| Component | Description | Documentation |
|
|
154
154
|
|-----------|-------------|---------------|
|
|
155
|
+
| **Calendar** | Inline date picker with single/range selection | [Calendar](https://maquina.app/documentation/components/calendar/) |
|
|
156
|
+
| **Combobox** | Searchable dropdown with keyboard navigation | [Combobox](https://maquina.app/documentation/components/combobox/) |
|
|
157
|
+
| **Date Picker** | Popover-based date selection | [Date Picker](https://maquina.app/documentation/components/date-picker/) |
|
|
155
158
|
| **Toggle Group** | Single/multiple selection button group | [Toggle Group](https://maquina.app/documentation/components/toggle-group/) |
|
|
156
159
|
|
|
160
|
+
### Feedback Components
|
|
161
|
+
|
|
162
|
+
| Component | Description | Documentation |
|
|
163
|
+
|-----------|-------------|---------------|
|
|
164
|
+
| **Toast** | Non-intrusive notifications with auto-dismiss | [Toast](https://maquina.app/documentation/components/toast/) |
|
|
165
|
+
|
|
157
166
|
### Form Components
|
|
158
167
|
|
|
159
168
|
| Component | Data Attribute | Variants |
|
|
@@ -252,6 +261,41 @@ bin/rails generate maquina_components:install --skip-helper
|
|
|
252
261
|
<%= pagination_nav(@pagy, :users_path) %>
|
|
253
262
|
```
|
|
254
263
|
|
|
264
|
+
### Combobox
|
|
265
|
+
|
|
266
|
+
```erb
|
|
267
|
+
<%= render "components/combobox", placeholder: "Select framework..." do |combobox_id| %>
|
|
268
|
+
<%= render "components/combobox/trigger", for_id: combobox_id, placeholder: "Select framework..." %>
|
|
269
|
+
<%= render "components/combobox/content", id: combobox_id do %>
|
|
270
|
+
<%= render "components/combobox/input", placeholder: "Search..." %>
|
|
271
|
+
<%= render "components/combobox/list" do %>
|
|
272
|
+
<%= render "components/combobox/option", value: "rails" do %>Ruby on Rails<% end %>
|
|
273
|
+
<%= render "components/combobox/option", value: "hanami" do %>Hanami<% end %>
|
|
274
|
+
<%= render "components/combobox/option", value: "sinatra" do %>Sinatra<% end %>
|
|
275
|
+
<% end %>
|
|
276
|
+
<%= render "components/combobox/empty" %>
|
|
277
|
+
<% end %>
|
|
278
|
+
<% end %>
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Toast Notifications
|
|
282
|
+
|
|
283
|
+
```erb
|
|
284
|
+
<%# Add toaster to your layout %>
|
|
285
|
+
<%= render "components/toaster", position: :bottom_right do %>
|
|
286
|
+
<%= toast_flash_messages %>
|
|
287
|
+
<% end %>
|
|
288
|
+
|
|
289
|
+
<%# In your controller %>
|
|
290
|
+
flash[:success] = "Changes saved successfully!"
|
|
291
|
+
|
|
292
|
+
<%# Or use the JavaScript API %>
|
|
293
|
+
<script>
|
|
294
|
+
Toast.success("Profile updated!")
|
|
295
|
+
Toast.error("Something went wrong", { description: "Please try again." })
|
|
296
|
+
</script>
|
|
297
|
+
```
|
|
298
|
+
|
|
255
299
|
### Tables
|
|
256
300
|
|
|
257
301
|
```erb
|
|
@@ -349,6 +393,10 @@ The install generator adds default theme variables. Customize them in `app/asset
|
|
|
349
393
|
| `sidebar_open?(cookie_name)` | Check if the sidebar is expanded |
|
|
350
394
|
| `pagination_nav(pagy, route)` | Render pagination from Pagy object |
|
|
351
395
|
| `pagination_simple(pagy, route)` | Render simple Previous/Next pagination |
|
|
396
|
+
| `toast_flash_messages` | Render all flash messages as toasts |
|
|
397
|
+
| `toast(variant, title, **options)` | Render a single toast notification |
|
|
398
|
+
| `combobox(placeholder:, **options, &block)` | Builder pattern for combobox |
|
|
399
|
+
| `combobox_simple(options:, **options)` | Data-driven simple combobox |
|
|
352
400
|
|
|
353
401
|
---
|
|
354
402
|
|
|
@@ -379,8 +427,15 @@ The install generator adds default theme variables. Customize them in `app/asset
|
|
|
379
427
|
|
|
380
428
|
### Interactive
|
|
381
429
|
|
|
430
|
+
- **[Calendar](https://maquina.app/documentation/components/calendar/)** — Inline date picker
|
|
431
|
+
- **[Combobox](https://maquina.app/documentation/components/combobox/)** — Searchable dropdown selection
|
|
432
|
+
- **[Date Picker](https://maquina.app/documentation/components/date-picker/)** — Popover date selection
|
|
382
433
|
- **[Toggle Group](https://maquina.app/documentation/components/toggle-group/)** — Toggle button groups
|
|
383
434
|
|
|
435
|
+
### Feedback
|
|
436
|
+
|
|
437
|
+
- **[Toast](https://maquina.app/documentation/components/toast/)** — Toast notifications
|
|
438
|
+
|
|
384
439
|
### Forms
|
|
385
440
|
|
|
386
441
|
- **[Form Components](https://maquina.app/documentation/components/form/)** — Buttons, inputs, and form styling
|
|
@@ -404,6 +459,28 @@ bin/rails test
|
|
|
404
459
|
|
|
405
460
|
---
|
|
406
461
|
|
|
462
|
+
## Claude Code Skill
|
|
463
|
+
|
|
464
|
+
This repository includes a Claude Code skill that teaches Claude how to build consistent, accessible UIs using maquina_components. The skill provides:
|
|
465
|
+
|
|
466
|
+
- **Component catalog** — Complete reference for all components with ERB examples
|
|
467
|
+
- **Form patterns** — Validation, error handling, and complex form structures
|
|
468
|
+
- **Layout patterns** — Sidebar navigation, page structure, responsive design
|
|
469
|
+
- **Turbo integration** — Turbo Frames, Streams, and component updates
|
|
470
|
+
- **Spec checklist** — Review criteria for UI implementation quality
|
|
471
|
+
|
|
472
|
+
### Installation
|
|
473
|
+
|
|
474
|
+
Copy the `skill/` directory to your Rails project:
|
|
475
|
+
|
|
476
|
+
```bash
|
|
477
|
+
cp -r /path/to/maquina_components/skill .claude/skills/maquina-ui-standards
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
See the [Skill README](skill/README.md) for detailed installation and usage instructions.
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
407
484
|
## Contributing
|
|
408
485
|
|
|
409
486
|
Bug reports and pull requests are welcome on GitHub at [github.com/maquina-app/maquina_components](https://github.com/maquina-app/maquina_components).
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/* ===== Calendar Component Styles ===== */
|
|
2
|
+
/*
|
|
3
|
+
* A date picker calendar with single and range selection.
|
|
4
|
+
* Uses data attributes for styling to avoid inline utility classes.
|
|
5
|
+
* Fully compatible with dark mode via CSS variables.
|
|
6
|
+
*
|
|
7
|
+
* Structure:
|
|
8
|
+
* - calendar (root container)
|
|
9
|
+
* - header (navigation)
|
|
10
|
+
* - weekdays (day name headers)
|
|
11
|
+
* - grid (day buttons grid)
|
|
12
|
+
* - week (row)
|
|
13
|
+
* - day (button)
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/* ===== Root Container ===== */
|
|
17
|
+
[data-component="calendar"] {
|
|
18
|
+
--cell-size: 2rem;
|
|
19
|
+
|
|
20
|
+
@apply p-3 w-fit rounded-lg border;
|
|
21
|
+
background-color: var(--background);
|
|
22
|
+
border-color: var(--border);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* ===== Header (Navigation) ===== */
|
|
26
|
+
[data-calendar-part="header"] {
|
|
27
|
+
display: flex;
|
|
28
|
+
align-items: center;
|
|
29
|
+
justify-content: space-between;
|
|
30
|
+
@apply mb-4;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
[data-calendar-part="header"] button {
|
|
34
|
+
display: inline-flex;
|
|
35
|
+
align-items: center;
|
|
36
|
+
justify-content: center;
|
|
37
|
+
width: var(--cell-size);
|
|
38
|
+
height: var(--cell-size);
|
|
39
|
+
@apply rounded-md;
|
|
40
|
+
border: none;
|
|
41
|
+
cursor: pointer;
|
|
42
|
+
background-color: transparent;
|
|
43
|
+
color: var(--foreground);
|
|
44
|
+
@apply transition-colors duration-150;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
[data-calendar-part="header"] button:hover:not(:disabled) {
|
|
48
|
+
background-color: var(--accent);
|
|
49
|
+
color: var(--accent-foreground);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
[data-calendar-part="header"] button:focus-visible {
|
|
53
|
+
@apply outline-none;
|
|
54
|
+
box-shadow: 0 0 0 2px var(--background),
|
|
55
|
+
0 0 0 4px var(--ring);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
[data-calendar-part="header"] button:disabled {
|
|
59
|
+
@apply opacity-50 cursor-not-allowed;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
[data-calendar-part="header"] button svg {
|
|
63
|
+
@apply size-4 shrink-0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
[data-calendar-part="caption"] {
|
|
67
|
+
@apply text-sm font-medium select-none;
|
|
68
|
+
color: var(--foreground);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* ===== Weekday Headers ===== */
|
|
72
|
+
[data-calendar-part="weekdays"] {
|
|
73
|
+
display: grid;
|
|
74
|
+
grid-template-columns: repeat(7, var(--cell-size));
|
|
75
|
+
@apply mb-1;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
[data-calendar-part="weekday"] {
|
|
79
|
+
display: flex;
|
|
80
|
+
align-items: center;
|
|
81
|
+
justify-content: center;
|
|
82
|
+
width: var(--cell-size);
|
|
83
|
+
height: var(--cell-size);
|
|
84
|
+
@apply text-xs font-normal select-none;
|
|
85
|
+
color: var(--muted-foreground);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* ===== Calendar Grid ===== */
|
|
89
|
+
[data-calendar-part="grid"] {
|
|
90
|
+
display: flex;
|
|
91
|
+
flex-direction: column;
|
|
92
|
+
@apply gap-1;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
[data-calendar-part="week"] {
|
|
96
|
+
display: grid;
|
|
97
|
+
grid-template-columns: repeat(7, var(--cell-size));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* ===== Day Button Base ===== */
|
|
101
|
+
[data-calendar-part="day"] {
|
|
102
|
+
display: inline-flex;
|
|
103
|
+
align-items: center;
|
|
104
|
+
justify-content: center;
|
|
105
|
+
width: var(--cell-size);
|
|
106
|
+
height: var(--cell-size);
|
|
107
|
+
@apply text-sm font-normal rounded-md;
|
|
108
|
+
border: none;
|
|
109
|
+
cursor: pointer;
|
|
110
|
+
background-color: transparent;
|
|
111
|
+
color: var(--foreground);
|
|
112
|
+
@apply transition-colors duration-150;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/* ===== Day States ===== */
|
|
116
|
+
|
|
117
|
+
/* Hover */
|
|
118
|
+
[data-calendar-part="day"]:hover:not(:disabled):not([data-state]) {
|
|
119
|
+
background-color: var(--accent);
|
|
120
|
+
color: var(--accent-foreground);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* Today */
|
|
124
|
+
[data-calendar-part="day"][data-today] {
|
|
125
|
+
background-color: var(--accent);
|
|
126
|
+
color: var(--accent-foreground);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* Selected (single mode) */
|
|
130
|
+
[data-calendar-part="day"][data-state="selected"] {
|
|
131
|
+
background-color: var(--primary);
|
|
132
|
+
color: var(--primary-foreground);
|
|
133
|
+
@apply rounded-md;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
[data-calendar-part="day"][data-state="selected"]:hover {
|
|
137
|
+
background-color: var(--primary);
|
|
138
|
+
color: var(--primary-foreground);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* Range Start */
|
|
142
|
+
[data-calendar-part="day"][data-state="range-start"] {
|
|
143
|
+
background-color: var(--primary);
|
|
144
|
+
color: var(--primary-foreground);
|
|
145
|
+
@apply rounded-l-md rounded-r-none;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* Range End */
|
|
149
|
+
[data-calendar-part="day"][data-state="range-end"] {
|
|
150
|
+
background-color: var(--primary);
|
|
151
|
+
color: var(--primary-foreground);
|
|
152
|
+
@apply rounded-r-md rounded-l-none;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* Range Middle */
|
|
156
|
+
[data-calendar-part="day"][data-state="range-middle"] {
|
|
157
|
+
background-color: var(--accent);
|
|
158
|
+
color: var(--accent-foreground);
|
|
159
|
+
@apply rounded-none;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/* Today within selection - override background */
|
|
163
|
+
[data-calendar-part="day"][data-today][data-state="selected"],
|
|
164
|
+
[data-calendar-part="day"][data-today][data-state="range-start"],
|
|
165
|
+
[data-calendar-part="day"][data-today][data-state="range-end"] {
|
|
166
|
+
background-color: var(--primary);
|
|
167
|
+
color: var(--primary-foreground);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
[data-calendar-part="day"][data-today][data-state="range-middle"] {
|
|
171
|
+
background-color: var(--accent);
|
|
172
|
+
color: var(--accent-foreground);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* Outside days (previous/next month) */
|
|
176
|
+
[data-calendar-part="day"][data-outside] {
|
|
177
|
+
color: var(--muted-foreground);
|
|
178
|
+
@apply opacity-50;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
[data-calendar-part="day"][data-outside][data-state="selected"],
|
|
182
|
+
[data-calendar-part="day"][data-outside][data-state="range-start"],
|
|
183
|
+
[data-calendar-part="day"][data-outside][data-state="range-end"] {
|
|
184
|
+
color: var(--primary-foreground);
|
|
185
|
+
@apply opacity-30;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
[data-calendar-part="day"][data-outside][data-state="range-middle"] {
|
|
189
|
+
color: var(--accent-foreground);
|
|
190
|
+
@apply opacity-30;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/* Disabled */
|
|
194
|
+
[data-calendar-part="day"]:disabled {
|
|
195
|
+
color: var(--muted-foreground);
|
|
196
|
+
@apply opacity-50 cursor-not-allowed;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/* Focus */
|
|
200
|
+
[data-calendar-part="day"]:focus-visible {
|
|
201
|
+
@apply outline-none;
|
|
202
|
+
position: relative;
|
|
203
|
+
z-index: 10;
|
|
204
|
+
box-shadow: 0 0 0 2px var(--background),
|
|
205
|
+
0 0 0 4px var(--ring);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/* ===== Responsive Cell Sizes ===== */
|
|
209
|
+
/*
|
|
210
|
+
* Custom cell sizes can be set via --cell-size CSS variable:
|
|
211
|
+
* style="--cell-size: 2.5rem;"
|
|
212
|
+
*
|
|
213
|
+
* Or with Tailwind classes:
|
|
214
|
+
* css_classes: "[--cell-size:2.5rem] md:[--cell-size:3rem]"
|
|
215
|
+
*/
|
|
216
|
+
|
|
217
|
+
/* ===== Dark Mode ===== */
|
|
218
|
+
/*
|
|
219
|
+
* Dark mode is handled automatically through CSS variables.
|
|
220
|
+
* The theme variables change based on the .dark class on html/body.
|
|
221
|
+
* No additional dark mode styles needed here.
|
|
222
|
+
*/
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/* ===== Combobox Component Styles ===== */
|
|
2
|
+
/*
|
|
3
|
+
* Combobox component for autocomplete/search with selection.
|
|
4
|
+
* Uses HTML5 Popover API for positioning and light-dismiss.
|
|
5
|
+
* Uses data attributes for styling to avoid inline utility classes.
|
|
6
|
+
* Fully compatible with dark mode via CSS variables.
|
|
7
|
+
*
|
|
8
|
+
* Structure:
|
|
9
|
+
* - combobox (root with Stimulus controller)
|
|
10
|
+
* - trigger (button that opens popover)
|
|
11
|
+
* - content (popover container)
|
|
12
|
+
* - input (search field)
|
|
13
|
+
* - list (scrollable options)
|
|
14
|
+
* - option (selectable item)
|
|
15
|
+
* - group (logical grouping)
|
|
16
|
+
* - label (section heading)
|
|
17
|
+
* - separator (divider)
|
|
18
|
+
* - empty (no results message)
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/* ===== Root Container ===== */
|
|
22
|
+
[data-component="combobox"] {
|
|
23
|
+
position: relative;
|
|
24
|
+
display: inline-block;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* ===== Trigger Button ===== */
|
|
28
|
+
/* Trigger uses button component styles via data-component="button" */
|
|
29
|
+
[data-combobox-part="trigger"] {
|
|
30
|
+
@apply justify-between gap-2;
|
|
31
|
+
min-width: 200px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
[data-combobox-part="trigger"] [data-combobox-target="label"] {
|
|
35
|
+
@apply truncate text-left flex-1;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* Placeholder state */
|
|
39
|
+
[data-combobox-part="trigger"][data-has-value="false"] [data-combobox-target="label"] {
|
|
40
|
+
color: var(--muted-foreground);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* Icon styling */
|
|
44
|
+
[data-combobox-part="trigger"] > svg {
|
|
45
|
+
@apply size-4 shrink-0 opacity-50;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* ===== Content (Popover) ===== */
|
|
49
|
+
[data-combobox-part="content"] {
|
|
50
|
+
background-color: var(--popover, var(--background));
|
|
51
|
+
color: var(--popover-foreground, var(--foreground));
|
|
52
|
+
border-color: var(--border);
|
|
53
|
+
@apply rounded-md border p-0 shadow-md outline-none;
|
|
54
|
+
@apply min-w-[200px];
|
|
55
|
+
|
|
56
|
+
/* Reset popover defaults - positioning handled by JS */
|
|
57
|
+
margin: 0;
|
|
58
|
+
padding: 0;
|
|
59
|
+
inset: unset;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* Width variants */
|
|
63
|
+
[data-combobox-part="content"][data-width="sm"] {
|
|
64
|
+
@apply w-40;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
[data-combobox-part="content"][data-width="default"] {
|
|
68
|
+
@apply w-[200px];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
[data-combobox-part="content"][data-width="md"] {
|
|
72
|
+
@apply w-56;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
[data-combobox-part="content"][data-width="lg"] {
|
|
76
|
+
@apply w-72;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
[data-combobox-part="content"][data-width="full"] {
|
|
80
|
+
@apply w-full;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* Alignment is handled by JavaScript for proper popover positioning */
|
|
84
|
+
|
|
85
|
+
/* Animation */
|
|
86
|
+
[data-combobox-part="content"]:popover-open {
|
|
87
|
+
animation: combobox-in 150ms ease-out;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@keyframes combobox-in {
|
|
91
|
+
from {
|
|
92
|
+
opacity: 0;
|
|
93
|
+
transform: scale(0.95) translateY(-4px);
|
|
94
|
+
}
|
|
95
|
+
to {
|
|
96
|
+
opacity: 1;
|
|
97
|
+
transform: scale(1) translateY(0);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* ===== Search Input ===== */
|
|
102
|
+
[data-combobox-part="input-wrapper"] {
|
|
103
|
+
display: flex;
|
|
104
|
+
align-items: center;
|
|
105
|
+
border-bottom: 1px solid var(--border);
|
|
106
|
+
@apply px-3 gap-2;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
[data-combobox-part="input-wrapper"] > svg {
|
|
110
|
+
@apply size-4 shrink-0 opacity-50;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
[data-combobox-part="input"] {
|
|
114
|
+
background-color: transparent;
|
|
115
|
+
color: var(--foreground);
|
|
116
|
+
@apply flex h-10 w-full py-3 text-sm outline-none;
|
|
117
|
+
@apply placeholder:text-muted-foreground;
|
|
118
|
+
@apply disabled:cursor-not-allowed disabled:opacity-50;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* ===== Options List ===== */
|
|
122
|
+
[data-combobox-part="list"] {
|
|
123
|
+
@apply max-h-[300px] overflow-y-auto overflow-x-hidden p-1;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* ===== Option Item ===== */
|
|
127
|
+
[data-combobox-part="option"] {
|
|
128
|
+
position: relative;
|
|
129
|
+
display: flex;
|
|
130
|
+
align-items: center;
|
|
131
|
+
cursor: default;
|
|
132
|
+
user-select: none;
|
|
133
|
+
color: var(--popover-foreground, var(--foreground));
|
|
134
|
+
@apply gap-2 rounded-sm py-1.5 text-sm outline-none transition-colors;
|
|
135
|
+
@apply pl-8 pr-2; /* Space for check icon on left */
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* Hover state */
|
|
139
|
+
[data-combobox-part="option"]:hover:not([aria-disabled="true"]) {
|
|
140
|
+
background-color: var(--accent);
|
|
141
|
+
color: var(--accent-foreground);
|
|
142
|
+
cursor: pointer;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/* Focus state (keyboard navigation) */
|
|
146
|
+
[data-combobox-part="option"]:focus {
|
|
147
|
+
background-color: var(--accent);
|
|
148
|
+
color: var(--accent-foreground);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/* Selected state */
|
|
152
|
+
[data-combobox-part="option"][data-selected="true"] {
|
|
153
|
+
background-color: var(--accent);
|
|
154
|
+
color: var(--accent-foreground);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/* Disabled state */
|
|
158
|
+
[data-combobox-part="option"][aria-disabled="true"] {
|
|
159
|
+
@apply opacity-50 cursor-not-allowed pointer-events-none;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/* Hidden state (filtered out) */
|
|
163
|
+
[data-combobox-part="option"][hidden] {
|
|
164
|
+
display: none;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* Check indicator */
|
|
168
|
+
[data-combobox-part="check"] {
|
|
169
|
+
position: absolute;
|
|
170
|
+
left: 8px;
|
|
171
|
+
display: flex;
|
|
172
|
+
align-items: center;
|
|
173
|
+
justify-content: center;
|
|
174
|
+
@apply size-4;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
[data-combobox-part="check"].invisible {
|
|
178
|
+
visibility: hidden;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
[data-combobox-part="check"] svg {
|
|
182
|
+
@apply size-4;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/* ===== Empty State ===== */
|
|
186
|
+
[data-combobox-part="empty"] {
|
|
187
|
+
@apply py-6 text-center text-sm;
|
|
188
|
+
color: var(--muted-foreground);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
[data-combobox-part="empty"][hidden] {
|
|
192
|
+
display: none;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/* ===== Group ===== */
|
|
196
|
+
[data-combobox-part="group"] {
|
|
197
|
+
display: flex;
|
|
198
|
+
flex-direction: column;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/* ===== Label ===== */
|
|
202
|
+
[data-combobox-part="label"] {
|
|
203
|
+
@apply px-2 py-1.5 text-xs font-medium;
|
|
204
|
+
color: var(--muted-foreground);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/* ===== Separator ===== */
|
|
208
|
+
[data-combobox-part="separator"] {
|
|
209
|
+
@apply -mx-1 my-1 h-px;
|
|
210
|
+
background-color: var(--border);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/* ===== Dark Mode ===== */
|
|
214
|
+
/*
|
|
215
|
+
* Dark mode is handled automatically through CSS variables.
|
|
216
|
+
* The theme variables change based on the .dark class on html/body.
|
|
217
|
+
* No additional dark mode styles needed here.
|
|
218
|
+
*/
|