merge text-xs override

This commit is contained in:
2026-07-17 12:52:50 -04:00
43 changed files with 158 additions and 159 deletions

View File

@@ -232,7 +232,7 @@ func badgesSection() func() *VNode {
ui.EnvBadge("staging"),
// Production deliberately renders NOTHING — the badge exists to tell you that
// you are NOT in production, and a badge that is always there says nothing.
Span(Attr("class", "text-xs text-ink-muted"),
Span(Attr("class", "text-ss text-ink-muted"),
Text("(production renders nothing — that is the point of it)")),
),
),
@@ -473,7 +473,7 @@ func selectsSection() func() *VNode {
field("Timezone", ui.FormTimezoneSelector(ui.FormSelectProps{
Value: tz.Get(), OnChange: func(v string) { tz.Set(v) }})),
),
P(Attr("class", "mt-3 text-xs text-ink-muted"),
P(Attr("class", "mt-3 text-ss text-ink-muted"),
Text("one="+orElse(one.Get(), "—")+" several="+orElse(strings.Join(langs.Get(), ","), "—"))),
),
@@ -484,7 +484,7 @@ func selectsSection() func() *VNode {
OnSelect: func(o ui.FormSelectOption) { picked.Set(o.Label + " <" + o.Value + ">") },
}),
),
P(Attr("class", "mt-3 text-xs text-ink-muted"),
P(Attr("class", "mt-3 text-ss text-ink-muted"),
Text("Two characters before it asks; 200 ms after you stop typing. A response for a query "+
"you have already typed past is DISCARDED rather than shown — which is the whole bug "+
"with hand-rolled autocompletes.")),
@@ -500,7 +500,7 @@ func selectsSection() func() *VNode {
ShowSelectAll: true,
OnChange: func(v []string) { tags.Set(v) },
}),
P(Attr("class", "mt-3 text-xs text-ink-muted"),
P(Attr("class", "mt-3 text-ss text-ink-muted"),
Text("Same selection model as the field above; only the thing you click on differs.")),
),
)
@@ -535,7 +535,7 @@ func togglesSection() func() *VNode {
demo("Signature pad — "+itoa(len(signed.Get()))+" bytes of SVG",
pad.Render(ui.SignaturePadProps{}),
P(Attr("class", "mt-3 text-xs text-ink-muted"),
P(Attr("class", "mt-3 text-ss text-ink-muted"),
Text("Draw in it. Long strokes are smoothed; a single stray point is not a stroke and "+
"is dropped, so a click does not leave a dot behind.")),
),
@@ -584,7 +584,7 @@ func datesSection() func() *VNode {
OnNavigate: func(m time.Time) { month.Set(m) },
}),
),
P(Attr("class", "mt-3 text-xs text-ink-muted"),
P(Attr("class", "mt-3 text-ss text-ink-muted"),
Text("The same grid the picker drops down, usable directly when you want it inline.")),
),
)
@@ -676,7 +676,7 @@ func tablesSection() func() *VNode {
SortDesc: gridDesc.Get(),
SetSortDesc: func(b bool) { gridDesc.Set(b) },
}),
P(Attr("class", "mt-3 text-xs text-ink-muted"),
P(Attr("class", "mt-3 text-ss text-ink-muted"),
Text("Click a Qty or Price cell and type. The grid does not own the rows — it tells you "+
"which cell changed and hands the value back; what you do with it is yours.")),
),
@@ -801,7 +801,7 @@ func overlaysSection(push func(ui.ToastType, string)) func() *VNode {
tipFocus.Render(Span(Text("Shown on FOCUS, not hover — tab to the field")),
ui.FormInput(ui.FormInputProps{Placeholder: "Focus me"})),
),
P(Attr("class", "mt-3 text-xs text-ink-muted"),
P(Attr("class", "mt-3 text-ss text-ink-muted"),
Text("Narrow the window and hover \"Right\": it flips to the left, and its arrow follows "+
"it. A tooltip that only answers to a mouse is a tooltip a keyboard user cannot read.")),
),
@@ -862,7 +862,7 @@ func overlaysSection(push func(ui.ToastType, string)) func() *VNode {
hoverMenu.Item(ui.MenuItemProps{}, Text("Two")),
),
),
P(Attr("class", "mt-3 text-xs text-ink-muted"),
P(Attr("class", "mt-3 text-ss text-ink-muted"),
Text("Opening one closes the other — a single-open manager. Submenus are exempt, or a "+
"submenu would close the very menu it belongs to as it opened. The items raise toasts, "+
"which is how you can see that an item really does close its own menu.")),
@@ -889,7 +889,7 @@ func overlaysSection(push func(ui.ToastType, string)) func() *VNode {
}, ui.ModalOptions{Size: ui.ModalSmall})
}}),
),
P(Attr("class", "mt-3 text-xs text-ink-muted"),
P(Attr("class", "mt-3 text-ss text-ink-muted"),
Text("Open the modal, then the nested one inside it, and press Escape twice: modals unwind "+
"ONE LAYER per press rather than all at once.")),
@@ -994,7 +994,7 @@ func feedbackSection(toaster *ui.Toaster, tour *ui.Tutorial) func() *VNode {
demo("The guided tour",
row("flex flex-wrap items-center gap-3",
tour.StartButton(0, "", Text("Take the tour")),
Span(Attr("class", "text-xs text-ink-muted"),
Span(Attr("class", "text-ss text-ink-muted"),
Text("It dims the page, cuts a hole around each target, and animates the spotlight from "+
"one to the next. Targets are CSS SELECTORS — the same section ids the sidebar jumps to.")),
),
@@ -1006,7 +1006,7 @@ func feedbackSection(toaster *ui.Toaster, tour *ui.Tutorial) func() *VNode {
OnClick: flash.Fire}),
ui.RemoteUpdateFlash(flash.Visible()),
),
P(Attr("class", "mt-3 text-xs text-ink-muted"),
P(Attr("class", "mt-3 text-ss text-ink-muted"),
Text("A two-second acknowledgement that data you are looking at was changed by somebody "+
"else. It is not a toast: it belongs next to the thing that moved, not in the corner.")),
),
@@ -1071,7 +1071,7 @@ func navigationSection() func() *VNode {
demo("Accordion — one open at a time, or several",
row("grid gap-6 lg:grid-cols-2",
row("flex flex-col gap-2",
P(Attr("class", "text-xs font-semibold uppercase tracking-widest text-ink-faint"),
P(Attr("class", "text-ss font-semibold uppercase tracking-widest text-ink-faint"),
Text("SingleAccordion")),
ui.SingleAccordion([]ui.AccordionItemData{
{Title: "What is Kjøl Wasm Web?", Content: panel("kjol's Go→WebAssembly UI engine.")},
@@ -1080,7 +1080,7 @@ func navigationSection() func() *VNode {
}, acc.Get(), func(i int) { acc.Set(i) }),
),
row("flex flex-col gap-2",
P(Attr("class", "text-xs font-semibold uppercase tracking-widest text-ink-faint"),
P(Attr("class", "text-ss font-semibold uppercase tracking-widest text-ink-faint"),
Text("Accordion (several at once)")),
ui.Accordion([]ui.AccordionItemData{
{Title: "First", Content: panel("Open me.")},
@@ -1107,7 +1107,7 @@ func navigationSection() func() *VNode {
}},
}, func(id string) { side.Set(id) }, ""),
),
P(Attr("class", "mt-3 text-xs text-ink-muted"),
P(Attr("class", "mt-3 text-ss text-ink-muted"),
Text("It reports the id you clicked and nothing else. The sidebar on THIS page is the "+
"same idea, wired to scroll the section into view.")),
),
@@ -1230,7 +1230,7 @@ func chartsSection() func() *VNode {
row("mt-4 flex items-center gap-3",
ui.Button(ui.ButtonProps{Color: ui.ButtonPrimary, Small: true, Text: "New data", OnClick: func() { seed.Set(seed.Get() + 1) }}),
ui.Button(ui.ButtonProps{Color: ui.ButtonNeutral, Small: true, Text: threeDLabel, OnClick: func() { threeD.Set(!threeD.Get()) }}),
Span(Attr("class", "text-xs text-ink-muted"), Text("Each chart takes a Title; a multi-series chart also draws a legend. Click a legend key (Errors, or a donut slice) to hide it — the scale and marks recompute. 3D extrudes the bars and tilts the donut.")),
Span(Attr("class", "text-ss text-ink-muted"), Text("Each chart takes a Title; a multi-series chart also draws a legend. Click a legend key (Errors, or a donut slice) to hide it — the scale and marks recompute. 3D extrudes the bars and tilts the donut.")),
),
),
@@ -1247,7 +1247,7 @@ func chartsSection() func() *VNode {
demo("US heatmap — a value per state, with proportional lat/lng points on top",
heat.Render(ui.USHeatmapProps{Data: usSignups, Points: usCities, Proportional: true}),
Span(Attr("class", "mt-3 block text-xs text-ink-muted"),
Span(Attr("class", "mt-3 block text-ss text-ink-muted"),
Text("webui.USHeatmap shades each state on the choropleth ramp and projects lat/lng points "+
"with a Go albersUsa port — Anchorage and Honolulu land on the insets. Hover a state or a point.")),
),

View File

@@ -89,7 +89,7 @@ func docPage(eyebrow, title, lede string, sections ...*VNode) *VNode {
mods := []Mod{Attr("class", "pb-16")}
mods = append(mods,
Div(Attr("class", "border-b border-line pb-6"),
P(Attr("class", "text-xs font-semibold uppercase tracking-widest text-accent"), Text(eyebrow)),
P(Attr("class", "text-ss font-semibold uppercase tracking-widest text-accent"), Text(eyebrow)),
H1(Attr("class", "mt-2 text-3xl font-semibold tracking-tight text-text-heading"), Text(title)),
P(Attr("class", "mt-3 text-ink-muted leading-relaxed"), Text(lede)),
),
@@ -150,7 +150,7 @@ func codeLang(caption, lang, src string) *VNode {
return Div(Attr("class", "mt-4 overflow-hidden rounded-default border border-neutral-800 bg-neutral-900"),
Div(Attr("class", "flex items-center gap-2 border-b border-neutral-800 px-4 py-2"),
Span(Attr("class", "text-xs font-medium text-ink-faint font-mono"), Text(caption)),
Span(Attr("class", "text-ss font-medium text-ink-faint font-mono"), Text(caption)),
Span(Attr("class", "ml-auto rounded-full bg-white/5 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wider text-ink-faint"), Text(lang)),
),
Pre(Attr("class", "overflow-x-auto px-4 py-3 text-[13px] leading-relaxed text-neutral-100 font-mono"), body),
@@ -164,7 +164,7 @@ func demo(title string, body ...*VNode) *VNode {
mods := []Mod{Attr("class", "mt-4 rounded-default border border-line bg-surface shadow-xs")}
mods = append(mods,
Div(Attr("class", "border-b border-line px-4 py-2"),
Span(Attr("class", "text-xs text-ink-muted"), Text(title)),
Span(Attr("class", "text-ss text-ink-muted"), Text(title)),
),
)
inner := []Mod{Attr("class", "p-4")}

View File

@@ -247,7 +247,7 @@ func layerItem(d Deps, l Layer) *VNode {
Span(Attr("class", "rounded-full bg-surface-raised px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wider text-ink-muted"),
Text("reference")),
),
Span(Attr("class", "text-xs text-ink-muted"), Text(l.Tagline)),
Span(Attr("class", "text-ss text-ink-muted"), Text(l.Tagline)),
)
}
@@ -257,6 +257,6 @@ func layerItem(d Deps, l Layer) *VNode {
}
return A(Attr("class", cls), Attr("href", l.Href),
Span(Attr("class", "text-sm font-medium text-ink"), Text(l.Name)),
Span(Attr("class", "text-xs text-ink-muted"), Text(l.Tagline)),
Span(Attr("class", "text-ss text-ink-muted"), Text(l.Tagline)),
)
}

View File

@@ -410,7 +410,7 @@ serving "./wwwroot" on http://localhost:8085`
func AboutPage(d Deps) func() *VNode {
return func() *VNode {
return Div(Attr("class", "mx-auto max-w-3xl py-4"),
P(Attr("class", "text-xs font-semibold uppercase tracking-widest text-accent"), Text("About")),
P(Attr("class", "text-ss font-semibold uppercase tracking-widest text-accent"), Text("About")),
H1(Attr("class", "mt-2 text-4xl font-semibold tracking-tight text-text-heading"), Text("Why this exists")),
P(Attr("class", "mt-6 text-lg leading-relaxed text-ink-soft"),

View File

@@ -98,7 +98,7 @@ function LayerItem(props: { layer: Layer; current?: Layer }) {
reference
</span>
</span>
<span class="text-xs text-ink-muted">{props.layer.tagline}</span>
<span class="text-ss text-ink-muted">{props.layer.tagline}</span>
</div>
}
>
@@ -113,7 +113,7 @@ function LayerItem(props: { layer: Layer; current?: Layer }) {
}
>
<span class="text-sm font-medium text-ink">{props.layer.name}</span>
<span class="text-xs text-ink-muted">{props.layer.tagline}</span>
<span class="text-ss text-ink-muted">{props.layer.tagline}</span>
</a>
</Show>
);

View File

@@ -112,7 +112,7 @@ function Panel(props: { title: string; children?: JSXElement }) {
return (
<div class="mt-4 rounded-default border border-line bg-surface shadow-xs">
<div class="border-b border-line px-4 py-2">
<span class="text-xs text-ink-muted">{props.title}</span>
<span class="text-ss text-ink-muted">{props.title}</span>
</div>
<div class="p-4">{props.children}</div>
</div>
@@ -153,7 +153,7 @@ function Body() {
return (
<div>
<div class="border-b border-line pb-6">
<p class="text-xs font-semibold uppercase tracking-widest text-primary">Kjøl JS Web</p>
<p class="text-ss font-semibold uppercase tracking-widest text-primary">Kjøl JS Web</p>
<h1 class="mt-2 text-3xl font-semibold tracking-tight text-ink">Components</h1>
<p class="mt-3 leading-relaxed text-ink-muted">
Every component in the Solid kit, running. Not a screenshot of one anywhere: each block
@@ -313,7 +313,7 @@ function Badges() {
<span class="text-sm font-semibold text-ink">kjol</span>
<EnvBadge />
</div>
<p class="mt-3 text-xs text-ink-muted">
<p class="mt-3 text-ss text-ink-muted">
Nothing beside the wordmark? Then this build is production which is what it is telling
you.
</p>
@@ -429,7 +429,7 @@ function Icons() {
<Icon icon="star" size={18} solid />
<Icon icon="star" size={18} solid={false} />
</div>
<p class="mt-3 text-xs text-ink-muted">
<p class="mt-3 text-ss text-ink-muted">
The last two are the same name in the solid and regular styles. Which one you get by
default is a CSS variable the app sets, read at runtime.
</p>
@@ -614,7 +614,7 @@ function Selects() {
<FormTimezoneSelector value={tz()} onchange={(e: any) => setTz(e?.currentTarget?.value ?? e)} />
</Field>
</div>
<p class="mt-3 text-xs text-ink-muted">
<p class="mt-3 text-ss text-ink-muted">
one: <span class="font-mono text-ink">{one() || "—"}</span> · several:{" "}
<span class="font-mono text-ink">{many().join(", ") || "—"}</span>
</p>
@@ -635,7 +635,7 @@ function Selects() {
onSelect={(value, option) => setPicked(option.label + " <" + value + ">")}
/>
</div>
<p class="mt-3 text-xs text-ink-muted">
<p class="mt-3 text-ss text-ink-muted">
Two characters before it asks; 200 ms after you stop typing. A response for a query you
have already typed past is DISCARDED rather than shown which is the whole bug with
hand-rolled autocompletes.
@@ -655,7 +655,7 @@ function Selects() {
searchable
showSelectAll
/>
<p class="mt-3 text-xs text-ink-muted">
<p class="mt-3 text-ss text-ink-muted">
Same selection model as the field above; only the thing you click on differs.
</p>
</Panel>
@@ -698,7 +698,7 @@ function Toggles() {
<Panel title={"Signature pad — " + signed().length + " bytes of SVG"}>
<FormSignaturePad onchange={setSigned} />
<p class="mt-3 text-xs text-ink-muted">
<p class="mt-3 text-ss text-ink-muted">
Draw in it. Clearing it emits an empty string, so "did they sign?" is just a length check.
</p>
</Panel>
@@ -735,7 +735,7 @@ function Dates() {
<div class="max-w-xs">
<Calendar selected={day()} onSelect={setDay} />
</div>
<p class="mt-3 text-xs text-ink-muted">
<p class="mt-3 text-ss text-ink-muted">
The same grid the picker drops down, usable directly when you want it inline. Pass{" "}
<code class="font-mono">variant="month"</code> for the big version.
</p>
@@ -859,7 +859,7 @@ function Tables() {
sortDesc={sortDesc()}
setSortDesc={setSortDesc}
/>
<p class="mt-3 text-xs text-ink-muted">
<p class="mt-3 text-ss text-ink-muted">
Click a Qty or Price cell and type; Tab and the arrow keys move between editable cells.
The grid does not own the rows it tells you which cell changed and hands the value back.
</p>
@@ -972,7 +972,7 @@ function Overlays() {
<FormInput placeholder="Focus me" />
</Tooltip>
</div>
<p class="mt-3 text-xs text-ink-muted">
<p class="mt-3 text-ss text-ink-muted">
A tooltip that only answers to a mouse is a tooltip a keyboard user cannot read.
</p>
</Panel>
@@ -1048,7 +1048,7 @@ function Overlays() {
</MenuContent>
</Menu>
</div>
<p class="mt-3 text-xs text-ink-muted">
<p class="mt-3 text-ss text-ink-muted">
The items raise toasts, which is how you can see that an item really does close its own
menu — and that the one marked closeOnClick={"{false}"} does not.
</p>
@@ -1064,7 +1064,7 @@ function Overlays() {
Open wizard
</ButtonUI>
</div>
<p class="mt-3 text-xs text-ink-muted">
<p class="mt-3 text-ss text-ink-muted">
Open the modal, then the nested one inside it, and press Escape twice: modals unwind ONE
LAYER per press rather than all at once.
</p>
@@ -1190,7 +1190,7 @@ function Feedback() {
Sticky (no timer)
</ButtonUI>
</div>
<p class="mt-3 text-xs text-ink-muted">
<p class="mt-3 text-ss text-ink-muted">
<code class="font-mono">useToast()</code> throws outside a{" "}
<code class="font-mono">&lt;ToastProvider&gt;</code> which is one of only two providers
this kit has.
@@ -1200,7 +1200,7 @@ function Feedback() {
<Panel title="The guided tour">
<div class="flex flex-wrap items-center gap-3">
<StartTutorialButton>Take the tour</StartTutorialButton>
<span class="text-xs text-ink-muted">
<span class="text-ss text-ink-muted">
It dims the page, cuts a hole around each target, and animates the spotlight from one
to the next. Targets are CSS SELECTORS the same section ids the sidebar jumps to.
</span>
@@ -1214,7 +1214,7 @@ function Feedback() {
</ButtonUI>
<RemoteUpdateFlash when={flash.visible()} />
</div>
<p class="mt-3 text-xs text-ink-muted">
<p class="mt-3 text-ss text-ink-muted">
A brief acknowledgement that data you are looking at was changed by somebody else. It is
not a toast: it belongs next to the thing that moved, not in the corner.
</p>
@@ -1269,7 +1269,7 @@ function Navigation() {
<Panel title="Accordion — one open at a time, or several">
<div class="grid gap-6 lg:grid-cols-2">
<div class="flex flex-col gap-2">
<p class="text-xs font-semibold uppercase tracking-widest text-ink-faint">
<p class="text-ss font-semibold uppercase tracking-widest text-ink-faint">
SingleAccordion
</p>
<SingleAccordion
@@ -1281,7 +1281,7 @@ function Navigation() {
/>
</div>
<div class="flex flex-col gap-2">
<p class="text-xs font-semibold uppercase tracking-widest text-ink-faint">
<p class="text-ss font-semibold uppercase tracking-widest text-ink-faint">
Accordion (several at once)
</p>
<Accordion
@@ -1314,7 +1314,7 @@ function Navigation() {
onItemClick={setSide}
/>
</div>
<p class="mt-3 text-xs text-ink-muted">
<p class="mt-3 text-ss text-ink-muted">
It scrolls the element whose <code class="font-mono">id</code> matches the item into view
so these really do jump, because those sections really do exist on this page.
</p>
@@ -1353,7 +1353,7 @@ function Search() {
onSelect={(value) => setHit(value)}
/>
</div>
<p class="mt-3 text-xs text-ink-muted">
<p class="mt-3 text-ss text-ink-muted">
The scorer is headless too: <code class="font-mono">rankFuzzyMatches</code> and{" "}
<code class="font-mono">fuzzySegments</code> give you the ranking and the highlight runs,
and you render them however you like.
@@ -1438,7 +1438,7 @@ function Charts() {
<ButtonUI color={BUTTON_COLOR_NEUTRAL} small onclick={() => setThreeD(!threeD())}>
{threeD() ? "Flat" : "3D"}
</ButtonUI>
<span class="text-xs text-ink-muted">
<span class="text-ss text-ink-muted">
Each chart carries a <code class="font-mono">title</code>; a multi-series chart also draws a
legend. Click a legend key say <em>Errors</em> or a donut slice to hide it, and the scale
and marks recompute from what's left. The <code class="font-mono">threeD</code> prop extrudes
@@ -1468,7 +1468,7 @@ function Charts() {
{ name: "Retries", data: shuffle([5, 7, 3, 9]) },
]} height={260} />
</div>
<p class="mt-3 text-xs text-ink-muted">
<p class="mt-3 text-ss text-ink-muted">
<code class="font-mono">horizontal</code> runs the categories down the y-axis;{" "}
<code class="font-mono">stacked</code> layers the series with a 2px surface gap between segments.
</p>
@@ -1476,7 +1476,7 @@ function Charts() {
<Panel title="US heatmap — a value per state, with proportional lat/lng points on top">
<USHeatmap data={US_SIGNUPS} points={US_CITIES} proportional valueFormat={(v) => v.toLocaleString("en-US")} />
<p class="mt-3 text-xs text-ink-muted">
<p class="mt-3 text-ss text-ink-muted">
<code class="font-mono">@ui/USHeatmap</code> shades each state on a themed sequential ramp and
projects <code class="font-mono">points</code> (latitude/longitude) with a dependency-free
albersUsa port — so Anchorage and Honolulu land on the Alaska and Hawaii insets. With{" "}
@@ -1557,7 +1557,7 @@ function Theming() {
)}
</For>
</div>
<p class="mt-3 text-xs text-ink-muted">
<p class="mt-3 text-ss text-ink-muted">
The swatch class is written out in full in the source, not built as{" "}
<code class="font-mono">"bg-" + name</code>. Tailwind finds the classes it must compile by
scanning the source for literal strings a concatenation is invisible to it, and every

View File

@@ -13,7 +13,7 @@ export function Overview() {
return (
<div>
<p class="text-xs font-semibold uppercase tracking-widest text-primary">Kjøl JS Web</p>
<p class="text-ss font-semibold uppercase tracking-widest text-primary">Kjøl JS Web</p>
<h1 class="mt-2 text-3xl font-semibold tracking-tight text-ink">
A Solid kit, built by a Go toolchain
</h1>
@@ -103,7 +103,7 @@ export function Overview() {
function Stage(props: { n: string; title: string; body: string }) {
return (
<div class="flex gap-4 border-l-2 border-line pl-4">
<span class="mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-surface-raised text-xs font-semibold text-ink-soft">
<span class="mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-surface-raised text-ss font-semibold text-ink-soft">
{props.n}
</span>
<div>

View File

@@ -29,7 +29,7 @@ export function Ssr() {
return (
<div class="page-ssr mx-auto max-w-2xl px-4 py-14">
<p class="text-xs font-semibold uppercase tracking-widest text-primary">Kjøl JS Web</p>
<p class="text-ss font-semibold uppercase tracking-widest text-primary">Kjøl JS Web</p>
<h1 class="mt-2 text-3xl font-semibold tracking-tight text-ink">
This page was rendered by Go
</h1>