handzon-core 0.6.1 → 0.7.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.
@@ -0,0 +1,206 @@
1
+ /* Multi-select dropdown (handzon-core/src/components/ui/MultiSelect.tsx).
2
+ *
3
+ * Wraps Radix Popover. Visual parity with the single-select Dropdown:
4
+ * trigger reuses .hz-dd-label + .hz-dd-trigger + .hz-dd-caret. The
5
+ * popover content (option list, in-popover search, count badges,
6
+ * footer Clear) is what's specific to multi-select.
7
+ */
8
+
9
+ /* The MultiSelect trigger is a single <button> wrapping the label
10
+ * chip + the inner trigger body. Radix Popover.Trigger asChild needs
11
+ * a *single* focusable element, so we collapse the structure into one
12
+ * button and let CSS draw the chip + body as siblings. */
13
+ .hz-ms-trigger {
14
+ background: transparent;
15
+ border: 0;
16
+ padding: 0;
17
+ /* The button is also a `.hz-dd` element. That sibling class sets
18
+ * font-size: 0.78em + the mono family. Don't redeclare font-size /
19
+ * font-weight / line-height / letter-spacing here — at equal
20
+ * specificity, this stylesheet loads after dropdown.css and would
21
+ * win, resolving `inherit` to the body's 16px and making the
22
+ * trigger taller than the single-select Sort dropdown. We only
23
+ * need to undo the UA button defaults that .hz-dd doesn't already
24
+ * cover (font-family + color). */
25
+ font-family: inherit;
26
+ color: inherit;
27
+ display: inline-flex;
28
+ align-items: stretch;
29
+ cursor: pointer;
30
+ }
31
+ .hz-ms-trigger-body {
32
+ display: inline-flex;
33
+ align-items: center;
34
+ gap: 0.45rem;
35
+ padding: 0.4rem 0.6rem;
36
+ min-height: 2.5rem;
37
+ background: transparent;
38
+ border: 1px solid var(--color-border);
39
+ color: var(--color-fg);
40
+ transition: border-color 0.12s ease, color 0.12s ease;
41
+ }
42
+ .hz-ms-trigger:hover .hz-ms-trigger-body,
43
+ .hz-ms-trigger:focus-visible .hz-ms-trigger-body,
44
+ .hz-ms-trigger[data-state="open"] .hz-ms-trigger-body {
45
+ border-color: var(--color-accent);
46
+ color: var(--color-accent);
47
+ }
48
+ .hz-ms-trigger:focus-visible { outline: none; }
49
+ .hz-ms-trigger[data-active] .hz-ms-trigger-body {
50
+ border-color: var(--color-accent);
51
+ color: var(--color-accent);
52
+ }
53
+
54
+ /* Icon sits inside the label chip on the LEFT segment, not inside
55
+ * the trigger body, so the chip reads "[icon] LEVEL" and the body
56
+ * carries only the current value. */
57
+ .hz-ms-label {
58
+ display: inline-flex;
59
+ align-items: center;
60
+ gap: 0.4rem;
61
+ /* Re-assert uppercase here because the inline-flex layout on the
62
+ * chip creates a nested span structure that loses the inheritance
63
+ * from .hz-dd-label in some rendering contexts. */
64
+ text-transform: uppercase;
65
+ }
66
+ .hz-ms-label-icon {
67
+ display: inline-flex;
68
+ align-items: center;
69
+ color: var(--color-muted);
70
+ }
71
+
72
+ /* Inherit the trigger's font (already mono + 0.78em via .hz-dd).
73
+ * No font-size override here — it would compound with the parent
74
+ * (0.78em × 0.78em ≈ 0.6em) and render as tiny ~10px text, out of
75
+ * step with the single-select Dropdown's value chrome.
76
+ *
77
+ * No muted color for the empty "Any" state either — the value text
78
+ * should read the same as the Sort dropdown's "Default" so the
79
+ * three trigger bodies share one visual rhythm. */
80
+ .hz-ms-value {
81
+ font-family: inherit;
82
+ }
83
+
84
+ /* ---------- Popover content ---------- */
85
+
86
+ .hz-ms-content {
87
+ z-index: 100;
88
+ min-width: 16rem;
89
+ max-width: 22rem;
90
+ display: flex;
91
+ flex-direction: column;
92
+ background: var(--color-bg);
93
+ border: 1px solid var(--color-border);
94
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
95
+ font-family: var(--font-mono);
96
+ font-size: 0.78em;
97
+ }
98
+
99
+ .hz-ms-search {
100
+ display: flex;
101
+ align-items: center;
102
+ gap: 0.5rem;
103
+ padding: 0.55rem 0.7rem;
104
+ border-bottom: 1px solid var(--color-border);
105
+ color: var(--color-muted);
106
+ }
107
+ .hz-ms-search input {
108
+ background: transparent;
109
+ border: 0;
110
+ color: var(--color-fg);
111
+ font: inherit;
112
+ outline: none;
113
+ width: 100%;
114
+ }
115
+ .hz-ms-search input::-webkit-search-cancel-button { display: none; }
116
+
117
+ .hz-ms-viewport {
118
+ max-height: 16rem;
119
+ overflow-y: auto;
120
+ padding: 0.25rem 0;
121
+ }
122
+
123
+ .hz-ms-empty {
124
+ padding: 0.75rem 0.85rem;
125
+ color: var(--color-muted);
126
+ text-align: center;
127
+ font-style: italic;
128
+ }
129
+
130
+ .hz-ms-option {
131
+ display: flex;
132
+ align-items: center;
133
+ gap: 0.55rem;
134
+ padding: 0.45rem 0.7rem;
135
+ cursor: pointer;
136
+ user-select: none;
137
+ outline: none;
138
+ color: var(--color-fg);
139
+ }
140
+ .hz-ms-option:hover,
141
+ .hz-ms-option:focus-visible,
142
+ .hz-ms-option[tabindex="0"]:focus {
143
+ background: var(--color-surface);
144
+ }
145
+ .hz-ms-option[data-checked] {
146
+ color: var(--color-accent);
147
+ }
148
+
149
+ .hz-ms-check {
150
+ display: inline-flex;
151
+ align-items: center;
152
+ justify-content: center;
153
+ width: 14px;
154
+ height: 14px;
155
+ border: 1px solid var(--color-border);
156
+ flex-shrink: 0;
157
+ color: var(--color-accent);
158
+ }
159
+ .hz-ms-option[data-checked] .hz-ms-check {
160
+ border-color: var(--color-accent);
161
+ background: color-mix(in oklab, var(--color-accent) 10%, transparent);
162
+ }
163
+
164
+ .hz-ms-option-label {
165
+ flex: 1;
166
+ text-transform: lowercase;
167
+ overflow: hidden;
168
+ text-overflow: ellipsis;
169
+ white-space: nowrap;
170
+ }
171
+
172
+ .hz-ms-count {
173
+ color: var(--color-muted);
174
+ font-size: 0.9em;
175
+ flex-shrink: 0;
176
+ }
177
+ .hz-ms-option[data-checked] .hz-ms-count { color: var(--color-accent); }
178
+
179
+ .hz-ms-footer {
180
+ padding: 0.45rem 0.55rem;
181
+ border-top: 1px solid var(--color-border);
182
+ display: flex;
183
+ justify-content: flex-end;
184
+ }
185
+
186
+ .hz-ms-clear {
187
+ display: inline-flex;
188
+ align-items: center;
189
+ gap: 0.35rem;
190
+ padding: 0.25rem 0.55rem;
191
+ background: transparent;
192
+ border: 1px solid var(--color-border);
193
+ color: var(--color-muted);
194
+ font: inherit;
195
+ cursor: pointer;
196
+ text-transform: uppercase;
197
+ letter-spacing: 0.06em;
198
+ font-size: 0.88em;
199
+ transition: color 0.12s ease, border-color 0.12s ease;
200
+ }
201
+ .hz-ms-clear:hover,
202
+ .hz-ms-clear:focus-visible {
203
+ color: var(--color-accent);
204
+ border-color: var(--color-accent);
205
+ outline: none;
206
+ }
@@ -9,6 +9,9 @@
9
9
  @import "./components/expressive-code.css";
10
10
  @import "./components/a11y.css";
11
11
  @import "./components/modal.css";
12
+ @import "./components/dropdown.css";
13
+ @import "./components/multiselect.css";
14
+ @import "./components/filterbar.css";
12
15
 
13
16
  /* Site chrome */
14
17
  @import "./components/progress.css";