@filipgutica/ui 1.8.1 → 1.10.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 +72 -14
- package/dist/index.js +1 -1
- package/dist/site.js +5 -5
- package/dist/{use-active-section-qEJQS1S9.js → use-active-section-DCS_wyYq.js} +59 -21
- package/package.json +1 -1
- package/src/components/tabs.css +9 -0
- package/src/components.css +45 -45
- package/src/site.css +196 -5
- package/src/theme.css +2 -0
- package/src/themes/graphite-indigo.css +3 -3
package/README.md
CHANGED
|
@@ -50,9 +50,10 @@ cancelable `closeAutoFocus` event and focus that heading.
|
|
|
50
50
|
|
|
51
51
|
`UiTabs` renders every labelled panel during SSR and initial hydration. After
|
|
52
52
|
mounting, it adds keyboard-accessible tabs and hides inactive panels without
|
|
53
|
-
unmounting them.
|
|
54
|
-
the
|
|
55
|
-
|
|
53
|
+
unmounting them. A tab strip narrower than its tabs scrolls, fades each clipped
|
|
54
|
+
edge, and keeps the selected tab in view when it resizes. Use unique item values
|
|
55
|
+
and keep page anchor headings outside the panels. Re-align an initial hash after
|
|
56
|
+
layout settles if enhancement changes the page height.
|
|
56
57
|
|
|
57
58
|
Track page sections from a component's setup function:
|
|
58
59
|
|
|
@@ -68,7 +69,10 @@ The returned readonly ref contains the last supplied heading above the root's
|
|
|
68
69
|
CSS `scroll-padding-top` inset, or the final section at the document bottom.
|
|
69
70
|
IDs must remain stable and in page order; missing elements are ignored after
|
|
70
71
|
mounting. Bind matching links to `aria-current="location"`. Scrolling, resizing,
|
|
71
|
-
layout changes, completed transitions, and restored pages update the value.
|
|
72
|
+
layout changes, completed transitions, and restored pages update the value. After
|
|
73
|
+
a jump to a section, through a `#id` link, a hash change, or a deep link, that
|
|
74
|
+
section stays current until the reader scrolls away from where the jump lands, so
|
|
75
|
+
a page too short to bring it to the top still marks it.
|
|
72
76
|
The composable does not change focus, the URL, or browser history, and removes
|
|
73
77
|
its listeners and observer when the component unmounts. During SSR it returns
|
|
74
78
|
the first supplied ID without accessing browser globals.
|
|
@@ -122,8 +126,9 @@ import { UiSiteHeader } from '@filipgutica/ui/site'
|
|
|
122
126
|
|
|
123
127
|
`project` is `wtree`, `annoterm`, `devps`, `workbench`, `filip-stack`, or `ui`. The project
|
|
124
128
|
menu is a native disclosure that works without JavaScript; Escape closes it and
|
|
125
|
-
returns focus to its button.
|
|
126
|
-
|
|
129
|
+
returns focus to its button. Inside `.fg-site-docs`, at 640px and below, the
|
|
130
|
+
header hides `links` so it fits one row, so repeat those destinations in the footer. Without a
|
|
131
|
+
default slot the header renders a System, Light, and Dark picker. A page with its own appearance control passes it
|
|
127
132
|
in the default slot and uses `useSiteAppearance({ applyToRoot: false })` when it
|
|
128
133
|
owns the root element.
|
|
129
134
|
|
|
@@ -167,8 +172,9 @@ import read from './captures/read.html?raw'
|
|
|
167
172
|
`aria-current="location"`, a text-only marker. An item with `current: true` gets
|
|
168
173
|
`aria-current="page"`, the selected fill and accent bar; `code: true` shows the
|
|
169
174
|
label in the monospace font. The page grid places the rail, which stays in view
|
|
170
|
-
on desktop. At 800px and below it is a native
|
|
171
|
-
interactive, then a drawer. The
|
|
175
|
+
on desktop. At 800px and below it is a native disclosure until the page is
|
|
176
|
+
interactive, then a drawer. The disclosure, the drawer button, and the drawer
|
|
177
|
+
title all show `label`. The drawer closes on navigation and focuses the
|
|
172
178
|
destination section, and focus follows the visible control across the
|
|
173
179
|
breakpoint.
|
|
174
180
|
|
|
@@ -180,9 +186,11 @@ focus returns to the button on close. Phones show the button as an icon. `v-mode
|
|
|
180
186
|
holds the active ID and defaults to the first item. Each capture has the ID
|
|
181
187
|
`idPrefix` + `id` (`frame-` by default), so a deep link such as `#frame-read`
|
|
182
188
|
selects its tab on load and on hash change. Without JavaScript every capture is
|
|
183
|
-
listed under its own heading and scrolls at full size.
|
|
184
|
-
|
|
185
|
-
the
|
|
189
|
+
listed under its own heading and scrolls at full size. Captures use a dark
|
|
190
|
+
terminal palette for the `.term` root and the converter's ANSI classes (`.tf0`
|
|
191
|
+
to `.tf15`, `.tb0` to `.tb15`, `.tf-dim`, `.tbold`, and the others). To change
|
|
192
|
+
it, set `--site-capture-bg`, `--t-bg`, `--t-fg`, `--t-dim`, or `--t0` to `--t15`
|
|
193
|
+
on `:root`, because the dialog renders outside the panel.
|
|
186
194
|
|
|
187
195
|
`UiCommandList` renders a table of monospace commands and descriptions. Use the
|
|
188
196
|
`command` slot to show a key as `<kbd>`, the `description` slot for `<kbd>` or
|
|
@@ -194,9 +202,59 @@ description and wraps.
|
|
|
194
202
|
|
|
195
203
|
`site.css` also includes page helpers: `.fg-site-steps` for an ordered list with
|
|
196
204
|
numbered circles, `.fg-site-facts` for an inline `dl` of short label and value
|
|
197
|
-
pairs
|
|
198
|
-
|
|
199
|
-
|
|
205
|
+
pairs whose links get a `--control-lg` hit area at 640px and below,
|
|
206
|
+
`.fg-site-definitions` for a two-column `dl` of `dt` and `dd` that stacks on
|
|
207
|
+
phones and keeps `code` such as `--all` on one line, `.fg-site-sr-only` for
|
|
208
|
+
visually hidden text, and `.fg-site-skip` for a skip link that appears on focus.
|
|
209
|
+
|
|
210
|
+
### Docs shell
|
|
211
|
+
|
|
212
|
+
Add `fg-site-docs` to the element that wraps a project page's header, rail,
|
|
213
|
+
main content, and footer. The shell then supplies:
|
|
214
|
+
|
|
215
|
+
- the frame: the header across the top, the `--sidebar` rail beside `main`, and
|
|
216
|
+
the footer on the frame edges. At 800px and below the rail stacks above `main`.
|
|
217
|
+
- element defaults inside the shell, plus the page background and font on
|
|
218
|
+
`body`: box sizing, heading sizes and margins, paragraph measure, links,
|
|
219
|
+
inline `code` at `--text-sm`, `kbd`, a 2px focus outline, and a `[hidden]`
|
|
220
|
+
rule that outranks the page's own `display` rules.
|
|
221
|
+
- `.fg-site-footer` for the footer and `.fg-site-legend` for a `dl` that explains
|
|
222
|
+
what a capture shows. Legend columns are at least `--site-legend-column` wide,
|
|
223
|
+
`--sidebar` by default; set it on the legend to fit more entries in a row.
|
|
224
|
+
|
|
225
|
+
```vue
|
|
226
|
+
<template>
|
|
227
|
+
<div class="fg-site-docs">
|
|
228
|
+
<UiSiteHeader project="devps" />
|
|
229
|
+
<UiSiteNav label="On this page" :groups="navigation" />
|
|
230
|
+
<main id="main">
|
|
231
|
+
<section aria-labelledby="title">…</section>
|
|
232
|
+
<dl class="fg-site-legend">
|
|
233
|
+
<div><dt>PORTS</dt><dd>The ports the server listens on.</dd></div>
|
|
234
|
+
</dl>
|
|
235
|
+
</main>
|
|
236
|
+
<footer class="fg-site-footer">
|
|
237
|
+
<a href="https://github.com/filipgutica">Built by Filip Gutica</a>
|
|
238
|
+
<nav aria-label="Project links">
|
|
239
|
+
<a href="https://github.com/filipgutica/devps/releases">Releases</a>
|
|
240
|
+
</nav>
|
|
241
|
+
</footer>
|
|
242
|
+
</div>
|
|
243
|
+
</template>
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
The header, rail, `main`, and footer must be direct children of the shell. The
|
|
247
|
+
element defaults sit in the `base` cascade layer, so library components and the
|
|
248
|
+
site's own rules win. That holds only when the site declares the layer order
|
|
249
|
+
before importing `site.css`: `@import "tailwindcss"` does this, or start the
|
|
250
|
+
stylesheet with `@layer base, components, utilities;`. To adopt the shell, delete
|
|
251
|
+
the site's own frame, element base, `kbd`, footer, legend, and ANSI palette
|
|
252
|
+
rules. Without `fg-site-docs`, the frame, element defaults, and phone header
|
|
253
|
+
rules do not apply. These apply on every page: the `fg-site-footer` and
|
|
254
|
+
`fg-site-legend` classes wherever a page uses them; the capture terminal palette
|
|
255
|
+
for every `UiCapture`, in the `components` layer, so a site's own unlayered
|
|
256
|
+
`.term` and ANSI rules and its `--t*` values still win; and `UiSiteNav`, whose
|
|
257
|
+
phone toggle and drawer title now show its `label`.
|
|
200
258
|
|
|
201
259
|
## Development
|
|
202
260
|
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as e, i as t, n, o as r, r as i, t as a } from "./use-active-section-
|
|
1
|
+
import { a as e, i as t, n, o as r, r as i, t as a } from "./use-active-section-DCS_wyYq.js";
|
|
2
2
|
import { Fragment as o, computed as s, createBlock as c, createCommentVNode as l, createElementBlock as u, createElementVNode as d, createTextVNode as f, createVNode as p, defineComponent as m, inject as h, mergeModels as g, mergeProps as _, normalizeStyle as v, openBlock as y, provide as b, ref as ee, renderList as x, renderSlot as S, resolveDynamicComponent as C, shallowRef as te, toDisplayString as w, unref as T, useId as E, useModel as ne, useSlots as D, watch as re, withCtx as O } from "vue";
|
|
3
3
|
import { CheckboxIndicator as k, CheckboxRoot as A, Primitive as j, ProgressIndicator as M, ProgressRoot as N, RadioGroupItem as P, RadioGroupRoot as F, SliderRange as I, SliderRoot as L, SliderThumb as R, SliderTrack as z, Toggle as B } from "reka-ui";
|
|
4
4
|
//#region src/components/UiCard.vue?vue&type=script&setup=true&lang.ts
|
package/dist/site.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as e, i as t, n, o as r, r as i, t as a } from "./use-active-section-
|
|
1
|
+
import { a as e, i as t, n, o as r, r as i, t as a } from "./use-active-section-DCS_wyYq.js";
|
|
2
2
|
import { Fragment as o, computed as s, createBlock as c, createCommentVNode as l, createElementBlock as u, createElementVNode as d, createTextVNode as f, createVNode as p, defineComponent as m, mergeModels as h, nextTick as g, normalizeClass as _, normalizeStyle as v, onBeforeUnmount as y, onMounted as b, onUnmounted as x, openBlock as S, ref as C, renderList as w, renderSlot as T, shallowRef as E, toDisplayString as D, unref as O, useId as k, useModel as ee, useSlots as A, useTemplateRef as te, watch as j, withCtx as M } from "vue";
|
|
3
3
|
import { tryOnMounted as N, usePreferredDark as P, useStorage as F } from "@vueuse/core";
|
|
4
4
|
//#region src/site/appearance.ts
|
|
@@ -250,7 +250,7 @@ var I = "tool-site-theme", L = (e) => e === "system" || e === "light" || e === "
|
|
|
250
250
|
}, [d("summary", {
|
|
251
251
|
class: "fg-site-rail__summary",
|
|
252
252
|
"aria-controls": O(t)
|
|
253
|
-
},
|
|
253
|
+
}, D(e.label), 9, pe), p(Z, {
|
|
254
254
|
"content-id": O(t),
|
|
255
255
|
label: e.label,
|
|
256
256
|
groups: e.groups,
|
|
@@ -264,7 +264,7 @@ var I = "tool-site-theme", L = (e) => e === "system" || e === "light" || e === "
|
|
|
264
264
|
key: 1,
|
|
265
265
|
open: l.value,
|
|
266
266
|
"onUpdate:open": h[0] ||= (e) => l.value = e,
|
|
267
|
-
title:
|
|
267
|
+
title: e.label,
|
|
268
268
|
onCloseAutoFocus: E
|
|
269
269
|
}, {
|
|
270
270
|
trigger: M(() => [p(r, {
|
|
@@ -272,7 +272,7 @@ var I = "tool-site-theme", L = (e) => e === "system" || e === "light" || e === "
|
|
|
272
272
|
size: "lg",
|
|
273
273
|
class: "fg-site-rail__toggle"
|
|
274
274
|
}, {
|
|
275
|
-
default: M(() => [
|
|
275
|
+
default: M(() => [f(D(e.label), 1)]),
|
|
276
276
|
_: 1
|
|
277
277
|
})]),
|
|
278
278
|
default: M(() => [p(Z, {
|
|
@@ -288,7 +288,7 @@ var I = "tool-site-theme", L = (e) => e === "system" || e === "light" || e === "
|
|
|
288
288
|
"active-id"
|
|
289
289
|
])]),
|
|
290
290
|
_: 1
|
|
291
|
-
}, 8, ["open"]))], 8, de));
|
|
291
|
+
}, 8, ["open", "title"]))], 8, de));
|
|
292
292
|
}
|
|
293
293
|
}), ge = [
|
|
294
294
|
"aria-label",
|
|
@@ -154,7 +154,7 @@ var N = /* @__PURE__ */ c({
|
|
|
154
154
|
_: 3
|
|
155
155
|
}, 8, ["open"]));
|
|
156
156
|
}
|
|
157
|
-
}), H = { class: "fg-tabs" }, U = ["aria-label"], W = [
|
|
157
|
+
}), H = { class: "fg-tabs" }, U = ["aria-label", "data-clipped"], W = [
|
|
158
158
|
"id",
|
|
159
159
|
"aria-controls",
|
|
160
160
|
"aria-selected",
|
|
@@ -180,16 +180,34 @@ var N = /* @__PURE__ */ c({
|
|
|
180
180
|
u(() => {
|
|
181
181
|
l.value = !0;
|
|
182
182
|
});
|
|
183
|
-
let C = b("list")
|
|
184
|
-
x([l, d], () => {
|
|
183
|
+
let C = b("list"), w = () => {
|
|
185
184
|
let e = C.value, t = e?.querySelector("[aria-selected=\"true\"]");
|
|
186
185
|
if (!e || !t) return;
|
|
187
|
-
let n = e.getBoundingClientRect(), { left:
|
|
188
|
-
|
|
189
|
-
},
|
|
190
|
-
|
|
186
|
+
let n = e.getBoundingClientRect(), r = getComputedStyle(e), i = n.left + (Number.parseFloat(r.scrollPaddingLeft) || 0), a = n.right - (Number.parseFloat(r.scrollPaddingRight) || 0), { left: o, right: s } = t.getBoundingClientRect();
|
|
187
|
+
o < i ? e.scrollLeft -= i - o : s > a && (e.scrollLeft += s - a);
|
|
188
|
+
}, T = m(), E = () => {
|
|
189
|
+
let e = C.value;
|
|
190
|
+
if (!e) return;
|
|
191
|
+
let t = e.scrollWidth - e.clientWidth, n = getComputedStyle(e).direction === "rtl" ? e.scrollLeft + t : e.scrollLeft, r = n > 1, i = n < t - 1;
|
|
192
|
+
T.value = r && i ? "both" : r ? "left" : i ? "right" : void 0;
|
|
193
|
+
}, D = () => {
|
|
194
|
+
w(), E();
|
|
195
|
+
};
|
|
196
|
+
x([
|
|
197
|
+
l,
|
|
198
|
+
d,
|
|
199
|
+
() => n.items
|
|
200
|
+
], D, {
|
|
201
|
+
flush: "post",
|
|
202
|
+
deep: !0
|
|
203
|
+
}), x(C, (e, t, n) => {
|
|
204
|
+
if (!e || typeof ResizeObserver > "u") return;
|
|
205
|
+
let r = new ResizeObserver(D);
|
|
206
|
+
r.observe(e), n(() => r.disconnect());
|
|
207
|
+
});
|
|
208
|
+
let O = (e) => {
|
|
191
209
|
e !== d.value && s("update:modelValue", e);
|
|
192
|
-
},
|
|
210
|
+
}, k = (e) => {
|
|
193
211
|
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey || ![
|
|
194
212
|
"ArrowLeft",
|
|
195
213
|
"ArrowRight",
|
|
@@ -213,7 +231,9 @@ var N = /* @__PURE__ */ c({
|
|
|
213
231
|
class: "fg-tabs__list",
|
|
214
232
|
role: "tablist",
|
|
215
233
|
"aria-label": n.label,
|
|
216
|
-
|
|
234
|
+
"data-clipped": T.value,
|
|
235
|
+
onKeydown: k,
|
|
236
|
+
onScrollPassive: E
|
|
217
237
|
}, [(f(!0), i(e, null, h(n.items, (e) => (f(), i("button", {
|
|
218
238
|
id: p(e.value),
|
|
219
239
|
key: e.value,
|
|
@@ -223,8 +243,8 @@ var N = /* @__PURE__ */ c({
|
|
|
223
243
|
"aria-controls": v(e.value),
|
|
224
244
|
"aria-selected": e.value === d.value,
|
|
225
245
|
tabindex: e.value === d.value ? 0 : -1,
|
|
226
|
-
onClick: (t) =>
|
|
227
|
-
onFocus: (t) =>
|
|
246
|
+
onClick: (t) => O(e.value),
|
|
247
|
+
onFocus: (t) => O(e.value)
|
|
228
248
|
}, _(e.label), 41, W))), 128))], 40, U)) : r("", !0), (f(!0), i(e, null, h(n.items, (e) => (f(), i("section", {
|
|
229
249
|
id: v(e.value),
|
|
230
250
|
key: e.value,
|
|
@@ -248,17 +268,35 @@ var N = /* @__PURE__ */ c({
|
|
|
248
268
|
id: e,
|
|
249
269
|
element: t
|
|
250
270
|
}] : [];
|
|
251
|
-
}), o = () => {
|
|
252
|
-
n = void 0
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
271
|
+
}), o = document.documentElement, s = () => Number.parseFloat(getComputedStyle(o).scrollPaddingTop) || 0, c, l = () => {
|
|
272
|
+
if (n = void 0, c) {
|
|
273
|
+
let e = Math.abs(window.scrollY - c.landing);
|
|
274
|
+
e > c.closest + 2 ? c = void 0 : c.closest = Math.min(c.closest, e);
|
|
275
|
+
}
|
|
276
|
+
let e = s(), r = a[0]?.id;
|
|
277
|
+
for (let t of a) t.element.getBoundingClientRect().top <= e + 1 && (r = t.id);
|
|
278
|
+
window.scrollY > 0 && window.scrollY + window.innerHeight >= o.scrollHeight - 2 && (r = a.at(-1)?.id), t.value = c?.id ?? r;
|
|
279
|
+
}, u = () => {
|
|
280
|
+
n === void 0 && (n = requestAnimationFrame(l));
|
|
281
|
+
}, d = (e) => {
|
|
282
|
+
let t = a.find((t) => t.id === e);
|
|
283
|
+
if (c = void 0, t) {
|
|
284
|
+
let n = Math.max(0, o.scrollHeight - window.innerHeight), r = window.scrollY + t.element.getBoundingClientRect().top - s(), i = Math.min(Math.max(r, 0), n);
|
|
285
|
+
c = {
|
|
286
|
+
id: e,
|
|
287
|
+
landing: i,
|
|
288
|
+
closest: Math.abs(window.scrollY - i)
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
u();
|
|
292
|
+
}, f = () => d(location.hash.slice(1)), p = (e) => {
|
|
293
|
+
if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
|
|
294
|
+
let t = e.target instanceof Element ? e.target.closest("a[href^=\"#\"]")?.getAttribute("href") : void 0;
|
|
295
|
+
t && d(t.slice(1));
|
|
258
296
|
};
|
|
259
|
-
window.addEventListener("scroll",
|
|
260
|
-
window.removeEventListener("scroll",
|
|
261
|
-
},
|
|
297
|
+
window.addEventListener("scroll", u, { passive: !0 }), window.addEventListener("resize", u), window.addEventListener("pageshow", u), window.addEventListener("hashchange", f), document.addEventListener("click", p), document.body.addEventListener("transitionend", u), typeof ResizeObserver < "u" && (r = new ResizeObserver(u), r.observe(document.body)), i = () => {
|
|
298
|
+
window.removeEventListener("scroll", u), window.removeEventListener("resize", u), window.removeEventListener("pageshow", u), window.removeEventListener("hashchange", f), document.removeEventListener("click", p), document.body.removeEventListener("transitionend", u);
|
|
299
|
+
}, location.hash && f(), l();
|
|
262
300
|
}), d(() => {
|
|
263
301
|
i?.(), r?.disconnect(), n !== void 0 && cancelAnimationFrame(n);
|
|
264
302
|
}), p(t);
|
package/package.json
CHANGED
package/src/components/tabs.css
CHANGED
|
@@ -12,10 +12,19 @@
|
|
|
12
12
|
width: max-content;
|
|
13
13
|
max-width: 100%;
|
|
14
14
|
overflow-x: auto;
|
|
15
|
+
scroll-padding-inline: var(--space-6);
|
|
15
16
|
margin-block-end: var(--space-4);
|
|
16
17
|
border-bottom: 1px solid var(--color-border-subtle);
|
|
17
18
|
}
|
|
18
19
|
|
|
20
|
+
/* A strip that scrolls fades each clipped edge; the scroll padding keeps a revealed tab clear
|
|
21
|
+
* of the fade. Mask stops are alpha only: #000 keeps a pixel and transparent hides it. */
|
|
22
|
+
.fg-tabs__list[data-clipped="right"] { mask-image: linear-gradient(to right, #000 calc(100% - var(--space-6)), transparent); }
|
|
23
|
+
.fg-tabs__list[data-clipped="left"] { mask-image: linear-gradient(to left, #000 calc(100% - var(--space-6)), transparent); }
|
|
24
|
+
.fg-tabs__list[data-clipped="both"] {
|
|
25
|
+
mask-image: linear-gradient(to right, transparent, #000 var(--space-6), #000 calc(100% - var(--space-6)), transparent);
|
|
26
|
+
}
|
|
27
|
+
|
|
19
28
|
.fg-tabs__tab {
|
|
20
29
|
flex: none;
|
|
21
30
|
min-height: var(--control-md);
|
package/src/components.css
CHANGED
|
@@ -24,16 +24,16 @@
|
|
|
24
24
|
.fg-code-block__header {
|
|
25
25
|
display: flex;
|
|
26
26
|
align-items: center;
|
|
27
|
-
gap:
|
|
27
|
+
gap: var(--space-3);
|
|
28
28
|
min-height: 2.5rem;
|
|
29
|
-
padding: 0.35rem
|
|
29
|
+
padding: 0.35rem var(--space-3);
|
|
30
30
|
border-bottom: 1px solid color-mix(in srgb, var(--color-code-text) 16%, transparent);
|
|
31
31
|
background: color-mix(in srgb, var(--color-code-text) 5%, var(--color-code));
|
|
32
|
-
font-size:
|
|
32
|
+
font-size: var(--text-xs);
|
|
33
33
|
}
|
|
34
34
|
.fg-code-block__title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
|
|
35
35
|
.fg-code-block__language { opacity: 0.7; }
|
|
36
|
-
.fg-code-block__actions { display: flex; align-items: center; gap:
|
|
36
|
+
.fg-code-block__actions { display: flex; align-items: center; gap: var(--space-2); margin-left: auto; flex-shrink: 0; }
|
|
37
37
|
.fg-code-block__copy {
|
|
38
38
|
display: inline-flex;
|
|
39
39
|
align-items: center;
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
gap: 0.4rem;
|
|
42
42
|
min-width: var(--control-lg);
|
|
43
43
|
min-height: var(--control-lg);
|
|
44
|
-
padding:
|
|
44
|
+
padding: var(--space-1) 0.4rem;
|
|
45
45
|
border: 0;
|
|
46
|
-
border-radius:
|
|
46
|
+
border-radius: var(--radius-inline);
|
|
47
47
|
background: transparent;
|
|
48
48
|
color: inherit;
|
|
49
49
|
font: inherit;
|
|
@@ -54,15 +54,15 @@
|
|
|
54
54
|
/* Inset: the code block clips its content. */
|
|
55
55
|
.fg-code-block__copy:focus-visible, .fg-code-block__pre:focus-visible { outline: 2px solid var(--color-focus); outline-offset: -2px; }
|
|
56
56
|
.fg-figure__plate:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
|
|
57
|
-
.fg-code-block__pre { margin: 0; padding:
|
|
58
|
-
.fg-code-block__pre, .fg-code-block__pre code { font-family: var(--font-mono); font-size:
|
|
57
|
+
.fg-code-block__pre { margin: 0; padding: var(--space-4); overflow: auto; max-height: 32rem; tab-size: 2; }
|
|
58
|
+
.fg-code-block__pre, .fg-code-block__pre code { font-family: var(--font-mono); font-size: var(--text-sm); line-height: 1.65; }
|
|
59
59
|
.fg-code-block__pre code { display: block; color: inherit; }
|
|
60
60
|
.fg-code-block__line { display: flex; min-height: 1.65em; }
|
|
61
61
|
.fg-code-block__text { white-space: pre; }
|
|
62
62
|
.fg-code-block__number { min-width: 2.5em; padding-right: 1em; flex-shrink: 0; text-align: right; opacity: 0.5; user-select: none; }
|
|
63
63
|
.fg-code-block[data-wrap="true"] .fg-code-block__text { min-width: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
64
64
|
.fg-code-block__status:empty { display: none; }
|
|
65
|
-
.fg-code-block__status:not(:empty) { display: block; padding:
|
|
65
|
+
.fg-code-block__status:not(:empty) { display: block; padding: var(--space-2) var(--space-3); font-size: var(--text-xs); }
|
|
66
66
|
.fg-code-block[data-variant="compact"] {
|
|
67
67
|
position: relative;
|
|
68
68
|
display: grid;
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
display: inline-flex;
|
|
123
123
|
align-items: center;
|
|
124
124
|
justify-content: center;
|
|
125
|
-
gap:
|
|
125
|
+
gap: var(--space-2);
|
|
126
126
|
color: var(--color-button-text);
|
|
127
127
|
background: var(--color-button-bg);
|
|
128
128
|
box-shadow: none;
|
|
@@ -167,19 +167,19 @@
|
|
|
167
167
|
.fg-button[data-size="sm"],
|
|
168
168
|
.fg-input[data-size="sm"],
|
|
169
169
|
.fg-select[data-size="sm"] {
|
|
170
|
-
font-size:
|
|
170
|
+
font-size: var(--text-sm);
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
.fg-button[data-size="md"],
|
|
174
174
|
.fg-input[data-size="md"],
|
|
175
175
|
.fg-select[data-size="md"] {
|
|
176
|
-
font-size:
|
|
176
|
+
font-size: var(--text-md);
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
.fg-button[data-size="lg"],
|
|
180
180
|
.fg-input[data-size="lg"],
|
|
181
181
|
.fg-select[data-size="lg"] {
|
|
182
|
-
font-size:
|
|
182
|
+
font-size: var(--text-lg);
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
.fg-button[data-size="sm"] { min-height: var(--control-sm); }
|
|
@@ -193,20 +193,20 @@
|
|
|
193
193
|
.fg-select[data-size="lg"] { height: var(--control-lg); }
|
|
194
194
|
|
|
195
195
|
.fg-button[data-size="sm"] { padding: 0 0.6rem; }
|
|
196
|
-
.fg-button[data-size="md"] { padding: 0
|
|
197
|
-
.fg-button[data-size="lg"] { padding: 0
|
|
196
|
+
.fg-button[data-size="md"] { padding: 0 var(--space-3); }
|
|
197
|
+
.fg-button[data-size="lg"] { padding: 0 var(--space-4); }
|
|
198
198
|
|
|
199
199
|
/* Deprecated UiButton aliases retained for existing consumers. */
|
|
200
200
|
.fg-button[data-size="compact"] {
|
|
201
201
|
min-height: var(--control-md);
|
|
202
202
|
padding: 0 0.7rem;
|
|
203
|
-
font-size:
|
|
203
|
+
font-size: var(--text-sm);
|
|
204
204
|
}
|
|
205
205
|
|
|
206
206
|
.fg-button[data-size="default"] {
|
|
207
207
|
min-height: var(--control-lg);
|
|
208
|
-
padding: 0
|
|
209
|
-
font-size:
|
|
208
|
+
padding: 0 var(--space-4);
|
|
209
|
+
font-size: var(--text-lg);
|
|
210
210
|
}
|
|
211
211
|
|
|
212
212
|
.fg-button[data-variant="secondary"] {
|
|
@@ -243,7 +243,7 @@
|
|
|
243
243
|
.fg-button[data-variant="text"] {
|
|
244
244
|
height: auto;
|
|
245
245
|
min-height: auto;
|
|
246
|
-
padding:
|
|
246
|
+
padding: var(--space-1);
|
|
247
247
|
color: var(--color-link);
|
|
248
248
|
background: transparent;
|
|
249
249
|
text-decoration: underline;
|
|
@@ -339,7 +339,7 @@
|
|
|
339
339
|
.fg-input[data-size="md"] { padding: 0 0.65rem; }
|
|
340
340
|
.fg-input[data-size="lg"] { padding: 0 0.7rem; }
|
|
341
341
|
|
|
342
|
-
.fg-select[data-size="sm"] { padding: 0 1.6rem 0
|
|
342
|
+
.fg-select[data-size="sm"] { padding: 0 1.6rem 0 var(--space-2); }
|
|
343
343
|
.fg-select[data-size="md"] { padding: 0 1.7rem 0 0.6rem; }
|
|
344
344
|
.fg-select[data-size="lg"] { padding: 0 1.8rem 0 0.7rem; }
|
|
345
345
|
|
|
@@ -361,14 +361,14 @@
|
|
|
361
361
|
|
|
362
362
|
.fg-field__label {
|
|
363
363
|
color: var(--color-text);
|
|
364
|
-
font-size:
|
|
364
|
+
font-size: var(--text-sm);
|
|
365
365
|
font-weight: 600;
|
|
366
366
|
}
|
|
367
367
|
|
|
368
368
|
.fg-field__description,
|
|
369
369
|
.fg-field__error {
|
|
370
370
|
margin: 0;
|
|
371
|
-
font-size:
|
|
371
|
+
font-size: var(--text-sm);
|
|
372
372
|
}
|
|
373
373
|
|
|
374
374
|
.fg-field__description { color: var(--color-muted); }
|
|
@@ -413,21 +413,21 @@
|
|
|
413
413
|
min-height: var(--control-sm);
|
|
414
414
|
align-items: center;
|
|
415
415
|
gap: 0.45rem;
|
|
416
|
-
font-size:
|
|
416
|
+
font-size: var(--text-sm);
|
|
417
417
|
}
|
|
418
418
|
|
|
419
419
|
.fg-checkbox[data-size="md"] {
|
|
420
420
|
min-height: var(--control-md);
|
|
421
421
|
align-items: center;
|
|
422
422
|
gap: 0.55rem;
|
|
423
|
-
font-size:
|
|
423
|
+
font-size: var(--text-md);
|
|
424
424
|
}
|
|
425
425
|
|
|
426
426
|
.fg-checkbox[data-size="lg"] {
|
|
427
427
|
min-height: var(--control-lg);
|
|
428
428
|
align-items: center;
|
|
429
429
|
gap: 0.65rem;
|
|
430
|
-
font-size:
|
|
430
|
+
font-size: var(--text-lg);
|
|
431
431
|
}
|
|
432
432
|
|
|
433
433
|
.fg-checkbox[data-size] .fg-checkbox__control { margin-top: 0; }
|
|
@@ -435,7 +435,7 @@
|
|
|
435
435
|
.fg-checkbox[data-size="sm"] .fg-checkbox__control {
|
|
436
436
|
width: 1rem;
|
|
437
437
|
height: 1rem;
|
|
438
|
-
border-radius:
|
|
438
|
+
border-radius: var(--radius-inline);
|
|
439
439
|
}
|
|
440
440
|
|
|
441
441
|
.fg-checkbox[data-size="md"] .fg-checkbox__control {
|
|
@@ -455,14 +455,14 @@
|
|
|
455
455
|
.fg-radio-card-group {
|
|
456
456
|
display: grid;
|
|
457
457
|
grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
|
|
458
|
-
gap:
|
|
458
|
+
gap: var(--space-3);
|
|
459
459
|
}
|
|
460
460
|
|
|
461
461
|
.fg-radio-card {
|
|
462
462
|
position: relative;
|
|
463
463
|
display: block;
|
|
464
464
|
min-width: 0;
|
|
465
|
-
padding:
|
|
465
|
+
padding: var(--space-3);
|
|
466
466
|
overflow: hidden;
|
|
467
467
|
border: 1px solid var(--color-border-subtle);
|
|
468
468
|
border-radius: var(--radius-panel);
|
|
@@ -493,15 +493,15 @@
|
|
|
493
493
|
.fg-radio-card__content {
|
|
494
494
|
display: grid;
|
|
495
495
|
min-width: 0;
|
|
496
|
-
gap:
|
|
496
|
+
gap: var(--space-1);
|
|
497
497
|
padding-right: 1.75rem;
|
|
498
498
|
}
|
|
499
499
|
|
|
500
500
|
.fg-radio-card__indicator {
|
|
501
501
|
position: absolute;
|
|
502
502
|
z-index: 1;
|
|
503
|
-
top:
|
|
504
|
-
right:
|
|
503
|
+
top: var(--space-3);
|
|
504
|
+
right: var(--space-3);
|
|
505
505
|
display: block;
|
|
506
506
|
width: 1rem;
|
|
507
507
|
height: 1rem;
|
|
@@ -523,7 +523,7 @@
|
|
|
523
523
|
padding: 0.18rem 0.48rem;
|
|
524
524
|
color: var(--color-muted);
|
|
525
525
|
background: var(--color-surface-muted);
|
|
526
|
-
font-size:
|
|
526
|
+
font-size: var(--text-xs);
|
|
527
527
|
font-weight: 500;
|
|
528
528
|
line-height: 1.25;
|
|
529
529
|
}
|
|
@@ -537,8 +537,8 @@
|
|
|
537
537
|
.fg-alert {
|
|
538
538
|
display: flex;
|
|
539
539
|
align-items: flex-start;
|
|
540
|
-
gap:
|
|
541
|
-
padding:
|
|
540
|
+
gap: var(--space-3);
|
|
541
|
+
padding: var(--space-3) var(--space-4);
|
|
542
542
|
border: 1px solid var(--color-border-subtle);
|
|
543
543
|
border-radius: var(--radius-control);
|
|
544
544
|
color: var(--color-text);
|
|
@@ -562,8 +562,8 @@
|
|
|
562
562
|
box-shadow: none;
|
|
563
563
|
}
|
|
564
564
|
|
|
565
|
-
.fg-surface[data-padding="compact"] { padding:
|
|
566
|
-
.fg-surface[data-padding="default"] { padding:
|
|
565
|
+
.fg-surface[data-padding="compact"] { padding: var(--space-3); }
|
|
566
|
+
.fg-surface[data-padding="default"] { padding: var(--space-4); }
|
|
567
567
|
|
|
568
568
|
.fg-card {
|
|
569
569
|
min-width: 0;
|
|
@@ -805,8 +805,8 @@
|
|
|
805
805
|
top: 50%;
|
|
806
806
|
left: 50%;
|
|
807
807
|
display: grid;
|
|
808
|
-
width: min(32rem, calc(100vw -
|
|
809
|
-
max-height: min(42rem, calc(100vh -
|
|
808
|
+
width: min(32rem, calc(100vw - var(--space-8)));
|
|
809
|
+
max-height: min(42rem, calc(100vh - var(--space-8)));
|
|
810
810
|
overflow: hidden;
|
|
811
811
|
transform: translate(-50%, -50%);
|
|
812
812
|
border: 1px solid var(--color-border-subtle);
|
|
@@ -821,8 +821,8 @@
|
|
|
821
821
|
display: flex;
|
|
822
822
|
align-items: flex-start;
|
|
823
823
|
justify-content: space-between;
|
|
824
|
-
gap:
|
|
825
|
-
padding:
|
|
824
|
+
gap: var(--space-4);
|
|
825
|
+
padding: var(--space-4);
|
|
826
826
|
}
|
|
827
827
|
|
|
828
828
|
.fg-dialog__header { border-bottom: 1px solid var(--color-border-subtle); }
|
|
@@ -836,21 +836,21 @@
|
|
|
836
836
|
}
|
|
837
837
|
|
|
838
838
|
.fg-dialog__description {
|
|
839
|
-
margin:
|
|
839
|
+
margin: var(--space-1) 0 0;
|
|
840
840
|
color: var(--color-muted);
|
|
841
|
-
font-size:
|
|
841
|
+
font-size: var(--text-md);
|
|
842
842
|
}
|
|
843
843
|
|
|
844
844
|
.fg-dialog__body {
|
|
845
845
|
min-height: 0;
|
|
846
846
|
overflow: auto;
|
|
847
|
-
padding:
|
|
847
|
+
padding: var(--space-4);
|
|
848
848
|
}
|
|
849
849
|
|
|
850
850
|
.fg-dialog__close {
|
|
851
851
|
display: inline-grid;
|
|
852
852
|
flex: none;
|
|
853
|
-
width:
|
|
853
|
+
width: var(--control-lg);
|
|
854
854
|
min-height: var(--control-lg);
|
|
855
855
|
padding: 0;
|
|
856
856
|
place-items: center;
|
|
@@ -900,7 +900,7 @@
|
|
|
900
900
|
bottom: 0;
|
|
901
901
|
left: 0;
|
|
902
902
|
width: 100%;
|
|
903
|
-
max-height: calc(100vh -
|
|
903
|
+
max-height: calc(100vh - var(--space-4));
|
|
904
904
|
transform: none;
|
|
905
905
|
border-radius: var(--radius-panel) var(--radius-panel) 0 0;
|
|
906
906
|
}
|
package/src/site.css
CHANGED
|
@@ -1,7 +1,120 @@
|
|
|
1
1
|
/* Shared chrome and page helpers for the project sites. Use with
|
|
2
2
|
* @filipgutica/ui/themes/graphite-indigo.css, which supplies the type, space, and
|
|
3
3
|
* page-measure roles this file reads. Nothing here targets site-specific markup. */
|
|
4
|
+
/* Element defaults for a docs page inside .fg-site-docs. They sit in the base layer, so
|
|
5
|
+
* library components and the site's own rules win, as long as the site declares the layer
|
|
6
|
+
* order first (Tailwind's import does, or write @layer base, components, utilities;).
|
|
7
|
+
* Pages without .fg-site-docs get none of them. */
|
|
8
|
+
@layer base {
|
|
9
|
+
html:has(.fg-site-docs) { scroll-padding-top: var(--space-6); }
|
|
10
|
+
body:has(.fg-site-docs) {
|
|
11
|
+
margin: 0;
|
|
12
|
+
background: var(--color-bg);
|
|
13
|
+
color: var(--color-text);
|
|
14
|
+
font: var(--text-md) / var(--leading) var(--font-ui);
|
|
15
|
+
-webkit-font-smoothing: antialiased;
|
|
16
|
+
}
|
|
17
|
+
.fg-site-docs,
|
|
18
|
+
.fg-site-docs *,
|
|
19
|
+
.fg-site-docs *::before,
|
|
20
|
+
.fg-site-docs *::after { box-sizing: border-box; }
|
|
21
|
+
.fg-site-docs :where(h1, h2, h3, p, dl, dd, figure) { margin: 0; }
|
|
22
|
+
.fg-site-docs :where(h1, h2, h3) {
|
|
23
|
+
font-weight: var(--weight-semibold);
|
|
24
|
+
line-height: var(--leading-tight);
|
|
25
|
+
text-wrap: balance;
|
|
26
|
+
}
|
|
27
|
+
.fg-site-docs :where(h1) { max-width: 22ch; font-size: var(--text-3xl); letter-spacing: var(--tracking-tight); }
|
|
28
|
+
.fg-site-docs :where(h2) { font-size: var(--text-xl); }
|
|
29
|
+
.fg-site-docs :where(p) { max-width: var(--measure); }
|
|
30
|
+
/* Tab panels and other enhanced markup use the hidden attribute, so it outranks the page's own
|
|
31
|
+
* display rules. until-found keeps the browser's find-in-page behavior. */
|
|
32
|
+
.fg-site-docs :where([hidden]:not([hidden="until-found"])) { display: none !important; }
|
|
33
|
+
.fg-site-docs :where(code, kbd, pre) { font-family: var(--font-mono); }
|
|
34
|
+
/* Monospace looks larger than the UI face, so inline code steps down: --text-sm in --text-md text.
|
|
35
|
+
* Code inside pre keeps the block's own size. */
|
|
36
|
+
.fg-site-docs :where(:not(pre) > code) { font-size: var(--text-sm); }
|
|
37
|
+
.fg-site-docs :where(a) { color: var(--color-link); text-underline-offset: 0.18em; }
|
|
38
|
+
.fg-site-docs :where(kbd) {
|
|
39
|
+
display: inline-block;
|
|
40
|
+
padding: 0 var(--space-1);
|
|
41
|
+
border: 1px solid var(--color-border);
|
|
42
|
+
border-bottom-width: 2px;
|
|
43
|
+
border-radius: var(--radius-inline);
|
|
44
|
+
background: var(--color-surface);
|
|
45
|
+
font-size: var(--text-xs);
|
|
46
|
+
white-space: nowrap;
|
|
47
|
+
}
|
|
48
|
+
.fg-site-docs :where(:focus-visible) { outline: 2px solid var(--color-focus); outline-offset: 2px; }
|
|
49
|
+
}
|
|
50
|
+
|
|
4
51
|
@layer components {
|
|
52
|
+
/* Docs shell: header across the top, the --sidebar rail beside main, and the footer
|
|
53
|
+
* on the frame edges. Header, rail, main, and footer are direct children. */
|
|
54
|
+
.fg-site-docs {
|
|
55
|
+
display: grid;
|
|
56
|
+
grid-template-columns: var(--sidebar) minmax(0, 1fr);
|
|
57
|
+
column-gap: var(--space-8);
|
|
58
|
+
max-width: calc(var(--page-max) + var(--sidebar) + var(--space-8) + var(--space-12));
|
|
59
|
+
margin-inline: auto;
|
|
60
|
+
padding-inline: var(--space-6);
|
|
61
|
+
}
|
|
62
|
+
.fg-site-docs > .fg-site-header {
|
|
63
|
+
--site-frame: 100%;
|
|
64
|
+
--site-gutter: 0px;
|
|
65
|
+
grid-column: 1 / -1;
|
|
66
|
+
min-width: 0;
|
|
67
|
+
}
|
|
68
|
+
.fg-site-docs > main {
|
|
69
|
+
display: grid;
|
|
70
|
+
grid-template-columns: minmax(0, 1fr);
|
|
71
|
+
gap: var(--space-12);
|
|
72
|
+
min-width: 0;
|
|
73
|
+
padding-block: var(--space-8) var(--space-16);
|
|
74
|
+
}
|
|
75
|
+
.fg-site-docs > .fg-site-footer { grid-column: 1 / -1; }
|
|
76
|
+
|
|
77
|
+
/* Footer: an attribution link at the start, project links in a nav at the end. */
|
|
78
|
+
.fg-site-footer {
|
|
79
|
+
display: flex;
|
|
80
|
+
flex-wrap: wrap;
|
|
81
|
+
align-items: center;
|
|
82
|
+
justify-content: space-between;
|
|
83
|
+
gap: 0 var(--space-5);
|
|
84
|
+
padding-block: var(--space-6) var(--space-8);
|
|
85
|
+
border-top: 1px solid var(--color-border-subtle);
|
|
86
|
+
color: var(--color-muted);
|
|
87
|
+
font-size: var(--text-sm);
|
|
88
|
+
}
|
|
89
|
+
.fg-site-footer nav { display: flex; flex-wrap: wrap; gap: 0 var(--space-5); }
|
|
90
|
+
.fg-site-footer a {
|
|
91
|
+
display: inline-flex;
|
|
92
|
+
min-height: var(--control-lg);
|
|
93
|
+
align-items: center;
|
|
94
|
+
color: var(--color-muted);
|
|
95
|
+
text-decoration: none;
|
|
96
|
+
}
|
|
97
|
+
.fg-site-footer a:hover { color: var(--color-text); text-decoration: underline; }
|
|
98
|
+
|
|
99
|
+
/* Legend: a dl of what a capture shows, with one div per dt and dd pair. Columns are at
|
|
100
|
+
* least --site-legend-column wide (default --sidebar); a page can lower it to fit more. */
|
|
101
|
+
.fg-site-legend {
|
|
102
|
+
display: grid;
|
|
103
|
+
grid-template-columns: repeat(auto-fit, minmax(min(var(--site-legend-column, var(--sidebar)), 100%), 1fr));
|
|
104
|
+
gap: 0 var(--space-6);
|
|
105
|
+
margin: 0;
|
|
106
|
+
font-size: var(--text-sm);
|
|
107
|
+
}
|
|
108
|
+
.fg-site-legend > div {
|
|
109
|
+
display: grid;
|
|
110
|
+
align-content: start;
|
|
111
|
+
gap: var(--space-1);
|
|
112
|
+
padding-block: var(--space-3);
|
|
113
|
+
border-top: 1px solid var(--color-border-subtle);
|
|
114
|
+
}
|
|
115
|
+
.fg-site-legend dt { font-family: var(--font-mono); font-weight: var(--weight-medium); }
|
|
116
|
+
.fg-site-legend dd { margin: 0; color: var(--color-muted); }
|
|
117
|
+
|
|
5
118
|
/* A centered frame. The header uses the same edges as the page below it.
|
|
6
119
|
* Set --site-frame on the header or a frame to change its width. */
|
|
7
120
|
.fg-site-frame,
|
|
@@ -138,8 +251,8 @@
|
|
|
138
251
|
.fg-site-nav a:focus-visible { outline: 2px solid var(--color-focus); outline-offset: -2px; }
|
|
139
252
|
|
|
140
253
|
/* Section rail (UiSiteNav). The page grid places it; on desktop it stays in view
|
|
141
|
-
* beside the article. At 800px and below it becomes a
|
|
142
|
-
* by a drawer once the page is interactive. */
|
|
254
|
+
* beside the article. At 800px and below it becomes a disclosure named by the
|
|
255
|
+
* label prop, replaced by a drawer once the page is interactive. */
|
|
143
256
|
.fg-site-rail {
|
|
144
257
|
position: sticky;
|
|
145
258
|
top: var(--space-6);
|
|
@@ -168,9 +281,9 @@
|
|
|
168
281
|
.fg-site-rail__group-label { margin-block-end: var(--space-1); }
|
|
169
282
|
|
|
170
283
|
/* Capture panel (UiCapture): tabs in the header, the capture as the body, and the
|
|
171
|
-
* command and caption as the footer. The
|
|
172
|
-
*
|
|
173
|
-
* full-size viewer. Nothing clips the panel, so focus rings inside it stay whole. */
|
|
284
|
+
* command and caption as the footer. The screen uses a dark terminal palette by
|
|
285
|
+
* default. A site can set --site-capture-bg and --t* values on :root, which also
|
|
286
|
+
* reach the full-size viewer. Nothing clips the panel, so focus rings inside it stay whole. */
|
|
174
287
|
.fg-capture {
|
|
175
288
|
position: relative;
|
|
176
289
|
min-width: 0;
|
|
@@ -220,7 +333,59 @@
|
|
|
220
333
|
overflow-x: auto;
|
|
221
334
|
background: var(--site-capture-bg, var(--color-code));
|
|
222
335
|
}
|
|
336
|
+
/* Terminal markup gets the dark default; a plain <pre> keeps the code background its text expects. */
|
|
337
|
+
.fg-capture__screen:has(> .term) { background: var(--site-capture-bg, var(--t-bg, #131316)); }
|
|
223
338
|
.fg-capture__screen > * { width: max-content; margin: 0; }
|
|
339
|
+
/* Terminal colors for checked-in capture markup: .term and the ANSI classes the capture
|
|
340
|
+
* converter emits. Each color reads the site's --t* value first, so a site palette on
|
|
341
|
+
* :root still wins, and these defaults apply only where a site sets none. */
|
|
342
|
+
.fg-capture__screen .term {
|
|
343
|
+
padding: var(--space-4);
|
|
344
|
+
color: var(--t-fg, #e6e6ea);
|
|
345
|
+
font: var(--weight-regular) var(--text-sm) / 1 var(--font-mono);
|
|
346
|
+
font-variant-ligatures: none;
|
|
347
|
+
tab-size: 8;
|
|
348
|
+
}
|
|
349
|
+
.fg-capture__screen .term i { display: inline-block; width: 1ch; overflow: visible; font-style: normal; }
|
|
350
|
+
.fg-capture__screen .tf0 { color: var(--t0, #2b2b31); }
|
|
351
|
+
.fg-capture__screen .tf1 { color: var(--t1, #f0776c); }
|
|
352
|
+
.fg-capture__screen .tf2 { color: var(--t2, #4cc38a); }
|
|
353
|
+
.fg-capture__screen .tf3 { color: var(--t3, #e2a54b); }
|
|
354
|
+
.fg-capture__screen .tf4 { color: var(--t4, #7d97ff); }
|
|
355
|
+
.fg-capture__screen .tf5 { color: var(--t5, #c792ea); }
|
|
356
|
+
.fg-capture__screen .tf6 { color: var(--t6, #5fd3d9); }
|
|
357
|
+
.fg-capture__screen .tf7 { color: var(--t7, #c8c8d0); }
|
|
358
|
+
.fg-capture__screen .tf8 { color: var(--t8, #a0a0ab); }
|
|
359
|
+
.fg-capture__screen .tf9 { color: var(--t9, #ff8f85); }
|
|
360
|
+
.fg-capture__screen .tf10 { color: var(--t10, #6fd3a0); }
|
|
361
|
+
.fg-capture__screen .tf11 { color: var(--t11, #e8b56a); }
|
|
362
|
+
.fg-capture__screen .tf12 { color: var(--t12, #7d97ff); }
|
|
363
|
+
.fg-capture__screen .tf13 { color: var(--t13, #d9a8f0); }
|
|
364
|
+
.fg-capture__screen .tf14 { color: var(--t14, #8ee3e8); }
|
|
365
|
+
.fg-capture__screen .tf15 { color: var(--t15, #ffffff); }
|
|
366
|
+
.fg-capture__screen .tb0 { background: var(--t0, #2b2b31); }
|
|
367
|
+
.fg-capture__screen .tb1 { background: var(--t1, #f0776c); }
|
|
368
|
+
.fg-capture__screen .tb2 { background: var(--t2, #4cc38a); }
|
|
369
|
+
.fg-capture__screen .tb3 { background: var(--t3, #e2a54b); }
|
|
370
|
+
.fg-capture__screen .tb4 { background: var(--t4, #7d97ff); }
|
|
371
|
+
.fg-capture__screen .tb5 { background: var(--t5, #c792ea); }
|
|
372
|
+
.fg-capture__screen .tb6 { background: var(--t6, #5fd3d9); }
|
|
373
|
+
.fg-capture__screen .tb7 { background: var(--t7, #c8c8d0); }
|
|
374
|
+
.fg-capture__screen .tb8 { background: var(--t8, #a0a0ab); }
|
|
375
|
+
.fg-capture__screen .tb9 { background: var(--t9, #ff8f85); }
|
|
376
|
+
.fg-capture__screen .tb10 { background: var(--t10, #6fd3a0); }
|
|
377
|
+
.fg-capture__screen .tb11 { background: var(--t11, #e8b56a); }
|
|
378
|
+
.fg-capture__screen .tb12 { background: var(--t12, #7d97ff); }
|
|
379
|
+
.fg-capture__screen .tb13 { background: var(--t13, #d9a8f0); }
|
|
380
|
+
.fg-capture__screen .tb14 { background: var(--t14, #8ee3e8); }
|
|
381
|
+
.fg-capture__screen .tb15 { background: var(--t15, #ffffff); }
|
|
382
|
+
.fg-capture__screen .tf-dim { color: var(--t-dim, #a0a0ab); }
|
|
383
|
+
.fg-capture__screen .tf-bg { color: var(--t-bg, #131316); }
|
|
384
|
+
.fg-capture__screen .tb-fg { background: var(--t-fg, #e6e6ea); }
|
|
385
|
+
.fg-capture__screen .tbold { font-weight: var(--weight-semibold); }
|
|
386
|
+
.fg-capture__screen .tital { font-style: italic; }
|
|
387
|
+
.fg-capture__screen .tul { text-decoration: underline; text-underline-offset: 0.18em; }
|
|
388
|
+
|
|
224
389
|
.fg-capture__screen[data-fit] { overflow: hidden; }
|
|
225
390
|
.fg-capture__screen[data-fit] > * { transform: scale(var(--capture-scale, 1)); transform-origin: top left; }
|
|
226
391
|
.fg-capture__expand {
|
|
@@ -355,6 +520,8 @@
|
|
|
355
520
|
}
|
|
356
521
|
.fg-site-definitions dt { font-weight: var(--weight-medium); }
|
|
357
522
|
.fg-site-definitions dd { margin: 0; color: var(--color-muted); }
|
|
523
|
+
/* Keep flags such as --all whole instead of breaking after a hyphen. */
|
|
524
|
+
.fg-site-definitions code { white-space: nowrap; }
|
|
358
525
|
|
|
359
526
|
.fg-site-sr-only {
|
|
360
527
|
position: absolute;
|
|
@@ -407,6 +574,8 @@
|
|
|
407
574
|
}
|
|
408
575
|
/* Keep in sync with MOBILE_QUERY in UiSiteNav.vue. */
|
|
409
576
|
@media (max-width: 800px) {
|
|
577
|
+
.fg-site-docs { grid-template-columns: minmax(0, 1fr); }
|
|
578
|
+
.fg-site-docs > main { gap: var(--space-8); padding-top: var(--space-6); }
|
|
410
579
|
.fg-site-rail {
|
|
411
580
|
position: static;
|
|
412
581
|
max-height: none;
|
|
@@ -432,8 +601,30 @@
|
|
|
432
601
|
.fg-site-rail__menu .fg-site-rail__group { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
433
602
|
.fg-site-rail__menu .fg-site-rail__group-label { grid-column: 1 / -1; }
|
|
434
603
|
.fg-site-rail__nav a { min-height: var(--control-lg); }
|
|
604
|
+
/* The drawer title already shows the label; the heading still names the nav. */
|
|
605
|
+
.fg-drawer__content .fg-site-rail__label {
|
|
606
|
+
position: absolute;
|
|
607
|
+
width: 1px;
|
|
608
|
+
height: 1px;
|
|
609
|
+
overflow: hidden;
|
|
610
|
+
clip-path: inset(50%);
|
|
611
|
+
white-space: nowrap;
|
|
612
|
+
}
|
|
435
613
|
}
|
|
436
614
|
@media (max-width: 640px) {
|
|
615
|
+
.fg-site-docs { padding-inline: var(--space-4); }
|
|
616
|
+
/* Docs-shell pages keep one header row on phones and repeat these links in their footer. */
|
|
617
|
+
.fg-site-docs .fg-site-header__links { display: none; }
|
|
618
|
+
/* Fact links, such as a Source link that stands in for the hidden header link, get a
|
|
619
|
+
* touch-sized hit area. The negative margin keeps each fact row one line tall, and the
|
|
620
|
+
* row gap of a list with links makes room for the part of the hit area past the line. */
|
|
621
|
+
.fg-site-facts:has(a) { row-gap: calc(var(--control-lg) - 1lh); }
|
|
622
|
+
.fg-site-facts a {
|
|
623
|
+
display: inline-flex;
|
|
624
|
+
min-height: var(--control-lg);
|
|
625
|
+
align-items: center;
|
|
626
|
+
margin-block: calc((1lh - var(--control-lg)) / 2);
|
|
627
|
+
}
|
|
437
628
|
.fg-dialog__content.fg-capture-viewer { width: 100%; max-width: none; }
|
|
438
629
|
/* Phones keep the icon; the accessible name still says Full size. */
|
|
439
630
|
.fg-capture[data-enhanced="true"] .fg-tabs__list { margin-inline-end: calc(var(--space-2) + var(--control-lg)); }
|
package/src/theme.css
CHANGED
|
@@ -75,6 +75,7 @@
|
|
|
75
75
|
--color-warning-surface: color-mix(in srgb, var(--color-warning) 13%, var(--color-surface));
|
|
76
76
|
--color-success-surface: color-mix(in srgb, var(--color-success) 12%, var(--color-surface));
|
|
77
77
|
--color-info-surface: color-mix(in srgb, var(--color-info) 12%, var(--color-surface));
|
|
78
|
+
--radius-inline: 0.25rem;
|
|
78
79
|
--radius-control: 0.375rem;
|
|
79
80
|
--radius-panel: 0.5rem;
|
|
80
81
|
--radius-pill: 999px;
|
|
@@ -147,6 +148,7 @@
|
|
|
147
148
|
--color-ui-warning: var(--color-warning);
|
|
148
149
|
--color-ui-success: var(--color-success);
|
|
149
150
|
--color-ui-info: var(--color-info);
|
|
151
|
+
--radius-ui-inline: var(--radius-inline);
|
|
150
152
|
--radius-ui-control: var(--radius-control);
|
|
151
153
|
--radius-ui-panel: var(--radius-panel);
|
|
152
154
|
}
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
--color-syntax-attribute: var(--color-syntax-number);
|
|
42
42
|
--color-error: #c7372d;
|
|
43
43
|
--color-warning: #86532e;
|
|
44
|
-
--color-success: #
|
|
44
|
+
--color-success: #157249;
|
|
45
45
|
--color-info: #175cd3;
|
|
46
46
|
--color-progress: var(--color-accent);
|
|
47
47
|
--color-error-surface: color-mix(in srgb, var(--color-error) 10%, var(--color-bg));
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
:root.dark {
|
|
65
65
|
color-scheme: dark;
|
|
66
66
|
--color-bg: #151619;
|
|
67
|
-
--color-surface: #
|
|
67
|
+
--color-surface: #0e0f12;
|
|
68
68
|
--color-surface-raised: #212226;
|
|
69
69
|
--color-surface-muted: #303238;
|
|
70
70
|
--color-text: #f4f5f8;
|
|
@@ -106,6 +106,6 @@
|
|
|
106
106
|
--color-warning-surface: color-mix(in srgb, var(--color-warning) 12%, var(--color-bg));
|
|
107
107
|
--color-success-surface: color-mix(in srgb, var(--color-success) 11%, var(--color-bg));
|
|
108
108
|
--color-info-surface: color-mix(in srgb, var(--color-info) 10%, var(--color-bg));
|
|
109
|
-
--shadow-dialog: 0 8px 24px rgb(0 0 0 / 45%), 0 0 0 1px var(--color-border);
|
|
109
|
+
--shadow-dialog: 0 8px 24px rgb(0 0 0 / 45%), 0 0 0 1px var(--color-border-subtle);
|
|
110
110
|
--color-status-text: var(--color-text);
|
|
111
111
|
}
|