maquina-components 0.5.1 → 0.6.0
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 +76 -2
- data/app/assets/stylesheets/alert.css +169 -135
- data/app/assets/stylesheets/badge.css +143 -138
- data/app/assets/stylesheets/breadcrumbs.css +183 -166
- data/app/assets/stylesheets/calendar.css +219 -206
- data/app/assets/stylesheets/card.css +126 -120
- data/app/assets/stylesheets/combobox.css +208 -191
- data/app/assets/stylesheets/date_picker.css +144 -134
- data/app/assets/stylesheets/drawer.css +158 -125
- data/app/assets/stylesheets/dropdown_menu.css +203 -190
- data/app/assets/stylesheets/empty.css +125 -117
- data/app/assets/stylesheets/form.css +625 -525
- data/app/assets/stylesheets/header.css +63 -47
- data/app/assets/stylesheets/menu_button.css +121 -98
- data/app/assets/stylesheets/pagination.css +130 -125
- data/app/assets/stylesheets/separator.css +23 -11
- data/app/assets/stylesheets/sidebar.css +447 -401
- data/app/assets/stylesheets/stats.css +77 -67
- data/app/assets/stylesheets/table.css +184 -166
- data/app/assets/stylesheets/toast.css +287 -278
- data/app/assets/stylesheets/toggle_group.css +132 -139
- data/app/assets/tailwind/maquina_components_engine/engine.css +54 -15
- data/app/assets/tailwind/maquina_components_engine/tokens.css +101 -0
- data/app/helpers/maquina_components/combobox_helper.rb +32 -24
- data/app/helpers/maquina_components/components_helper.rb +30 -6
- data/app/helpers/maquina_components/dropdown_menu_helper.rb +12 -12
- data/app/helpers/maquina_components/icons_helper.rb +26 -2
- data/app/javascript/controllers/drawer_trigger_controller.js +24 -3
- data/app/views/components/_label.html.erb +14 -0
- data/app/views/components/_table.html.erb +2 -2
- data/app/views/components/calendar/_week.html.erb +4 -12
- data/app/views/components/drawer/_close.html.erb +1 -1
- data/app/views/components/drawer/_description.html.erb +6 -0
- data/app/views/components/drawer/_header.html.erb +1 -1
- data/app/views/components/drawer/_provider.html.erb +13 -4
- data/app/views/components/drawer/_section.html.erb +7 -0
- data/app/views/components/drawer/_separator.html.erb +11 -0
- data/app/views/components/drawer/_title.html.erb +6 -0
- data/app/views/components/drawer/_trigger.html.erb +24 -7
- data/app/views/components/sidebar/_group_action.html.erb +26 -0
- data/app/views/components/sidebar/_menu_action.html.erb +28 -0
- data/app/views/components/sidebar/_menu_badge.html.erb +10 -0
- data/app/views/components/sidebar/_menu_button.html.erb +3 -2
- data/app/views/components/sidebar/_menu_link.html.erb +3 -2
- data/app/views/components/sidebar/_separator.html.erb +12 -0
- data/lib/generators/maquina_components/install/install_generator.rb +36 -1
- data/lib/generators/maquina_components/install/templates/maquina_components_helper.rb.tt +5 -0
- data/lib/generators/maquina_components/install/templates/shape_state_tokens.css.tt +76 -0
- data/lib/generators/maquina_components/install/templates/theme.css.tt +10 -3
- data/lib/maquina-components.rb +29 -1
- data/lib/maquina_components/doctor.rb +280 -0
- data/lib/maquina_components/version.rb +1 -1
- data/lib/tasks/maquina_components_tasks.rake +16 -4
- metadata +14 -2
|
@@ -11,212 +11,225 @@
|
|
|
11
11
|
* - grid (day buttons grid)
|
|
12
12
|
* - week (row)
|
|
13
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
14
|
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
15
|
+
* Cascade order in this file (full contract documented in form.css):
|
|
16
|
+
* 1. base [data-component="calendar"], [data-calendar-part="…"]
|
|
17
|
+
* 2. sizes — none (cell metrics come from --cell-size)
|
|
18
|
+
* 3. variants [data-calendar-part="day"]:where([data-today], [data-state="…"], [data-outside])
|
|
19
|
+
* 4. states […]:where(:hover, :focus-visible, :disabled)
|
|
20
|
+
* 5. dark — none; dark-mode differences are tokens (see tokens.css)
|
|
21
|
+
* Every rule is flattened to 0,1,0 with :where() and lives in
|
|
22
|
+
* @layer components, so a caller's utility class wins and source order is
|
|
23
|
+
* the only tie-breaker. (Rules whose target is a bare element read 0,1,1 — an
|
|
24
|
+
* element selector cannot be zeroed away.)
|
|
25
|
+
*
|
|
26
|
+
* Note on the day cell: `:hover` deliberately sits after `[data-today]` and
|
|
27
|
+
* `[data-outside]`. Before flattening it out-specified them (0,4,0 vs 0,2,0);
|
|
28
|
+
* now only source order keeps that outcome.
|
|
29
|
+
*
|
|
30
|
+
* Custom cell sizes can be set via the --cell-size CSS variable:
|
|
31
|
+
* style="--cell-size: 2.5rem;"
|
|
32
|
+
* or with Tailwind classes:
|
|
33
|
+
* css_classes: "[--cell-size:2.5rem] md:[--cell-size:3rem]"
|
|
215
34
|
*/
|
|
216
35
|
|
|
217
|
-
|
|
218
|
-
/*
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
36
|
+
@layer components {
|
|
37
|
+
/* ===== Root Container ===== */
|
|
38
|
+
[data-component="calendar"] {
|
|
39
|
+
--cell-size: 2rem;
|
|
40
|
+
|
|
41
|
+
@apply p-3 w-fit border;
|
|
42
|
+
border-radius: var(--calendar-radius, var(--surface-radius, 0.5rem));
|
|
43
|
+
/* A calendar panel sits above the page (standalone or inside a date-picker
|
|
44
|
+
popover), so it paints --popover rather than the page background. */
|
|
45
|
+
background-color: var(--popover, var(--background));
|
|
46
|
+
border-color: var(--border);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* ===== Header (Navigation) ===== */
|
|
50
|
+
[data-calendar-part="header"] {
|
|
51
|
+
display: flex;
|
|
52
|
+
align-items: center;
|
|
53
|
+
justify-content: space-between;
|
|
54
|
+
@apply mb-4;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
[data-calendar-part="header"] button {
|
|
58
|
+
display: inline-flex;
|
|
59
|
+
align-items: center;
|
|
60
|
+
justify-content: center;
|
|
61
|
+
width: var(--cell-size);
|
|
62
|
+
height: var(--cell-size);
|
|
63
|
+
border-radius: var(--calendar-cell-radius, var(--control-radius, 0.375rem));
|
|
64
|
+
border: none;
|
|
65
|
+
cursor: pointer;
|
|
66
|
+
background-color: transparent;
|
|
67
|
+
color: var(--foreground);
|
|
68
|
+
@apply transition-colors duration-150;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
[data-calendar-part="header"] button svg {
|
|
72
|
+
@apply size-4 shrink-0;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
[data-calendar-part="header"] button:where(:hover:not(:disabled)) {
|
|
76
|
+
background-color: var(--accent-hover, var(--accent));
|
|
77
|
+
color: var(--accent-foreground);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
[data-calendar-part="header"] button:where(:focus-visible) {
|
|
81
|
+
outline: var(--focus-ring-width, 3px) var(--focus-ring-style, solid)
|
|
82
|
+
var(--focus-ring-color, var(--ring));
|
|
83
|
+
outline-offset: var(--focus-ring-offset, 0px);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
[data-calendar-part="header"] button:where(:disabled) {
|
|
87
|
+
@apply opacity-50 cursor-not-allowed;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
[data-calendar-part="caption"] {
|
|
91
|
+
@apply text-sm select-none;
|
|
92
|
+
font-weight: var(--label-weight, 500);
|
|
93
|
+
color: var(--foreground);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* ===== Weekday Headers ===== */
|
|
97
|
+
[data-calendar-part="weekdays"] {
|
|
98
|
+
display: grid;
|
|
99
|
+
grid-template-columns: repeat(7, var(--cell-size));
|
|
100
|
+
@apply mb-1;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
[data-calendar-part="weekday"] {
|
|
104
|
+
display: flex;
|
|
105
|
+
align-items: center;
|
|
106
|
+
justify-content: center;
|
|
107
|
+
width: var(--cell-size);
|
|
108
|
+
height: var(--cell-size);
|
|
109
|
+
@apply text-xs font-normal select-none;
|
|
110
|
+
color: var(--muted-foreground);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* ===== Calendar Grid ===== */
|
|
114
|
+
[data-calendar-part="grid"] {
|
|
115
|
+
display: flex;
|
|
116
|
+
flex-direction: column;
|
|
117
|
+
@apply gap-1;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
[data-calendar-part="week"] {
|
|
121
|
+
display: grid;
|
|
122
|
+
grid-template-columns: repeat(7, var(--cell-size));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* ===== Day Button Base ===== */
|
|
126
|
+
[data-calendar-part="day"] {
|
|
127
|
+
display: inline-flex;
|
|
128
|
+
align-items: center;
|
|
129
|
+
justify-content: center;
|
|
130
|
+
width: var(--cell-size);
|
|
131
|
+
height: var(--cell-size);
|
|
132
|
+
@apply text-sm font-normal;
|
|
133
|
+
border-radius: var(--calendar-cell-radius, var(--control-radius, 0.375rem));
|
|
134
|
+
border: none;
|
|
135
|
+
cursor: pointer;
|
|
136
|
+
background-color: transparent;
|
|
137
|
+
color: var(--foreground);
|
|
138
|
+
@apply transition-colors duration-150;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* ===== Day Variants ===== */
|
|
142
|
+
|
|
143
|
+
/* Today */
|
|
144
|
+
[data-calendar-part="day"]:where([data-today]) {
|
|
145
|
+
background-color: var(--accent);
|
|
146
|
+
color: var(--accent-foreground);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/* Selected (single mode) */
|
|
150
|
+
[data-calendar-part="day"]:where([data-state="selected"]) {
|
|
151
|
+
background-color: var(--primary);
|
|
152
|
+
color: var(--primary-foreground);
|
|
153
|
+
border-radius: var(--calendar-cell-radius, var(--control-radius, 0.375rem));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* Range Start */
|
|
157
|
+
[data-calendar-part="day"]:where([data-state="range-start"]) {
|
|
158
|
+
background-color: var(--primary);
|
|
159
|
+
color: var(--primary-foreground);
|
|
160
|
+
border-radius: var(--calendar-cell-radius, var(--control-radius, 0.375rem)) 0 0
|
|
161
|
+
var(--calendar-cell-radius, var(--control-radius, 0.375rem));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/* Range End */
|
|
165
|
+
[data-calendar-part="day"]:where([data-state="range-end"]) {
|
|
166
|
+
background-color: var(--primary);
|
|
167
|
+
color: var(--primary-foreground);
|
|
168
|
+
border-radius: 0 var(--calendar-cell-radius, var(--control-radius, 0.375rem))
|
|
169
|
+
var(--calendar-cell-radius, var(--control-radius, 0.375rem)) 0;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/* Range Middle */
|
|
173
|
+
[data-calendar-part="day"]:where([data-state="range-middle"]) {
|
|
174
|
+
background-color: var(--accent);
|
|
175
|
+
color: var(--accent-foreground);
|
|
176
|
+
/* Structural: the middle of a joined range must have square edges */
|
|
177
|
+
border-radius: 0;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/* Today within selection - override background */
|
|
181
|
+
[data-calendar-part="day"]:where([data-today][data-state="selected"], [data-today][data-state="range-start"], [data-today][data-state="range-end"]) {
|
|
182
|
+
background-color: var(--primary);
|
|
183
|
+
color: var(--primary-foreground);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
[data-calendar-part="day"]:where([data-today][data-state="range-middle"]) {
|
|
187
|
+
background-color: var(--accent);
|
|
188
|
+
color: var(--accent-foreground);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/* Outside days (previous/next month) */
|
|
192
|
+
[data-calendar-part="day"]:where([data-outside]) {
|
|
193
|
+
color: var(--muted-foreground);
|
|
194
|
+
@apply opacity-50;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
[data-calendar-part="day"]:where([data-outside][data-state="selected"], [data-outside][data-state="range-start"], [data-outside][data-state="range-end"]) {
|
|
198
|
+
color: var(--primary-foreground);
|
|
199
|
+
@apply opacity-30;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
[data-calendar-part="day"]:where([data-outside][data-state="range-middle"]) {
|
|
203
|
+
color: var(--accent-foreground);
|
|
204
|
+
@apply opacity-30;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/* ===== Day States ===== */
|
|
208
|
+
|
|
209
|
+
/* Hover — only for cells with no selection state of their own */
|
|
210
|
+
[data-calendar-part="day"]:where(:hover:not(:disabled):not([data-state])) {
|
|
211
|
+
background-color: var(--accent-hover, var(--accent));
|
|
212
|
+
color: var(--accent-foreground);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/* A selected cell keeps its fill on hover */
|
|
216
|
+
[data-calendar-part="day"]:where([data-state="selected"]:hover) {
|
|
217
|
+
background-color: var(--primary);
|
|
218
|
+
color: var(--primary-foreground);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/* Disabled */
|
|
222
|
+
[data-calendar-part="day"]:where(:disabled) {
|
|
223
|
+
color: var(--muted-foreground);
|
|
224
|
+
@apply opacity-50 cursor-not-allowed;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/* Focus */
|
|
228
|
+
[data-calendar-part="day"]:where(:focus-visible) {
|
|
229
|
+
position: relative;
|
|
230
|
+
z-index: 10;
|
|
231
|
+
outline: var(--focus-ring-width, 3px) var(--focus-ring-style, solid)
|
|
232
|
+
var(--focus-ring-color, var(--ring));
|
|
233
|
+
outline-offset: var(--focus-ring-offset, 0px);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
@@ -3,126 +3,132 @@
|
|
|
3
3
|
* Card component for grouping related content with header, body, and footer.
|
|
4
4
|
* Uses data attributes for styling to maintain consistency with other components.
|
|
5
5
|
* Fully compatible with dark mode via CSS variables.
|
|
6
|
+
*
|
|
7
|
+
* Cascade order in this file (full contract documented in form.css):
|
|
8
|
+
* 1. base [data-component="card"], [data-card-part="…"]
|
|
9
|
+
* 2. sizes […]:where([data-size="…"])
|
|
10
|
+
* 3. variants […]:where([data-layout="…"], [data-spacing="…"], [data-align="…"])
|
|
11
|
+
* 4. states […]:where(a:hover, button:focus-visible, …)
|
|
12
|
+
* 5. dark — none; dark-mode differences are tokens (see tokens.css)
|
|
13
|
+
* Every rule is flattened to 0,1,0 with :where() and lives in
|
|
14
|
+
* @layer components, so a caller's utility class wins and source order is
|
|
15
|
+
* the only tie-breaker. (Rules whose target is a bare element read 0,1,1 — an
|
|
16
|
+
* element selector cannot be zeroed away.)
|
|
6
17
|
*/
|
|
7
18
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
@layer components {
|
|
20
|
+
/* ===== Base Card Styles ===== */
|
|
21
|
+
[data-component="card"] {
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-direction: column;
|
|
24
|
+
|
|
25
|
+
/* Border, radius & elevation */
|
|
26
|
+
@apply border;
|
|
27
|
+
border-radius: var(--card-radius, var(--surface-radius, 0.5rem));
|
|
28
|
+
box-shadow: var(--card-shadow, var(--elevation-raised, var(--shadow-sm, 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1))));
|
|
29
|
+
border-color: var(--border);
|
|
30
|
+
|
|
31
|
+
/* Colors */
|
|
32
|
+
background-color: var(--card);
|
|
33
|
+
color: var(--card-foreground);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* ===== Card Header ===== */
|
|
37
|
+
:where([data-component="card"]) [data-card-part="header"] {
|
|
38
|
+
display: flex;
|
|
39
|
+
flex-direction: column;
|
|
40
|
+
@apply gap-1.5 p-6;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* Header with row layout (when using action) */
|
|
44
|
+
:where([data-component="card"]) [data-card-part="header"]:where([data-layout="row"]) {
|
|
45
|
+
flex-direction: row;
|
|
46
|
+
align-items: center;
|
|
47
|
+
justify-content: space-between;
|
|
48
|
+
@apply gap-4;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* ===== Card Title ===== */
|
|
52
|
+
:where([data-component="card"]) [data-card-part="title"] {
|
|
53
|
+
@apply text-lg font-semibold leading-none tracking-tight;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* Small title variant (for compact headers) */
|
|
57
|
+
:where([data-component="card"]) [data-card-part="title"]:where([data-size="sm"]) {
|
|
58
|
+
@apply text-sm;
|
|
59
|
+
font-weight: var(--label-weight, 500);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* ===== Card Description ===== */
|
|
63
|
+
:where([data-component="card"]) [data-card-part="description"] {
|
|
64
|
+
@apply text-sm;
|
|
65
|
+
color: var(--muted-foreground);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* ===== Card Action ===== */
|
|
69
|
+
:where([data-component="card"]) [data-card-part="action"] {
|
|
70
|
+
display: flex;
|
|
71
|
+
align-items: center;
|
|
72
|
+
flex-shrink: 0;
|
|
73
|
+
@apply gap-2;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* ===== Card Content ===== */
|
|
77
|
+
:where([data-component="card"]) [data-card-part="content"] {
|
|
78
|
+
@apply p-6 pt-0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* Content with top padding (when no header) */
|
|
82
|
+
:where([data-component="card"]) [data-card-part="content"]:where([data-spacing="full"]) {
|
|
83
|
+
@apply pt-6;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* ===== Card Footer ===== */
|
|
87
|
+
:where([data-component="card"]) [data-card-part="footer"] {
|
|
88
|
+
display: flex;
|
|
89
|
+
align-items: center;
|
|
90
|
+
@apply p-6 pt-0;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* Footer with top padding (when no content) */
|
|
94
|
+
:where([data-component="card"]) [data-card-part="footer"]:where([data-spacing="full"]) {
|
|
95
|
+
@apply pt-6;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* Footer alignment variants */
|
|
99
|
+
:where([data-component="card"]) [data-card-part="footer"]:where([data-align="between"]) {
|
|
100
|
+
justify-content: space-between;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
:where([data-component="card"]) [data-card-part="footer"]:where([data-align="end"]) {
|
|
104
|
+
justify-content: flex-end;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
:where([data-component="card"]) [data-card-part="footer"]:where([data-align="center"]) {
|
|
108
|
+
justify-content: center;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* ===== Icon Support ===== */
|
|
112
|
+
:where([data-component="card"]) [data-card-part="header"] svg,
|
|
113
|
+
:where([data-component="card"]) [data-card-part="action"] svg {
|
|
114
|
+
@apply size-4 shrink-0;
|
|
115
|
+
color: var(--muted-foreground);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* ===== Interactive Card (when used as link/button) ===== */
|
|
119
|
+
[data-component="card"]:where(a, button) {
|
|
120
|
+
text-decoration: none;
|
|
121
|
+
cursor: pointer;
|
|
122
|
+
@apply transition-[border-color,box-shadow] duration-150;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
[data-component="card"]:where(a:hover, button:hover) {
|
|
126
|
+
border-color: var(--accent);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
[data-component="card"]:where(a:focus-visible, button:focus-visible) {
|
|
130
|
+
outline: var(--focus-ring-width, 3px) var(--focus-ring-style, solid)
|
|
131
|
+
var(--focus-ring-color, var(--ring));
|
|
132
|
+
outline-offset: var(--focus-ring-offset, 0px);
|
|
133
|
+
}
|
|
20
134
|
}
|
|
21
|
-
|
|
22
|
-
/* ===== Card Header ===== */
|
|
23
|
-
[data-component="card"] [data-card-part="header"] {
|
|
24
|
-
display: flex;
|
|
25
|
-
flex-direction: column;
|
|
26
|
-
@apply gap-1.5 p-6;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/* Header with row layout (when using action) */
|
|
30
|
-
[data-component="card"] [data-card-part="header"][data-layout="row"] {
|
|
31
|
-
flex-direction: row;
|
|
32
|
-
align-items: center;
|
|
33
|
-
justify-content: space-between;
|
|
34
|
-
@apply gap-4;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/* ===== Card Title ===== */
|
|
38
|
-
[data-component="card"] [data-card-part="title"] {
|
|
39
|
-
@apply text-lg font-semibold leading-none tracking-tight;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/* Small title variant (for compact headers) */
|
|
43
|
-
[data-component="card"] [data-card-part="title"][data-size="sm"] {
|
|
44
|
-
@apply text-sm font-medium;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/* ===== Card Description ===== */
|
|
48
|
-
[data-component="card"] [data-card-part="description"] {
|
|
49
|
-
@apply text-sm;
|
|
50
|
-
color: var(--muted-foreground);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/* ===== Card Action ===== */
|
|
54
|
-
[data-component="card"] [data-card-part="action"] {
|
|
55
|
-
display: flex;
|
|
56
|
-
align-items: center;
|
|
57
|
-
flex-shrink: 0;
|
|
58
|
-
@apply gap-2;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/* ===== Card Content ===== */
|
|
62
|
-
[data-component="card"] [data-card-part="content"] {
|
|
63
|
-
@apply p-6 pt-0;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/* Content with top padding (when no header) */
|
|
67
|
-
[data-component="card"] [data-card-part="content"][data-spacing="full"] {
|
|
68
|
-
@apply pt-6;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/* ===== Card Footer ===== */
|
|
72
|
-
[data-component="card"] [data-card-part="footer"] {
|
|
73
|
-
display: flex;
|
|
74
|
-
align-items: center;
|
|
75
|
-
@apply p-6 pt-0;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/* Footer with top padding (when no content) */
|
|
79
|
-
[data-component="card"] [data-card-part="footer"][data-spacing="full"] {
|
|
80
|
-
@apply pt-6;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/* Footer alignment variants */
|
|
84
|
-
[data-component="card"] [data-card-part="footer"][data-align="between"] {
|
|
85
|
-
justify-content: space-between;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
[data-component="card"] [data-card-part="footer"][data-align="end"] {
|
|
89
|
-
justify-content: flex-end;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
[data-component="card"] [data-card-part="footer"][data-align="center"] {
|
|
93
|
-
justify-content: center;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/* ===== Icon Support ===== */
|
|
97
|
-
[data-component="card"] [data-card-part="header"] svg,
|
|
98
|
-
[data-component="card"] [data-card-part="action"] svg {
|
|
99
|
-
@apply size-4 shrink-0;
|
|
100
|
-
color: var(--muted-foreground);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/* ===== Interactive Card (when used as link/button) ===== */
|
|
104
|
-
a[data-component="card"],
|
|
105
|
-
button[data-component="card"] {
|
|
106
|
-
text-decoration: none;
|
|
107
|
-
cursor: pointer;
|
|
108
|
-
@apply transition-[border-color,box-shadow] duration-150;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
a[data-component="card"]:hover,
|
|
112
|
-
button[data-component="card"]:hover {
|
|
113
|
-
border-color: var(--accent);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
a[data-component="card"]:focus-visible,
|
|
117
|
-
button[data-component="card"]:focus-visible {
|
|
118
|
-
outline: none;
|
|
119
|
-
box-shadow: 0 0 0 2px var(--background),
|
|
120
|
-
0 0 0 4px var(--border);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/* ===== Dark Mode ===== */
|
|
124
|
-
/*
|
|
125
|
-
* Dark mode is handled automatically through CSS variables.
|
|
126
|
-
* The theme variables change based on the .dark class on html/body.
|
|
127
|
-
* No additional dark mode styles needed here.
|
|
128
|
-
*/
|