|
|
|
|
@@ -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"><ToastProvider></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
|
|
|
|
|
|