@filipgutica/ui 1.14.1 → 1.16.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.
- package/README.md +7 -5
- package/dist/components/UiSegmentedControl.vue.d.ts +42 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +177 -177
- package/dist/site/UiSiteAppearancePicker.vue.d.ts +12 -0
- package/dist/site/index.d.ts +2 -0
- package/dist/site.js +190 -185
- package/dist/{use-active-section-DCS_wyYq.js → use-active-section-DMbpGE2f.js} +60 -8
- package/package.json +1 -1
- package/src/components.css +51 -2
- package/src/site.css +2 -35
|
@@ -154,20 +154,72 @@ var N = /* @__PURE__ */ c({
|
|
|
154
154
|
_: 3
|
|
155
155
|
}, 8, ["open"]));
|
|
156
156
|
}
|
|
157
|
-
}), H =
|
|
157
|
+
}), H = [
|
|
158
|
+
"aria-label",
|
|
159
|
+
"data-size",
|
|
160
|
+
"data-icon-only"
|
|
161
|
+
], U = [
|
|
162
|
+
"aria-pressed",
|
|
163
|
+
"aria-label",
|
|
164
|
+
"title",
|
|
165
|
+
"disabled",
|
|
166
|
+
"onClick"
|
|
167
|
+
], W = {
|
|
168
|
+
key: 0,
|
|
169
|
+
class: "fg-segmented__label"
|
|
170
|
+
}, G = /* @__PURE__ */ c({
|
|
171
|
+
__name: "UiSegmentedControl",
|
|
172
|
+
props: {
|
|
173
|
+
label: {},
|
|
174
|
+
items: {},
|
|
175
|
+
modelValue: { default: () => void 0 },
|
|
176
|
+
iconOnly: {
|
|
177
|
+
type: Boolean,
|
|
178
|
+
default: !1
|
|
179
|
+
},
|
|
180
|
+
disabled: {
|
|
181
|
+
type: Boolean,
|
|
182
|
+
default: !1
|
|
183
|
+
},
|
|
184
|
+
size: { default: "md" }
|
|
185
|
+
},
|
|
186
|
+
emits: ["update:modelValue"],
|
|
187
|
+
setup(t, { emit: n }) {
|
|
188
|
+
let a = n;
|
|
189
|
+
return (n, o) => (f(), i("div", {
|
|
190
|
+
class: "fg-segmented",
|
|
191
|
+
role: "group",
|
|
192
|
+
"aria-label": t.label,
|
|
193
|
+
"data-size": t.size,
|
|
194
|
+
"data-icon-only": t.iconOnly ? "true" : void 0
|
|
195
|
+
}, [(f(!0), i(e, null, h(t.items, (e) => (f(), i("button", {
|
|
196
|
+
key: e.value,
|
|
197
|
+
type: "button",
|
|
198
|
+
class: "fg-segmented__item",
|
|
199
|
+
"aria-pressed": t.modelValue === e.value,
|
|
200
|
+
"aria-label": t.iconOnly ? e.label : void 0,
|
|
201
|
+
title: t.iconOnly ? e.label : void 0,
|
|
202
|
+
disabled: t.disabled || e.disabled,
|
|
203
|
+
onClick: (t) => a("update:modelValue", e.value)
|
|
204
|
+
}, [g(n.$slots, "icon", {
|
|
205
|
+
item: e,
|
|
206
|
+
pressed: t.modelValue === e.value
|
|
207
|
+
}), t.iconOnly ? r("", !0) : (f(), i("span", W, _(e.label), 1))], 8, U))), 128))], 8, H));
|
|
208
|
+
}
|
|
209
|
+
}), K = { class: "fg-tabs" }, q = ["aria-label", "data-clipped"], J = [
|
|
158
210
|
"id",
|
|
159
211
|
"aria-controls",
|
|
160
212
|
"aria-selected",
|
|
161
213
|
"tabindex",
|
|
162
214
|
"onClick",
|
|
163
215
|
"onFocus"
|
|
164
|
-
],
|
|
216
|
+
], Y = [
|
|
165
217
|
"id",
|
|
166
218
|
"role",
|
|
167
219
|
"aria-labelledby",
|
|
168
220
|
"hidden",
|
|
169
221
|
"tabindex"
|
|
170
|
-
],
|
|
222
|
+
], X = ["id", "hidden"], Z = /* @__PURE__ */ c({
|
|
171
223
|
__name: "UiTabs",
|
|
172
224
|
props: {
|
|
173
225
|
items: {},
|
|
@@ -224,7 +276,7 @@ var N = /* @__PURE__ */ c({
|
|
|
224
276
|
inline: "nearest"
|
|
225
277
|
}));
|
|
226
278
|
};
|
|
227
|
-
return (t, o) => (f(), i("div",
|
|
279
|
+
return (t, o) => (f(), i("div", K, [l.value ? (f(), i("div", {
|
|
228
280
|
key: 0,
|
|
229
281
|
ref_key: "list",
|
|
230
282
|
ref: C,
|
|
@@ -245,7 +297,7 @@ var N = /* @__PURE__ */ c({
|
|
|
245
297
|
tabindex: e.value === d.value ? 0 : -1,
|
|
246
298
|
onClick: (t) => O(e.value),
|
|
247
299
|
onFocus: (t) => O(e.value)
|
|
248
|
-
}, _(e.label), 41,
|
|
300
|
+
}, _(e.label), 41, J))), 128))], 40, q)) : r("", !0), (f(!0), i(e, null, h(n.items, (e) => (f(), i("section", {
|
|
249
301
|
id: v(e.value),
|
|
250
302
|
key: e.value,
|
|
251
303
|
class: "fg-tabs__panel",
|
|
@@ -257,9 +309,9 @@ var N = /* @__PURE__ */ c({
|
|
|
257
309
|
id: S(e.value),
|
|
258
310
|
class: "fg-tabs__heading",
|
|
259
311
|
hidden: l.value
|
|
260
|
-
}, _(e.label), 9,
|
|
312
|
+
}, _(e.label), 9, X), g(t.$slots, "panel", { value: e.value })], 8, Y))), 128))]));
|
|
261
313
|
}
|
|
262
|
-
}),
|
|
314
|
+
}), Q = ({ targetIds: e }) => {
|
|
263
315
|
let t = m(e[0]), n, r, i;
|
|
264
316
|
return u(() => {
|
|
265
317
|
let a = e.flatMap((e) => {
|
|
@@ -302,4 +354,4 @@ var N = /* @__PURE__ */ c({
|
|
|
302
354
|
}), p(t);
|
|
303
355
|
};
|
|
304
356
|
//#endregion
|
|
305
|
-
export {
|
|
357
|
+
export { R as a, V as i, Z as n, P as o, G as r, N as s, Q as t };
|
package/package.json
CHANGED
package/src/components.css
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
/* Package-owned typography keeps controls consistent across consuming apps. */
|
|
6
6
|
.fg-button, .fg-input, .fg-select, .fg-checkbox, .fg-field,
|
|
7
7
|
.fg-radio-card, .fg-badge, .fg-alert, .fg-surface, .fg-card,
|
|
8
|
-
.fg-dialog__content, .fg-code-block, .fg-toggle-button, .fg-switch {
|
|
8
|
+
.fg-dialog__content, .fg-code-block, .fg-toggle-button, .fg-switch, .fg-segmented {
|
|
9
9
|
font-family: var(--font-ui);
|
|
10
10
|
font-size: var(--text-md);
|
|
11
11
|
font-weight: var(--weight-regular);
|
|
@@ -172,7 +172,8 @@
|
|
|
172
172
|
.fg-select:disabled,
|
|
173
173
|
.fg-checkbox[data-disabled="true"],
|
|
174
174
|
.fg-switch[data-disabled="true"],
|
|
175
|
-
.fg-toggle-button:disabled
|
|
175
|
+
.fg-toggle-button:disabled,
|
|
176
|
+
.fg-segmented__item:disabled {
|
|
176
177
|
cursor: not-allowed;
|
|
177
178
|
opacity: 0.58;
|
|
178
179
|
}
|
|
@@ -721,6 +722,50 @@
|
|
|
721
722
|
.fg-toggle-button:hover:not(:disabled, [aria-pressed="true"]) { border-color: var(--color-border); }
|
|
722
723
|
.fg-toggle-button[aria-pressed="true"] { border-color: var(--color-accent); }
|
|
723
724
|
|
|
725
|
+
/* Segmented control: one pressed choice on a muted track, so it reads as a raised thumb in both themes. */
|
|
726
|
+
.fg-segmented {
|
|
727
|
+
--fg-segmented-item: var(--control-md);
|
|
728
|
+
/* The thumb is lighter than the track in both themes; the dark raised surface is darker than the track. */
|
|
729
|
+
--fg-segmented-thumb: light-dark(var(--color-row-selected), color-mix(in srgb, var(--color-text) 10%, var(--color-surface-muted)));
|
|
730
|
+
display: inline-flex;
|
|
731
|
+
flex: none;
|
|
732
|
+
/* The fill alone marks the track. The transparent border keeps its size, and forced colors draw it. */
|
|
733
|
+
border: 1px solid transparent;
|
|
734
|
+
border-radius: var(--radius-control);
|
|
735
|
+
background: var(--color-surface-muted);
|
|
736
|
+
}
|
|
737
|
+
.fg-segmented[data-size="sm"] { --fg-segmented-item: var(--control-sm); font-size: var(--text-sm); }
|
|
738
|
+
.fg-segmented[data-size="lg"] { --fg-segmented-item: var(--control-lg); font-size: var(--text-lg); }
|
|
739
|
+
.fg-segmented__item {
|
|
740
|
+
position: relative;
|
|
741
|
+
isolation: isolate;
|
|
742
|
+
display: inline-flex;
|
|
743
|
+
gap: var(--space-2);
|
|
744
|
+
min-height: var(--fg-segmented-item);
|
|
745
|
+
align-items: center;
|
|
746
|
+
justify-content: center;
|
|
747
|
+
padding: 0 var(--space-3);
|
|
748
|
+
border: 0;
|
|
749
|
+
border-radius: var(--radius-control);
|
|
750
|
+
color: var(--color-muted);
|
|
751
|
+
background: transparent;
|
|
752
|
+
font: inherit;
|
|
753
|
+
cursor: pointer;
|
|
754
|
+
}
|
|
755
|
+
.fg-segmented[data-icon-only="true"] .fg-segmented__item { width: var(--fg-segmented-item); padding: 0; }
|
|
756
|
+
/* The thumb is inset inside each full-size button, so it floats on the track and the hit target keeps its size. */
|
|
757
|
+
.fg-segmented__item::before { content: ""; position: absolute; inset: 2px; z-index: -1; border-radius: var(--radius-inline); }
|
|
758
|
+
.fg-segmented__item:hover:not(:disabled, [aria-pressed="true"]) { color: var(--color-text); }
|
|
759
|
+
.fg-segmented__item:hover:not(:disabled, [aria-pressed="true"])::before { background: color-mix(in srgb, var(--fg-segmented-thumb) 45%, transparent); }
|
|
760
|
+
/* The ring gives the pressed choice 3:1 against the track in both themes (WCAG 1.4.11). */
|
|
761
|
+
.fg-segmented__item[aria-pressed="true"] { color: var(--color-text); }
|
|
762
|
+
/* Drawn inside the button, the ring hugs the thumb instead of reaching the next choice. */
|
|
763
|
+
.fg-segmented .fg-segmented__item:focus-visible { outline-offset: -2px; }
|
|
764
|
+
.fg-segmented__item[aria-pressed="true"]::before {
|
|
765
|
+
background: var(--fg-segmented-thumb);
|
|
766
|
+
box-shadow: inset 0 0 0 1px var(--color-border);
|
|
767
|
+
}
|
|
768
|
+
|
|
724
769
|
.fg-switch { display: inline-flex; align-items: center; gap: var(--space-2); min-width: 0; }
|
|
725
770
|
.fg-switch__control {
|
|
726
771
|
display: inline-flex;
|
|
@@ -943,6 +988,7 @@
|
|
|
943
988
|
.fg-dialog__close:focus-visible,
|
|
944
989
|
.fg-dialog__content:focus-visible,
|
|
945
990
|
.fg-toggle-button:focus-visible,
|
|
991
|
+
.fg-segmented__item:focus-visible,
|
|
946
992
|
.fg-switch__control:focus-visible .fg-switch__track {
|
|
947
993
|
outline: 2px solid var(--color-focus);
|
|
948
994
|
outline-offset: 2px;
|
|
@@ -979,6 +1025,9 @@
|
|
|
979
1025
|
}
|
|
980
1026
|
|
|
981
1027
|
@media (forced-colors: active) {
|
|
1028
|
+
/* Forced colors drop the fill and the ring, so the pressed choice takes the system highlight. */
|
|
1029
|
+
.fg-segmented__item[aria-pressed="true"] { forced-color-adjust: none; color: HighlightText; }
|
|
1030
|
+
.fg-segmented__item[aria-pressed="true"]::before { forced-color-adjust: none; background: Highlight; }
|
|
982
1031
|
.fg-switch__track { border-color: ButtonText; background: Canvas; }
|
|
983
1032
|
.fg-switch__track::after { background: ButtonText; }
|
|
984
1033
|
.fg-switch__control[aria-checked="true"] .fg-switch__track { border-color: Highlight; background: Highlight; forced-color-adjust: none; }
|
package/src/site.css
CHANGED
|
@@ -224,48 +224,15 @@
|
|
|
224
224
|
.fg-site-nav a[aria-current="location"] { box-shadow: inset 2px 0 0 var(--color-project); color: var(--color-text); font-weight: var(--weight-medium); }
|
|
225
225
|
.fg-site-nav a code { font-family: var(--font-mono); font-size: var(--text-sm); }
|
|
226
226
|
|
|
227
|
-
.
|
|
228
|
-
display: inline-flex;
|
|
229
|
-
flex: none;
|
|
230
|
-
border: 1px solid var(--color-border-subtle);
|
|
231
|
-
border-radius: var(--radius-control);
|
|
232
|
-
/* A muted track, so the pressed choice reads as a raised thumb in both themes. */
|
|
233
|
-
background: var(--color-surface-muted);
|
|
234
|
-
}
|
|
235
|
-
.fg-site-appearance__choice {
|
|
236
|
-
display: inline-flex;
|
|
237
|
-
width: var(--control-lg);
|
|
238
|
-
min-height: var(--control-lg);
|
|
239
|
-
align-items: center;
|
|
240
|
-
justify-content: center;
|
|
241
|
-
padding: 0;
|
|
242
|
-
border: 0;
|
|
243
|
-
color: var(--color-muted);
|
|
244
|
-
background: transparent;
|
|
245
|
-
font: inherit;
|
|
246
|
-
cursor: pointer;
|
|
247
|
-
}
|
|
248
|
-
.fg-site-appearance__choice + .fg-site-appearance__choice { border-left: 1px solid var(--color-border-subtle); }
|
|
249
|
-
.fg-site-appearance__choice:first-child { border-radius: var(--radius-control) 0 0 var(--radius-control); }
|
|
250
|
-
.fg-site-appearance__choice:last-child { border-radius: 0 var(--radius-control) var(--radius-control) 0; }
|
|
251
|
-
.fg-site-appearance__choice:hover { color: var(--color-text); background: var(--color-row-hover); }
|
|
252
|
-
/* The ring gives the pressed choice 3:1 against the track in both themes (WCAG 1.4.11). */
|
|
253
|
-
.fg-site-appearance__choice[aria-pressed="true"] {
|
|
254
|
-
color: var(--color-text);
|
|
255
|
-
background: var(--color-row-selected);
|
|
256
|
-
box-shadow: inset 0 0 0 1px var(--color-border);
|
|
257
|
-
}
|
|
258
|
-
/* Forced colors drop the fill and the ring, so the pressed choice takes the system highlight. */
|
|
227
|
+
/* Forced colors drop the inset marker, so the current link takes a system border. */
|
|
259
228
|
@media (forced-colors: active) {
|
|
260
229
|
.fg-site-nav a[aria-current] { border-inline-start: 2px solid Highlight; }
|
|
261
|
-
.fg-site-appearance__choice[aria-pressed="true"] { forced-color-adjust: none; color: HighlightText; background: Highlight; }
|
|
262
230
|
}
|
|
263
231
|
|
|
264
232
|
/* Focus is a 2px outline outside the control, which forced-colors mode keeps. An
|
|
265
233
|
* inset ring is used only where a scrolling ancestor would clip an outer one. */
|
|
266
234
|
.fg-site-header a:focus-visible,
|
|
267
|
-
.fg-site-projects__trigger:focus-visible
|
|
268
|
-
.fg-site-appearance__choice:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
|
|
235
|
+
.fg-site-projects__trigger:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
|
|
269
236
|
/* Inset: the desktop rail and the phone drawer scroll. */
|
|
270
237
|
.fg-site-nav a:focus-visible { outline: 2px solid var(--color-focus); outline-offset: -2px; }
|
|
271
238
|
|