maquina-components 0.5.0 → 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 +79 -3
- data/app/assets/stylesheets/alert.css +169 -135
- data/app/assets/stylesheets/badge.css +143 -138
- data/app/assets/stylesheets/breadcrumbs.css +185 -147
- data/app/assets/stylesheets/calendar.css +219 -206
- data/app/assets/stylesheets/card.css +126 -120
- data/app/assets/stylesheets/combobox.css +215 -163
- data/app/assets/stylesheets/date_picker.css +144 -134
- data/app/assets/stylesheets/drawer.css +166 -118
- 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 +178 -0
- data/app/assets/stylesheets/pagination.css +130 -125
- data/app/assets/stylesheets/separator.css +32 -0
- data/app/assets/stylesheets/sidebar.css +448 -390
- data/app/assets/stylesheets/stats.css +111 -0
- 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 -12
- data/app/assets/tailwind/maquina_components_engine/tokens.css +101 -0
- data/app/helpers/maquina_components/combobox_helper.rb +34 -25
- data/app/helpers/maquina_components/components_helper.rb +57 -0
- data/app/helpers/maquina_components/dropdown_menu_helper.rb +12 -12
- data/app/helpers/maquina_components/icons_helper.rb +84 -2
- data/app/javascript/controllers/breadcrumb_controller.js +39 -30
- data/app/javascript/controllers/combobox_controller.js +9 -0
- data/app/javascript/controllers/drawer_controller.js +43 -9
- data/app/javascript/controllers/drawer_trigger_controller.js +55 -4
- data/app/javascript/controllers/menu_button_controller.js +107 -29
- data/app/javascript/controllers/sidebar_controller.js +6 -8
- data/app/javascript/controllers/sidebar_trigger_controller.js +33 -4
- data/app/javascript/controllers/toaster_controller.js +12 -0
- data/app/views/components/_alert.html.erb +3 -1
- data/app/views/components/_badge.html.erb +7 -1
- data/app/views/components/_breadcrumbs.html.erb +1 -1
- data/app/views/components/_calendar.html.erb +1 -1
- data/app/views/components/_card.html.erb +1 -1
- data/app/views/components/_combobox.html.erb +3 -2
- data/app/views/components/_date_picker.html.erb +4 -3
- data/app/views/components/_drawer.html.erb +8 -2
- data/app/views/components/_dropdown.html.erb +21 -24
- data/app/views/components/_dropdown_menu.html.erb +1 -1
- data/app/views/components/_empty.html.erb +1 -1
- data/app/views/components/_header.html.erb +1 -1
- data/app/views/components/_label.html.erb +14 -0
- data/app/views/components/_menu_button.html.erb +29 -34
- data/app/views/components/_pagination.html.erb +1 -1
- data/app/views/components/_separator.html.erb +9 -10
- data/app/views/components/_sidebar.html.erb +1 -1
- data/app/views/components/_simple_table.html.erb +3 -1
- data/app/views/components/_table.html.erb +3 -3
- data/app/views/components/_toast.html.erb +6 -1
- data/app/views/components/_toaster.html.erb +1 -1
- data/app/views/components/_toggle_group.html.erb +1 -1
- data/app/views/components/alert/_description.html.erb +1 -1
- data/app/views/components/alert/_title.html.erb +1 -1
- data/app/views/components/breadcrumbs/_ellipsis.html.erb +1 -1
- data/app/views/components/breadcrumbs/_item.html.erb +1 -1
- data/app/views/components/breadcrumbs/_link.html.erb +1 -1
- data/app/views/components/breadcrumbs/_list.html.erb +1 -1
- data/app/views/components/breadcrumbs/_page.html.erb +1 -1
- data/app/views/components/breadcrumbs/_separator.html.erb +1 -1
- data/app/views/components/calendar/_header.html.erb +1 -1
- data/app/views/components/calendar/_week.html.erb +5 -13
- data/app/views/components/card/_action.html.erb +1 -1
- data/app/views/components/card/_content.html.erb +1 -1
- data/app/views/components/card/_description.html.erb +1 -1
- data/app/views/components/card/_footer.html.erb +1 -1
- data/app/views/components/card/_header.html.erb +1 -1
- data/app/views/components/card/_title.html.erb +1 -1
- data/app/views/components/combobox/_content.html.erb +1 -1
- data/app/views/components/combobox/_empty.html.erb +3 -3
- data/app/views/components/combobox/_group.html.erb +1 -1
- data/app/views/components/combobox/_input.html.erb +1 -1
- data/app/views/components/combobox/_label.html.erb +1 -1
- data/app/views/components/combobox/_list.html.erb +1 -1
- data/app/views/components/combobox/_option.html.erb +1 -1
- data/app/views/components/combobox/_separator.html.erb +1 -1
- data/app/views/components/combobox/_trigger.html.erb +1 -1
- data/app/views/components/drawer/_close.html.erb +2 -2
- data/app/views/components/drawer/_content.html.erb +1 -1
- data/app/views/components/drawer/_description.html.erb +6 -0
- data/app/views/components/drawer/_footer.html.erb +1 -1
- data/app/views/components/drawer/_header.html.erb +3 -3
- data/app/views/components/drawer/_provider.html.erb +14 -5
- 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/dropdown_menu/_content.html.erb +1 -1
- data/app/views/components/dropdown_menu/_group.html.erb +1 -1
- data/app/views/components/dropdown_menu/_item.html.erb +1 -1
- data/app/views/components/dropdown_menu/_label.html.erb +3 -7
- data/app/views/components/dropdown_menu/_separator.html.erb +1 -1
- data/app/views/components/dropdown_menu/_shortcut.html.erb +3 -7
- data/app/views/components/dropdown_menu/_trigger.html.erb +1 -1
- data/app/views/components/empty/_content.html.erb +1 -1
- data/app/views/components/empty/_description.html.erb +3 -7
- data/app/views/components/empty/_header.html.erb +1 -1
- data/app/views/components/empty/_media.html.erb +5 -3
- data/app/views/components/empty/_title.html.erb +3 -7
- data/app/views/components/pagination/_content.html.erb +1 -1
- data/app/views/components/pagination/_item.html.erb +1 -1
- data/app/views/components/pagination/_link.html.erb +1 -1
- data/app/views/components/pagination/_next.html.erb +1 -1
- data/app/views/components/pagination/_previous.html.erb +1 -1
- data/app/views/components/sidebar/_content.html.erb +1 -1
- data/app/views/components/sidebar/_footer.html.erb +1 -1
- data/app/views/components/sidebar/_group.html.erb +1 -1
- data/app/views/components/sidebar/_group_action.html.erb +26 -0
- data/app/views/components/sidebar/_header.html.erb +1 -1
- data/app/views/components/sidebar/_inset.html.erb +1 -1
- data/app/views/components/sidebar/_menu.html.erb +1 -1
- 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 +4 -3
- data/app/views/components/sidebar/_menu_item.html.erb +1 -1
- data/app/views/components/sidebar/_menu_link.html.erb +7 -9
- data/app/views/components/sidebar/_provider.html.erb +1 -1
- data/app/views/components/sidebar/_separator.html.erb +12 -0
- data/app/views/components/sidebar/_trigger.html.erb +1 -1
- data/app/views/components/stats/_stats_card.html.erb +32 -92
- data/app/views/components/stats/_stats_grid.html.erb +18 -24
- data/app/views/components/table/_body.html.erb +1 -1
- data/app/views/components/table/_caption.html.erb +3 -3
- data/app/views/components/table/_cell.html.erb +3 -3
- data/app/views/components/table/_footer.html.erb +1 -1
- data/app/views/components/table/_head.html.erb +3 -3
- data/app/views/components/table/_header.html.erb +1 -1
- data/app/views/components/table/_row.html.erb +1 -1
- data/app/views/components/toast/_action.html.erb +1 -1
- data/app/views/components/toast/_description.html.erb +1 -1
- data/app/views/components/toast/_title.html.erb +1 -1
- data/app/views/components/toggle_group/_item.html.erb +1 -1
- data/lib/generators/maquina_components/install/install_generator.rb +36 -1
- data/lib/generators/maquina_components/install/templates/maquina_components_helper.rb.tt +6 -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 +34 -1
- data/lib/maquina_components/doctor.rb +280 -0
- data/lib/maquina_components/engine.rb +7 -3
- data/lib/maquina_components/version.rb +1 -1
- data/lib/tasks/maquina_components_tasks.rake +16 -4
- metadata +46 -3
- data/app/assets/stylesheets/maquina_components.css +0 -178
|
@@ -1,145 +1,150 @@
|
|
|
1
1
|
/* ===== Badge Component Styles ===== */
|
|
2
|
-
/*
|
|
2
|
+
/*
|
|
3
3
|
* Badge component for status indicators, tags, counts, and labels.
|
|
4
4
|
* Uses data attributes for styling to avoid inline utility classes.
|
|
5
5
|
* Fully compatible with dark mode and supports icons.
|
|
6
|
+
*
|
|
7
|
+
* Cascade order in this file (full contract documented in form.css):
|
|
8
|
+
* 1. base [data-component="badge"]
|
|
9
|
+
* 2. sizes [data-component="badge"]:where([data-size="…"])
|
|
10
|
+
* 3. variants [data-component="badge"]:where([data-variant="…"])
|
|
11
|
+
* 4. states :where(:hover, :focus-visible, :active, :disabled)
|
|
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 or a
|
|
16
|
+
* pseudo-element read 0,1,1 — an element selector cannot be zeroed away.)
|
|
6
17
|
*/
|
|
7
18
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
[data-component="badge"][data-variant="
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
19
|
+
@layer components {
|
|
20
|
+
/* ===== Base Badge Styles ===== */
|
|
21
|
+
[data-component="badge"] {
|
|
22
|
+
/* Layout */
|
|
23
|
+
display: inline-flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
white-space: nowrap;
|
|
26
|
+
@apply gap-1 border border-transparent leading-none;
|
|
27
|
+
border-radius: var(--badge-radius, var(--control-radius, 0.375rem));
|
|
28
|
+
font-weight: var(--label-weight, 500);
|
|
29
|
+
|
|
30
|
+
/* Transitions */
|
|
31
|
+
@apply transition-[background-color,border-color,color,opacity] duration-150;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* ===== Icon Support ===== */
|
|
35
|
+
[data-component="badge"] svg {
|
|
36
|
+
/* Scales with font size using em */
|
|
37
|
+
width: 0.875em;
|
|
38
|
+
height: 0.875em;
|
|
39
|
+
@apply shrink-0 pointer-events-none;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* ===== Size Variants ===== */
|
|
43
|
+
|
|
44
|
+
/* Small size - compact badges for inline use */
|
|
45
|
+
[data-component="badge"]:where([data-size="sm"]) {
|
|
46
|
+
@apply text-xs px-2 py-0.5 h-5;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* Medium size - default, balanced size */
|
|
50
|
+
[data-component="badge"]:where([data-size="md"]) {
|
|
51
|
+
@apply text-sm px-2.5 py-1 h-6;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Large size - prominent badges */
|
|
55
|
+
[data-component="badge"]:where([data-size="lg"]) {
|
|
56
|
+
@apply text-sm px-3 py-1.5 h-7;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* ===== Visual Variants ===== */
|
|
60
|
+
|
|
61
|
+
/* Default variant - muted appearance */
|
|
62
|
+
[data-component="badge"]:where([data-variant="default"]) {
|
|
63
|
+
background-color: var(--muted);
|
|
64
|
+
color: var(--muted-foreground);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* Primary variant - brand color */
|
|
68
|
+
[data-component="badge"]:where([data-variant="primary"]) {
|
|
69
|
+
background-color: var(--primary);
|
|
70
|
+
color: var(--primary-foreground);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Secondary variant - subtle appearance */
|
|
74
|
+
[data-component="badge"]:where([data-variant="secondary"]) {
|
|
75
|
+
background-color: var(--secondary);
|
|
76
|
+
color: var(--secondary-foreground);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Destructive variant - errors, deletions */
|
|
80
|
+
[data-component="badge"]:where([data-variant="destructive"]) {
|
|
81
|
+
background-color: var(--destructive);
|
|
82
|
+
color: var(--destructive-foreground);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* Success variant - positive status */
|
|
86
|
+
[data-component="badge"]:where([data-variant="success"]) {
|
|
87
|
+
background-color: var(--success, oklch(0.627 0.194 149.214));
|
|
88
|
+
color: var(--success-foreground, oklch(0.985 0 0));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/* Warning variant - caution status */
|
|
92
|
+
[data-component="badge"]:where([data-variant="warning"]) {
|
|
93
|
+
background-color: var(--warning, oklch(0.769 0.188 70.08));
|
|
94
|
+
color: var(--warning-foreground, oklch(0.216 0.006 56.043));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* Info variant - informational status.
|
|
98
|
+
--info has no engine default on purpose: undefined falls back to the neutral
|
|
99
|
+
default treatment, never to --primary (which would make an informational
|
|
100
|
+
badge read as a brand call to action). */
|
|
101
|
+
[data-component="badge"]:where([data-variant="info"]) {
|
|
102
|
+
background-color: var(--info, var(--muted));
|
|
103
|
+
color: var(--info-foreground, var(--muted-foreground));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* Outline variant - transparent with border */
|
|
107
|
+
[data-component="badge"]:where([data-variant="outline"]) {
|
|
108
|
+
@apply bg-transparent;
|
|
109
|
+
color: var(--foreground);
|
|
110
|
+
border-color: var(--border);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* ===== Interactive States (when used as link/button) ===== */
|
|
114
|
+
|
|
115
|
+
/* Hover - solid variants just soften */
|
|
116
|
+
[data-component="badge"]:where(
|
|
117
|
+
[data-variant="default"]:hover,
|
|
118
|
+
[data-variant="primary"]:hover,
|
|
119
|
+
[data-variant="secondary"]:hover,
|
|
120
|
+
[data-variant="destructive"]:hover,
|
|
121
|
+
[data-variant="success"]:hover,
|
|
122
|
+
[data-variant="warning"]:hover,
|
|
123
|
+
[data-variant="info"]:hover
|
|
124
|
+
) {
|
|
125
|
+
@apply opacity-90;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* Hover - the outline variant fills instead */
|
|
129
|
+
[data-component="badge"]:where([data-variant="outline"]:hover) {
|
|
130
|
+
background-color: var(--accent-hover, var(--accent));
|
|
131
|
+
color: var(--accent-foreground);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* Focus state for keyboard navigation */
|
|
135
|
+
[data-component="badge"]:where(a:focus-visible, button:focus-visible) {
|
|
136
|
+
outline: var(--focus-ring-width, 3px) var(--focus-ring-style, solid)
|
|
137
|
+
var(--focus-ring-color, var(--ring));
|
|
138
|
+
outline-offset: var(--focus-ring-offset, 0px);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* Active/pressed state */
|
|
142
|
+
[data-component="badge"]:where(a:active, button:active) {
|
|
143
|
+
@apply scale-[0.98];
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* Disabled state (if used as button) */
|
|
147
|
+
[data-component="badge"]:where(button:disabled) {
|
|
148
|
+
@apply opacity-50 cursor-not-allowed pointer-events-none;
|
|
149
|
+
}
|
|
81
150
|
}
|
|
82
|
-
|
|
83
|
-
[data-component="badge"][data-variant="destructive"]:hover {
|
|
84
|
-
@apply opacity-90;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/* Success variant - positive status */
|
|
88
|
-
[data-component="badge"][data-variant="success"] {
|
|
89
|
-
background-color: var(--success);
|
|
90
|
-
color: var(--success-foreground);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
[data-component="badge"][data-variant="success"]:hover {
|
|
94
|
-
@apply opacity-90;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/* Warning variant - caution status */
|
|
98
|
-
[data-component="badge"][data-variant="warning"] {
|
|
99
|
-
background-color: var(--warning);
|
|
100
|
-
color: var(--warning-foreground);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
[data-component="badge"][data-variant="warning"]:hover {
|
|
104
|
-
@apply opacity-90;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/* Outline variant - transparent with border */
|
|
108
|
-
[data-component="badge"][data-variant="outline"] {
|
|
109
|
-
@apply bg-transparent;
|
|
110
|
-
color: var(--foreground);
|
|
111
|
-
border-color: var(--border);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
[data-component="badge"][data-variant="outline"]:hover {
|
|
115
|
-
background-color: var(--accent);
|
|
116
|
-
color: var(--accent-foreground);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/* ===== Interactive States (when used as link/button) ===== */
|
|
120
|
-
|
|
121
|
-
/* Focus state for keyboard navigation */
|
|
122
|
-
a[data-component="badge"]:focus-visible,
|
|
123
|
-
button[data-component="badge"]:focus-visible {
|
|
124
|
-
@apply outline-none;
|
|
125
|
-
box-shadow: 0 0 0 2px var(--background),
|
|
126
|
-
0 0 0 4px var(--border);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/* Active/pressed state */
|
|
130
|
-
a[data-component="badge"]:active,
|
|
131
|
-
button[data-component="badge"]:active {
|
|
132
|
-
@apply scale-[0.98];
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/* Disabled state (if used as button) */
|
|
136
|
-
button[data-component="badge"]:disabled {
|
|
137
|
-
@apply opacity-50 cursor-not-allowed pointer-events-none;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/* ===== Dark Mode ===== */
|
|
141
|
-
/*
|
|
142
|
-
* Dark mode is handled automatically through CSS variables.
|
|
143
|
-
* The theme variables change based on the .dark class on html/body.
|
|
144
|
-
* No additional dark mode styles needed here.
|
|
145
|
-
*/
|
|
@@ -1,186 +1,224 @@
|
|
|
1
1
|
/* ===== Breadcrumbs Component Styles ===== */
|
|
2
2
|
/* Comprehensive CSS using data-attribute selectors */
|
|
3
3
|
/* Uses @apply for theme-customizable properties */
|
|
4
|
+
/*
|
|
5
|
+
* Cascade order in this file (full contract documented in form.css):
|
|
6
|
+
* 1. base [data-component="breadcrumbs"], [data-breadcrumb-part="…"]
|
|
7
|
+
* 2. sizes :where([data-component="breadcrumbs"][data-size="sm"]) …
|
|
8
|
+
* 3. variants :where([data-component="breadcrumbs"][data-separator="…"]) …
|
|
9
|
+
* 4. states […]:where(:hover, :focus-visible, [data-state="open"], .hidden)
|
|
10
|
+
* 5. dark — none; dark-mode differences are tokens (see tokens.css)
|
|
11
|
+
* Every rule is flattened to 0,1,0 with :where() and lives in
|
|
12
|
+
* @layer components, so a caller's utility class wins and source order is
|
|
13
|
+
* the only tie-breaker. (Rules whose target is a bare element or a
|
|
14
|
+
* pseudo-element read 0,1,1 — an element selector cannot be zeroed away.)
|
|
15
|
+
*
|
|
16
|
+
* Imported LAST, after dropdown_menu.css: the overflow popover below has to
|
|
17
|
+
* beat dropdown_menu.css's `position: absolute`, and since every rule is now a
|
|
18
|
+
* flat 0,1,0 that is decided by import order alone (it used to lean on a
|
|
19
|
+
* doubled attribute selector). See engine.css.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
@layer components {
|
|
23
|
+
/* ===== Breadcrumbs Container (nav) ===== */
|
|
24
|
+
[data-component="breadcrumbs"] {
|
|
25
|
+
/* Container has no default styles - allows flexible placement */
|
|
26
|
+
}
|
|
4
27
|
|
|
5
|
-
/* ===== Breadcrumbs
|
|
6
|
-
[data-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@apply text-sm break-words;
|
|
14
|
-
list-style: none;
|
|
15
|
-
padding: 0;
|
|
16
|
-
margin: 0;
|
|
17
|
-
}
|
|
28
|
+
/* ===== Breadcrumbs List ===== */
|
|
29
|
+
[data-breadcrumb-part="list"] {
|
|
30
|
+
@apply flex flex-wrap items-center gap-1.5;
|
|
31
|
+
@apply text-sm break-words;
|
|
32
|
+
list-style: none;
|
|
33
|
+
padding: 0;
|
|
34
|
+
margin: 0;
|
|
35
|
+
}
|
|
18
36
|
|
|
19
|
-
/* Compact variant */
|
|
20
|
-
[data-component="breadcrumbs"][data-size="sm"] [data-breadcrumb-part="list"] {
|
|
21
|
-
|
|
22
|
-
}
|
|
37
|
+
/* Compact variant */
|
|
38
|
+
:where([data-component="breadcrumbs"][data-size="sm"]) [data-breadcrumb-part="list"] {
|
|
39
|
+
@apply gap-1 text-xs;
|
|
40
|
+
}
|
|
23
41
|
|
|
24
|
-
/* ===== Breadcrumb Item ===== */
|
|
25
|
-
[data-breadcrumb-part="item"] {
|
|
26
|
-
|
|
27
|
-
}
|
|
42
|
+
/* ===== Breadcrumb Item ===== */
|
|
43
|
+
[data-breadcrumb-part="item"] {
|
|
44
|
+
@apply inline-flex items-center;
|
|
45
|
+
}
|
|
28
46
|
|
|
29
|
-
/* Hidden state for responsive collapsing */
|
|
30
|
-
[data-breadcrumb-part="item"].hidden {
|
|
31
|
-
|
|
32
|
-
}
|
|
47
|
+
/* Hidden state for responsive collapsing */
|
|
48
|
+
[data-breadcrumb-part="item"]:where(.hidden) {
|
|
49
|
+
@apply hidden;
|
|
50
|
+
}
|
|
33
51
|
|
|
34
|
-
/* ===== Breadcrumb Link ===== */
|
|
35
|
-
[data-breadcrumb-part="link"] {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
52
|
+
/* ===== Breadcrumb Link ===== */
|
|
53
|
+
[data-breadcrumb-part="link"] {
|
|
54
|
+
@apply inline-flex items-center;
|
|
55
|
+
@apply text-sm;
|
|
56
|
+
font-weight: var(--label-weight, 500);
|
|
57
|
+
@apply underline-offset-4;
|
|
58
|
+
@apply transition-colors;
|
|
59
|
+
color: var(--muted-foreground);
|
|
60
|
+
}
|
|
42
61
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
62
|
+
/* Link with icon */
|
|
63
|
+
[data-breadcrumb-part="link"] svg {
|
|
64
|
+
@apply size-3.5 shrink-0;
|
|
65
|
+
}
|
|
47
66
|
|
|
48
|
-
[data-breadcrumb-part="link"]:
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
67
|
+
[data-breadcrumb-part="link"] svg:where(:first-child) {
|
|
68
|
+
@apply mr-1.5;
|
|
69
|
+
}
|
|
52
70
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
71
|
+
[data-breadcrumb-part="link"]:where(:hover) {
|
|
72
|
+
color: var(--foreground);
|
|
73
|
+
@apply underline;
|
|
74
|
+
}
|
|
57
75
|
|
|
58
|
-
[data-breadcrumb-part="link"]
|
|
59
|
-
|
|
60
|
-
|
|
76
|
+
[data-breadcrumb-part="link"]:where(:focus-visible) {
|
|
77
|
+
@apply outline-none underline;
|
|
78
|
+
color: var(--foreground);
|
|
79
|
+
}
|
|
61
80
|
|
|
62
|
-
/* ===== Breadcrumb Page (current) ===== */
|
|
63
|
-
[data-breadcrumb-part="page"] {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
81
|
+
/* ===== Breadcrumb Page (current) ===== */
|
|
82
|
+
[data-breadcrumb-part="page"] {
|
|
83
|
+
@apply inline-flex items-center;
|
|
84
|
+
@apply text-sm;
|
|
85
|
+
font-weight: var(--label-weight, 500);
|
|
86
|
+
color: var(--foreground);
|
|
87
|
+
}
|
|
68
88
|
|
|
69
|
-
/* Page with icon */
|
|
70
|
-
[data-breadcrumb-part="page"] svg {
|
|
71
|
-
|
|
72
|
-
}
|
|
89
|
+
/* Page with icon */
|
|
90
|
+
[data-breadcrumb-part="page"] svg {
|
|
91
|
+
@apply size-3.5 shrink-0;
|
|
92
|
+
}
|
|
73
93
|
|
|
74
|
-
[data-breadcrumb-part="page"] svg:first-child {
|
|
75
|
-
|
|
76
|
-
}
|
|
94
|
+
[data-breadcrumb-part="page"] svg:where(:first-child) {
|
|
95
|
+
@apply mr-1.5;
|
|
96
|
+
}
|
|
77
97
|
|
|
78
|
-
/* ===== Breadcrumb Separator ===== */
|
|
79
|
-
[data-breadcrumb-part="separator"] {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
98
|
+
/* ===== Breadcrumb Separator ===== */
|
|
99
|
+
[data-breadcrumb-part="separator"] {
|
|
100
|
+
@apply inline-flex items-center;
|
|
101
|
+
color: var(--muted-foreground);
|
|
102
|
+
}
|
|
83
103
|
|
|
84
|
-
[data-breadcrumb-part="separator"] svg {
|
|
85
|
-
|
|
86
|
-
}
|
|
104
|
+
[data-breadcrumb-part="separator"] svg {
|
|
105
|
+
@apply size-3.5 shrink-0;
|
|
106
|
+
}
|
|
87
107
|
|
|
88
|
-
/* Hidden state for responsive collapsing */
|
|
89
|
-
[data-breadcrumb-part="separator"].hidden {
|
|
90
|
-
|
|
91
|
-
}
|
|
108
|
+
/* Hidden state for responsive collapsing */
|
|
109
|
+
[data-breadcrumb-part="separator"]:where(.hidden) {
|
|
110
|
+
@apply hidden;
|
|
111
|
+
}
|
|
92
112
|
|
|
93
|
-
/* ===== Breadcrumb Ellipsis ===== */
|
|
94
|
-
[data-breadcrumb-part="ellipsis"] {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
113
|
+
/* ===== Breadcrumb Ellipsis ===== */
|
|
114
|
+
[data-breadcrumb-part="ellipsis"] {
|
|
115
|
+
@apply inline-flex size-9 items-center justify-center;
|
|
116
|
+
color: var(--muted-foreground);
|
|
117
|
+
cursor: pointer;
|
|
118
|
+
}
|
|
98
119
|
|
|
99
|
-
[data-breadcrumb-part="ellipsis"] svg {
|
|
100
|
-
|
|
101
|
-
}
|
|
120
|
+
[data-breadcrumb-part="ellipsis"] svg {
|
|
121
|
+
@apply size-4 shrink-0;
|
|
122
|
+
}
|
|
102
123
|
|
|
103
|
-
/* Ellipsis as dropdown trigger */
|
|
104
|
-
[data-breadcrumb-part="ellipsis"][data-state="open"],
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
124
|
+
/* Ellipsis as dropdown trigger */
|
|
125
|
+
[data-breadcrumb-part="ellipsis"]:where([data-state="open"], :hover) {
|
|
126
|
+
color: var(--foreground);
|
|
127
|
+
}
|
|
108
128
|
|
|
109
|
-
/* =====
|
|
110
|
-
/*
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
129
|
+
/* ===== Overflow Dropdown (top-layer popover) ===== */
|
|
130
|
+
/* Visual styling comes from dropdown_menu.css via data-dropdown-menu-part.
|
|
131
|
+
Anchor positioning places the popover in modern browsers;
|
|
132
|
+
breadcrumb_controller falls back to measured coordinates elsewhere. */
|
|
133
|
+
@supports (anchor-name: --a) and (position-area: block-end) {
|
|
134
|
+
[data-breadcrumb-part="ellipsis"] {
|
|
135
|
+
anchor-name: --maquina-breadcrumbs;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
[data-breadcrumb-part="dropdown"]:where([data-dropdown-menu-part="content"]) {
|
|
139
|
+
position: fixed;
|
|
140
|
+
position-anchor: --maquina-breadcrumbs;
|
|
141
|
+
position-area: block-end span-inline-end;
|
|
142
|
+
margin-block-start: 4px;
|
|
143
|
+
position-try-fallbacks: flip-block;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
114
146
|
|
|
115
|
-
/*
|
|
116
|
-
|
|
117
|
-
[data-controller="breadcrumb"] [data-breadcrumb-part="
|
|
118
|
-
|
|
119
|
-
}
|
|
147
|
+
/* ===== Responsive Behavior ===== */
|
|
148
|
+
/* Force nowrap when responsive controller is active so scrollWidth detects overflow */
|
|
149
|
+
:where([data-controller="breadcrumb"]) [data-breadcrumb-part="list"] {
|
|
150
|
+
@apply flex-nowrap overflow-hidden;
|
|
151
|
+
}
|
|
120
152
|
|
|
121
|
-
/*
|
|
122
|
-
[data-controller="breadcrumb"] [data-breadcrumb-part="item"]
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
153
|
+
/* Items must not shrink or wrap text, otherwise flex compresses them and scrollWidth never exceeds clientWidth */
|
|
154
|
+
:where([data-controller="breadcrumb"]) [data-breadcrumb-part="item"],
|
|
155
|
+
:where([data-controller="breadcrumb"]) [data-breadcrumb-part="separator"] {
|
|
156
|
+
@apply shrink-0 whitespace-nowrap;
|
|
157
|
+
}
|
|
126
158
|
|
|
127
|
-
|
|
128
|
-
[data-controller="breadcrumb"] [data-breadcrumb-part="item"]:last-child
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
159
|
+
/* Allow the last item (current page) to truncate gracefully instead of hard-clipping */
|
|
160
|
+
:where([data-controller="breadcrumb"]) [data-breadcrumb-part="item"]:where(:last-child) {
|
|
161
|
+
@apply shrink min-w-0 overflow-hidden;
|
|
162
|
+
text-overflow: ellipsis;
|
|
163
|
+
}
|
|
132
164
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
165
|
+
:where([data-controller="breadcrumb"] [data-breadcrumb-part="item"]:last-child) :is([data-breadcrumb-part="page"], [data-breadcrumb-part="link"]) {
|
|
166
|
+
@apply overflow-hidden;
|
|
167
|
+
text-overflow: ellipsis;
|
|
168
|
+
}
|
|
138
169
|
|
|
139
|
-
/*
|
|
140
|
-
[data-controller="breadcrumb"] [data-breadcrumb-target="
|
|
141
|
-
|
|
142
|
-
|
|
170
|
+
/* Items hidden by Stimulus controller */
|
|
171
|
+
:where([data-controller="breadcrumb"]) [data-breadcrumb-target="item"]:where(.hidden),
|
|
172
|
+
:where([data-controller="breadcrumb"]) [data-breadcrumb-target="ellipsisSeparator"]:where(.hidden) {
|
|
173
|
+
@apply hidden;
|
|
174
|
+
}
|
|
143
175
|
|
|
144
|
-
/*
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
@apply gap-1;
|
|
176
|
+
/* Ellipsis shown by Stimulus controller */
|
|
177
|
+
:where([data-controller="breadcrumb"]) [data-breadcrumb-target="ellipsis"]:where(:not(.hidden)) {
|
|
178
|
+
@apply inline-flex;
|
|
148
179
|
}
|
|
149
180
|
|
|
150
|
-
/*
|
|
151
|
-
|
|
152
|
-
|
|
181
|
+
/* ===== Mobile Adjustments ===== */
|
|
182
|
+
@media (max-width: 640px) {
|
|
183
|
+
[data-breadcrumb-part="list"] {
|
|
184
|
+
@apply gap-1;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/* Hide middle items on very small screens by default */
|
|
188
|
+
:where([data-component="breadcrumbs"][data-auto-collapse]) [data-breadcrumb-part="item"]:where(:not(:first-child):not(:last-child)) {
|
|
189
|
+
@apply hidden sm:inline-flex;
|
|
190
|
+
}
|
|
153
191
|
}
|
|
154
|
-
}
|
|
155
192
|
|
|
156
|
-
/* ===== Variants ===== */
|
|
193
|
+
/* ===== Separator Variants ===== */
|
|
157
194
|
|
|
158
|
-
/* Slash separator variant */
|
|
159
|
-
[data-component="breadcrumbs"][data-separator="slash"] [data-breadcrumb-part="separator"]::before {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
195
|
+
/* Slash separator variant */
|
|
196
|
+
:where([data-component="breadcrumbs"][data-separator="slash"]) [data-breadcrumb-part="separator"]::before {
|
|
197
|
+
content: "/";
|
|
198
|
+
@apply px-1;
|
|
199
|
+
}
|
|
163
200
|
|
|
164
|
-
[data-component="breadcrumbs"][data-separator="slash"] [data-breadcrumb-part="separator"] svg {
|
|
165
|
-
|
|
166
|
-
}
|
|
201
|
+
:where([data-component="breadcrumbs"][data-separator="slash"]) [data-breadcrumb-part="separator"] svg {
|
|
202
|
+
@apply hidden;
|
|
203
|
+
}
|
|
167
204
|
|
|
168
|
-
/* Dot separator variant */
|
|
169
|
-
[data-component="breadcrumbs"][data-separator="dot"] [data-breadcrumb-part="separator"]::before {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
205
|
+
/* Dot separator variant */
|
|
206
|
+
:where([data-component="breadcrumbs"][data-separator="dot"]) [data-breadcrumb-part="separator"]::before {
|
|
207
|
+
content: "•";
|
|
208
|
+
@apply px-1;
|
|
209
|
+
}
|
|
173
210
|
|
|
174
|
-
[data-component="breadcrumbs"][data-separator="dot"] [data-breadcrumb-part="separator"] svg {
|
|
175
|
-
|
|
176
|
-
}
|
|
211
|
+
:where([data-component="breadcrumbs"][data-separator="dot"]) [data-breadcrumb-part="separator"] svg {
|
|
212
|
+
@apply hidden;
|
|
213
|
+
}
|
|
177
214
|
|
|
178
|
-
/* Arrow separator variant */
|
|
179
|
-
[data-component="breadcrumbs"][data-separator="arrow"] [data-breadcrumb-part="separator"]::before {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
215
|
+
/* Arrow separator variant */
|
|
216
|
+
:where([data-component="breadcrumbs"][data-separator="arrow"]) [data-breadcrumb-part="separator"]::before {
|
|
217
|
+
content: "→";
|
|
218
|
+
@apply px-1;
|
|
219
|
+
}
|
|
183
220
|
|
|
184
|
-
[data-component="breadcrumbs"][data-separator="arrow"] [data-breadcrumb-part="separator"] svg {
|
|
185
|
-
|
|
221
|
+
:where([data-component="breadcrumbs"][data-separator="arrow"]) [data-breadcrumb-part="separator"] svg {
|
|
222
|
+
@apply hidden;
|
|
223
|
+
}
|
|
186
224
|
}
|