Skip to content

Add 20+ layout, form, and chat components; expand benchmarking#131

Open
developit wants to merge 41 commits into
mainfrom
claude/kind-carson-z90vyp
Open

Add 20+ layout, form, and chat components; expand benchmarking#131
developit wants to merge 41 commits into
mainfrom
claude/kind-carson-z90vyp

Conversation

@developit

Copy link
Copy Markdown
Owner

Summary

This PR significantly expands kinu's component library with 20+ new components focused on layout primitives, form enhancements, and chat/messaging UI. It also introduces comprehensive benchmarking infrastructure to track per-component bundle size and generates LLM-friendly documentation.

Key Changes

New Layout & Spacing Components

  • Stack, Row, Cluster, Grid, Center, Spacer — CSS-driven flex/grid layout primitives with token-based gap control
  • AppShell — full-page scaffold with header, sidebar, main, footer grid layout
  • Stepper — horizontal ordered steps with numbered markers

Form & Input Enhancements

  • NumberField — native number input with stepper buttons driven by the command bus
  • PasswordInput — password input with show/hide toggle
  • TagsInput — token/tags input that submits via hidden field
  • Form — wrapper that runs native validation before submit handler
  • Added :user-invalid CSS styling to Select, Textarea, Checkbox for post-interaction validation feedback

Chat & Messaging Components

  • Message — chat bubble with author-driven color and alignment
  • Thread — message list that sticks to bottom as new messages arrive
  • Composer — chat input form with autosizing textarea and Enter-to-send
  • Command — command palette (Dialog + Listbox composition)

Utility & Display Components

  • Code — styled code block and inline code with optional copy button
  • CopyButton — one-tap copy-to-clipboard with CSS-only copied state
  • Rating — star rating built from native radio group
  • Indicator — corner overlay for notification counts or status dots
  • Hotkey — declarative keyboard shortcut binding to commands

Infrastructure & Documentation

  • Per-component bundle size benchmarking (benchmarks/size/run.mjs) tracking JS, CSS, and total sizes
  • Generated llms.txt and components.json from component metadata for LLM authoring guidance
  • New foundation docs: Forms & Validation and Motion & View Transitions
  • CONTRIBUTING.md — single source of truth for component contribution process
  • ROADMAP.md — long-horizon execution plan with stable IDs and status tracking
  • ARCHITECTURE.md — expanded with platform-gating policy

Library Utilities

  • src/lib/hotkeys.ts — global hotkey singleton using delegated keydown listener
  • src/lib/motion.ts — View Transitions API wrapper with fallback
  • src/lib/commands.ts — enhanced command bus for custom commands (--prev, --next, --step-up, --step-down)

Styling & Theming

  • Added spacing scale tokens (--k-space-0 through --k-space-xl) for layout primitives
  • New theme files: themes/emerald.css, themes/violet.css
  • Enhanced base.css with forced-colors (Windows High Contrast) support
  • Updated Alert to support banner attribute for full-bleed page-level alerts
  • Updated Button sizing defaults and added Textarea autogrow attribute

Tests

  • New test suites: layout.test.tsx, controls.test.tsx, display.test.tsx, chat.test.tsx, lib.test.tsx

Notable Implementation Details

  • All new components follow the createSimpleComponent pattern — thin JSX-to-HTML pass-throughs with k attribute styling hooks
  • Layout components use CSS custom properties for gap control, enabling token-based spacing without per-instance JS state
  • Form validation leverages native HTML Constraint Validation API (:user-invalid, required, type, pattern, etc.) — no validation library
  • Chat components (Message, Thread, Composer) compose existing primitives (e.g., Composer wraps Textarea)
  • Hotkey and command systems use delegated event listeners to avoid per-instance overhead
  • Benchmarking splits JS and CSS sizes separately to track the library's performance-first discipline

https://claude.ai/code/session_01ScFTtdr4ETgSEGEYG5Hopr

claude added 30 commits June 16, 2026 13:33
A long-horizon, ID-stamped execution plan for extending Kinu (layout
primitives, controls, display, conversation surface, convenience
compositions, platform enhancements, and cross-cutting functionality),
validated against the current component tree. Includes the Kinu Test, a
Definition-of-Done runbook, platform-gating policy, and phased sequencing.
Parks the Popover-API overlay migration and records withdrawn proposals.
…olve FUN-5/DIS-4

- Add §0.7 execution discipline: one item at a time, JS-primary/CSS-secondary
  min+gzip deltas recorded per item; update CON-5 and DoD #12 accordingly.
- FUN-5: keep hand-maintained dark palette + HSL-triplet format; defer light-dark(),
  forward path via CSS Custom Functions (@function) preserving the triplet/alpha format.
- DIS-4: Code becomes a shipped component with an opt-in highlighting plugin seam.
- Add §12 decisions log capturing the above.
biome 1.9's experimental CSS parser cannot handle Kinu's deliberate modern
CSS (attr(... type(<number>)), @position-try, nested @starting-style),
producing 21 false-positive parse errors. Disable biome's CSS linter
(tsc remains the type gate; CI gates size, not lint) and fix the 10 real
JS/TS nits it surfaced in demo/docs:
- 6 decorative <svg> get explicit aria-hidden="true" (matches existing usage)
- 4 array-index keys replaced with stable keys (RaceStage.note, budget.label,
  mapped row value)

pnpm lint now passes (tsc + biome, exit 0). No library bundle change.
JS Δ 0 B · CSS Δ 0 B (biome.json/demo/docs are not in dist).
Single source of truth for adding a component: the platform-first prime
directive, toolchain + gates, component folder anatomy, the
createSimpleComponent factory and k-attribute styling model, the docs
wiring checklist (barrel export, metadata.mjs, examples/<name>.tsx), the
Definition-of-Done gate table, and the size-first commit discipline
(record gzipped JS Δ / CSS Δ in every src/ commit). Linked from AGENTS.md
alongside ROADMAP.md and ARCHITECTURE.md.

JS Δ 0 B · CSS Δ 0 B (docs only).
Introduce a 6-step --k-space-* scale (0/xs/sm/md/lg/xl → 0–40px) in
variables.css, placed with --k-radius in the root block so it persists
across light/dark. Step names mirror kinu's existing sm/md/lg size
convention so future layout primitives can map gap props directly to a
token. Documented in the Theming page with an override example; this also
makes the page's long-standing "spacing tokens" claim accurate.

JS Δ 0 B · CSS Δ +32 B (gzip, dist/index.css 10982→11014).
Codify how kinu adopts cutting-edge platform features without breaking
users: progressive enhancement over hard failure, native capability
detection over version sniffing (the installCommands() native no-op as the
model), SSR-safety by construction, documenting the baseline in component
notes, and no polyfill bloat by default. Grounded in existing practice
(ProgressRing typed attr(), Textarea field-sizing fallback, the commands
polyfill's three-guard install).

JS Δ 0 B · CSS Δ 0 B (docs only).
Codify the two shared mechanisms new interactive components must reuse
rather than reinventing: (1) the command/commandfor attribute model with
its layered, tree-shakeable, idempotent + SSR-safe installers in
src/lib/commands.ts; and (2) event-driven global singletons modeled on
toast (module-level dispatch + one mounted container, no provider/context,
SSR-safe to import).

JS Δ 0 B · CSS Δ 0 B (docs only).
Extend the size harness so size regressions are attributable per output and
per component:

- Report JS and CSS gzip (and raw) separately for every scenario instead of
  one combined total; totals still reconcile (1.85 / 3.62 / 14.57 KiB).
- Add a per-component matrix: enumerate src/components/* (skipping folders
  without an index, e.g. toast), build each in isolation with bounded
  concurrency, and emit a table sorted by gzip. 63 components in ~2.6s
  (vite warm-caches across in-process builds).
- Outputs land under benchmarks/size/.tmp/components/<name>/, which the CI
  compressed-size-action pattern ({dist,benchmarks/size/.tmp}/**) already
  matches — so per-component size deltas now surface automatically on PRs.
- BENCH_QUICK=1 / --quick skips the matrix for fast local iteration;
  BENCH_CONCURRENCY tunes the pool.
- Ignore benchmarks/size/.tmp in biome so the minified build artifacts the
  harness emits are never linted.

JS Δ 0 B · CSS Δ 0 B (benchmark tooling + config; nothing bundled).
CSS-only flex column with a token-based gap. One-line factory
(createSimpleComponent('stack','div')); all behaviour is attribute
selectors:
- gap: 0|xs|sm|md|lg|xl -> --k-gap -> --k-space-* (default md)
- align: start|center|end|stretch (align-items)
- justify: start|center|end|between|around|evenly (justify-content)

Wired into the barrel export, docs metadata + live example, and an SSR
smoke test (renders without a DOM). First component through the CON-5
per-component size matrix: isolated 1.39 KiB gzip.

JS Δ +17 B · CSS Δ +168 B (gzip, dist/).
CSS-only flex row with wrap for chip rows, button rows, and toolbars. Same
token-based gap mechanism as Stack; align defaults to center, gap to sm.
- gap: 0|xs|sm|md|lg|xl -> --k-gap -> --k-space-* (default sm)
- align: start|center|end|stretch|baseline (align-items, default center)
- justify: start|center|end|between|around|evenly

Barrel export, docs metadata + example (chip/button row), SSR smoke test.
Isolated 1.41 KiB gzip.

JS Δ +14 B · CSS Δ +125 B (gzip, dist/).
CSS-only auto-fit grid for dashboards and card galleries:
repeat(auto-fit, minmax(var(--k-grid-min,16rem), 1fr)).
- gap: 0|xs|sm|md|lg|xl -> --k-gap -> --k-space-* (default md)
- min: xs|sm|md|lg|xl column-width presets (10-24rem) -> --k-grid-min;
  override arbitrarily via the --k-grid-min custom property
- cols: 1-6 for a fixed equal-column grid (overrides auto-fit)

Barrel export, docs metadata + card-grid example, SSR smoke test.
Isolated 1.39 KiB gzip.

JS Δ +11 B · CSS Δ +195 B (gzip, dist/).
CSS grid named-area page scaffold with compound parts (AppShell.Header /
Sidebar / Main / Footer) rendered as semantic <header>/<aside>/<main>/
<footer>. min-height:100dvh; collapses to a single column at <=48rem where
the inline sidebar rail hides and mobile nav can hand off to the modal
Sidebar dialog. Zero JavaScript.

Barrel export, docs metadata + constrained shell example, SSR smoke test
covering all four parts. Isolated 1.44 KiB gzip.

Note: the roadmap's optional DoD demo migration (rebuild the Linear shell
route) is deferred to the demo-migration pass; this lands the component.

JS Δ +108 B · CSS Δ +108 B (gzip, dist/).
Run scripts/generate-docs.mjs to emit the generated docs artifacts for
Stack, Cluster, Grid, and AppShell (manifest.json entries consumed by the
demo + per-component markdown pages). Completes the docs half of the LAY-1/
2/4/7 DoD; subsequent components regenerate these in-commit.

JS Δ 0 B · CSS Δ 0 B (generated docs only).
Form-associated star rating built from a native radio group — keyboard
accessible and form-submittable with no custom JS event wiring. N radio +
label pairs render in descending DOM order so a CSS sibling combinator
fills the checked star and every lower one; flex row-reverse flips it back,
and :has() drives the hover preview. Inputs carry per-star aria-labels.
- name (required), value, count (default 5), readOnly, size (sm|md|lg)
- readOnly disables the inputs; :has(input:disabled) suppresses hover

Barrel export, docs metadata + example + generated page, SSR smoke tests
(interactive + read-only).

JS Δ +346 B · CSS Δ +189 B (gzip, dist/).
The generated per-component cases used `import * as C; void C;`, which let
the bundler tree-shake the component body away — leaving only the CSS
side-effect import and under-reporting JS for logic components (e.g. Rating
read 0.06 KiB gzip JS when its real cost is ~0.55). Switch the generated
entry to `export * from '<component>'` so the component is retained and its
cost-when-used is measured. Logic components now report real JS
(dropdown-menu 2.09, combobox 1.64, dialog 1.25 KiB gzip); pure-CSS
primitives are unchanged. This also makes the .tmp outputs the CI
compressed-size-action tracks reflect true per-component JS.

JS Δ 0 B · CSS Δ 0 B (benchmark tooling; nothing bundled).
Native <input type="number"> in an InputGroup with − / + buttons. The
buttons fire command="--step-down"/"--step-up" on the existing command bus;
the input is a factory component whose internal ref (4th-arg, the Carousel
pattern) listens for the bubbled `command` event and calls native
stepUp()/stepDown(), then dispatches input/change so forms stay in sync.
Zero new global listeners. Forwards every native input attribute.

Native Invoker Commands are Baseline; installCommands() is the old-Safari
fallback. Barrel export, docs metadata + example + generated page, SSR
smoke test.

JS Δ +231 B · CSS Δ +130 B (gzip, dist/).
One-tap copy-to-clipboard button. A factory button whose internal ref wires
click -> navigator.clipboard.writeText, then toggles a [copied] attribute
for ~1.2s. The idle/copied labels render via CSS attr() (data-label /
data-copied), so the success state needs no JS text swap. Copies `value`,
or the textContent of the element matched by the `for` selector.

SSR-safe: navigator is only touched inside the click handler. Barrel
export, docs metadata + example + generated page, SSR smoke test.

JS Δ +207 B · CSS Δ +129 B (gzip, dist/).
Pure-CSS metric block with compound parts Stat.Label, Stat.Value, and
Stat.Delta. Stat.Delta takes trend (up|down|flat), colored via the semantic
success/destructive tokens through an attribute selector. Composes with
Grid for dashboard stat rows. Zero JavaScript.

Barrel export, docs metadata + example + generated page, SSR smoke test.

JS Δ +70 B · CSS Δ +68 B (gzip, dist/).
Wire the forms layer to native constraint validation with no JS validation
logic and no "touched" state:
- Add :user-invalid / [invalid] destructive styling to Textarea, Select,
  and Checkbox, matching the existing Input/NumberField/OTP pattern.
- Field.Error is now hidden until the field is invalid — it reveals on
  :has(:user-invalid) or :has([invalid]) (server-side errors), and keeps its
  role="alert". The label already reddens via :has(:user-invalid).
- New docs/pages/forms.md documenting the :user-invalid timing, the Field +
  Field.Error contract, custom/server messages, and the submit contract.

:user-invalid is Baseline; :user-valid is left unstyled for apps to use.

JS Δ +0 B · CSS Δ +73 B (gzip, dist/).
Productize the "intuitive for LLMs" contract so it never drifts again:
- scripts/gen-llms.mjs builds llms.txt (a static preamble +
  scripts/llms-preamble.md, plus an always-current component reference) and
  a machine-readable components.json from docs/metadata.mjs. Run on every
  `pnpm build`, so adding a component updates the contract automatically.
- Fix the long-standing drift: the old hand-maintained llms.txt claimed the
  attribute was `p` ("the p stands for kinu"); the code emits `k`. The
  generated copy is correct and now covers all 71 components (the old one
  predated Stack/Grid/Stat/Rating/CopyButton/NumberField/…).
- Ship it: add `./llms.txt` and `./components.json` package exports + files
  entries, so `kinu/llms.txt` resolves for agents.
- Regenerate demo/public/llms.txt (served by the docs site).

JS Δ 0 B · CSS Δ 0 B (tooling + generated docs; nothing bundled).
CSS-only flex row — the horizontal sibling of Stack. Same token-based gap;
align defaults to center, gap to sm, no wrap by default (pass wrap, or use
Cluster when wrapping is the point). Kept separate from Stack[direction]
for LLM legibility per the roadmap.

Barrel export, docs metadata + example + generated page, SSR smoke test.

JS Δ +9 B · CSS Δ +102 B (gzip, dist/).
CSS-only centering via display:grid;place-items:center. Pass inline to
shrink-wrap and center inline. Zero JavaScript.

Barrel export, docs metadata + example + generated page, SSR smoke test.

JS Δ +14 B · CSS Δ +22 B (gzip, dist/).
CSS-only flex spacer. Default flex:1 grows to push siblings to opposite
ends of a Row/Cluster/Stack; pass size (xs-xl) for a fixed gap (via
flex-basis, so it works along either axis). Completes the LAY family.

Barrel export, docs metadata + example + generated page, llms regen, SSR
smoke test.

JS Δ +5 B · CSS Δ +58 B (gzip, dist/).
Pure-CSS horizontal stepper: <ol k="steps"> + <li k="step"> with
CSS-counter numbered markers and flex line connectors, zero JavaScript.
Stepper.Step takes state (upcoming|current|complete) -> data-state, which
drives the marker (number vs check), the primary outline for current, and
the connector color for traversed steps.

Barrel export, docs metadata + example + generated page, llms regen, SSR
smoke test.

JS Δ +74 B · CSS Δ +233 B (gzip, dist/).
Pure-CSS chat message bubble. <div k="message" from="user|assistant|
system"> drives alignment (user flips to the right) and bubble color
(user = primary, assistant = muted, system = quiet italic). Compound parts
Message.Avatar (round badge) and Message.Bubble (content; drop a <Prose>
inside for markdown). Zero JavaScript.

Barrel export, docs metadata (new Conversation category) + example +
generated page, llms regen, SSR smoke test.

JS Δ +62 B · CSS Δ +114 B (gzip, dist/).
A scroll container that pins to the latest message via native scroll
anchoring: children opt out of anchoring and a 1px bottom anchor element
keeps the viewport at the bottom as messages are appended — no scrollTo
loop, no JavaScript. Pass scrollable to enable; degrades to a normal scroll
container where anchoring is unsupported.

Barrel export, docs metadata + example + generated page, llms regen, SSR
smoke test.

JS Δ +60 B · CSS Δ +47 B (gzip, dist/).
A <form k="composer"> around an autosizing Textarea. Enter submits,
Shift+Enter inserts a newline — one delegated keydown calls
form.requestSubmit(), guarded against IME composition. Compound parts
Composer.Send (submit button on the trailing edge) and Composer.Actions
(row for attach/model controls). No chat engine: typing indicator is
Spinner, suggestions are a Cluster of Chip; bring your own submit handler.

Also types Textarea's documented `autosize` prop, which was missing from
TextareaOwnProps (surfaced because docs examples aren't tsc-checked).

Barrel export, docs metadata + example + generated page, llms regen, SSR
smoke test.

JS Δ +146 B · CSS Δ +151 B (gzip, dist/).
<form k="form"> with no form-state engine. On submit it runs native
checkValidity(): if invalid it blocks submission and focuses the first
invalid control; if valid it calls onValid with the event. Pairs with the
:user-invalid CSS layer (FUN-1) and Field/Field.Error — no touched/errors
state to manage. Repurposes the orphaned legacy examples/form.tsx.

Barrel export, docs metadata + example + generated page, llms regen, SSR
smoke test.

JS Δ +88 B · CSS Δ +7 B (gzip, dist/).
A command palette assembled entirely from shipped parts: a modal Dialog
hosting a Listbox. The Listbox provides substring filtering (Command.Input)
and keyboard navigation (installMenuShortcuts); the Dialog provides the
modal + focus trap. Command.Input/List alias ListboxInput/ListboxList and
Command.Item is Item, so items keep shortcut/destructive/href. No fuzzy
engine, no new state. Place inside <Dialog> and open via trigger or hotkey.

Barrel export, docs metadata + example + generated page, llms regen, SSR
smoke test.

JS Δ +49 B · CSS Δ +147 B (gzip, dist/).
A tags/token input that submits natively: a Cluster-like box of Chips plus a
text field, mirrored into a hidden form input. The one place a little array
state is honest — a single per-mount ref manages the chips imperatively (no
framework store), reading config from data-* attributes so it stays
module-scoped and SSR-safe. Enter (or the separator) adds a tag, Backspace
on empty removes the last, a chip's × removes it; every change rewrites the
hidden field and dispatches input/change. API: name, value, separator, max,
duplicates. Submitted value is the tags joined by separator.

Imports Chip's CSS so it's styled standalone. Barrel export, docs metadata
+ example + generated page, llms regen, SSR smoke test.

JS Δ +740 B · CSS Δ +106 B (gzip, dist/).
claude added 10 commits June 21, 2026 02:07
Native <input type="password"> in an InputGroup with a Show/Hide toggle.
The toggle rides the command bus (command="--toggle-password", like
NumberField): a per-input ref flips the type and a [revealed] attribute,
and the toggle's label follows via the adjacent-sibling combinator. No new
global listeners, SSR-safe. Forwards native input attributes; pass
defaultRevealed to start visible.

Barrel export, docs metadata + example + generated page, llms regen, SSR
smoke test.

JS Δ +206 B · CSS Δ +139 B (gzip, dist/).
Pure-CSS corner overlay: a <span k="indicator"> that positions a Badge
child (or a [dot]) at a corner of whatever it wraps — Avatar, Button, icon.
placement = top-end (default) | top-start | bottom-end | bottom-start; dot
renders a small status dot with no count. Zero JavaScript.

Barrel export, docs metadata + example + generated page, llms regen, SSR
smoke test.

JS Δ +14 B · CSS Δ +148 B (gzip, dist/).
Add a composable [k="alert"][banner] modifier — full-bleed, square
corners, page-level horizontal inset — for page-level banners. Implemented
as a boolean attribute (not a tone variant) so it composes with any tone,
e.g. <Alert variant="info" banner>. Replaces the proposed standalone
Banner component. CSS-only.

JS Δ +0 B · CSS Δ +35 B (gzip, dist/).
Pure-CSS chrome over <pre> (block) / <code inline> (inline): mono font,
surface, radius, horizontal scroll, zero JS for the base. Code.Copy is a
corner button (revealed on hover) that copies the enclosing block; its
label renders via CSS ::after so it adds nothing to the copied text. No
highlighter in core — the seam is the advisory [language] attribute (an
opt-in plugin can target [k="code"][language]) and/or pre-highlighted
children.

Barrel export, docs metadata + example + generated page, llms regen, SSR
smoke test.

JS Δ +85 B · CSS Δ +200 B (gzip, dist/).
Add a @supports (appearance: base-select) block to select/style.css that
upgrades Select to a fully stylable dropdown on Chromium — themed
::picker(select), hover/focus/checked option states, hidden default
checkmark, and a rotating picker icon — using kinu tokens. Gated, so it
degrades to the native styled <select> everywhere else with zero added
JavaScript and zero risk (CON-3). No API change.

JS Δ +0 B · CSS Δ +157 B (gzip, dist/).
A global keydown singleton (installHotkeys, CON-4 pattern) plus a <Hotkey>
that renders a hidden command button tagged with the chord. On match the
listener clicks it, firing its command on the bus — so keyboard shortcuts
reuse command/commandfor with no per-app key handlers and no JS registry
(the DOM is the registry). Chord syntax: mod (⌘/Ctrl), alt, shift + key;
bare keys ignored while typing. SSR-safe; pairs with Command and Kbd.

Barrel export (+ installHotkeys/normalizeChord), docs metadata + example +
generated page, llms regen, SSR smoke test.

JS Δ +481 B · CSS Δ +10 B (gzip, dist/).
Ship a tiny transition(cb) helper that runs a DOM update inside a View
Transition where supported and falls back to a synchronous update otherwise
(SSR-safe). Formalize the existing --k-ease-* motion tokens and document
view-transition-name conventions and the cross-document @view-transition
recipe in a new Motion & View Transitions page. Exported from kinu.

Adds a real unit test for normalizeChord + transition.

JS Δ +53 B · CSS Δ +0 B (gzip, dist/).
Productize theming per the FUN-5 plan (keeping the HSL-triplet format and
hand-maintained dark palette — no light-dark(), per the decision log):
- Document the --k-* tokens as a stable public contract in the Theming page
  (grouped token table + the h s l triplet/alpha convention).
- Ship two importable preset brand themes, kinu/themes/violet.css and
  kinu/themes/emerald.css, each overriding only the brand tokens across the
  light, system-dark, and explicit-dark scopes; added package exports + files.
- Fix a Theming doc bug: dark mode uses data-color-scheme, not data-theme.

JS Δ 0 B · CSS Δ 0 B (standalone theme CSS + docs; not in the bundle).
- Add a --k-density scalar (default 1) that multiplies control heights/
  padding; convert Button's md size as the reference (calc(... *
  var(--k-density))), unchanged at the default.
- Restore a system-color focus outline under forced-colors (Windows High
  Contrast) in base.css, where box-shadow focus rings are dropped, for the
  interactive components.
- Document density, RTL (components already use logical properties, so they
  mirror under dir=rtl), and forced-colors guidance in the Theming page.

JS Δ +0 B · CSS Δ +93 B (gzip, dist/).
Add a [virtual] base rule that applies content-visibility:auto +
contain-intrinsic-size to a container's rows, so List/Listbox/Tree (or any
[k] wrapper) render thousands of rows smoothly without a JS virtualizer.
Row-height estimate overridable via --k-virtual-row. Documented as a recipe
in the Base Styles page. Pure CSS, degrades gracefully where unsupported.

JS Δ +0 B · CSS Δ +42 B (gzip, dist/).
@netlify

netlify Bot commented Jun 21, 2026

Copy link
Copy Markdown

Deploy Preview for kinu-sh ready!

Name Link
🔨 Latest commit 3799926
🔍 Latest deploy log https://app.netlify.com/projects/kinu-sh/deploys/6a375b0077148b0008c0aea5
😎 Deploy Preview https://deploy-preview-131--kinu-sh.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions

github-actions Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Size Change: +171 kB (+454.66%) 🆘

Total Size: 209 kB

📦 View Changed
Filename Size Change
benchmarks/size/.tmp/components/accordion/bundle.css 1.37 kB +1.37 kB (new file) 🆕
benchmarks/size/.tmp/components/accordion/bundle.js 353 B +353 B (new file) 🆕
benchmarks/size/.tmp/components/alert-dialog/bundle.css 1.23 kB +1.23 kB (new file) 🆕
benchmarks/size/.tmp/components/alert-dialog/bundle.js 1.27 kB +1.27 kB (new file) 🆕
benchmarks/size/.tmp/components/alert/bundle.css 1.06 kB +1.06 kB (new file) 🆕
benchmarks/size/.tmp/components/alert/bundle.js 343 B +343 B (new file) 🆕
benchmarks/size/.tmp/components/app-shell/bundle.css 1.06 kB +1.06 kB (new file) 🆕
benchmarks/size/.tmp/components/app-shell/bundle.js 446 B +446 B (new file) 🆕
benchmarks/size/.tmp/components/aspect-ratio/bundle.css 972 B +972 B (new file) 🆕
benchmarks/size/.tmp/components/aspect-ratio/bundle.js 231 B +231 B (new file) 🆕
benchmarks/size/.tmp/components/avatar/bundle.css 1.15 kB +1.15 kB (new file) 🆕
benchmarks/size/.tmp/components/avatar/bundle.js 479 B +479 B (new file) 🆕
benchmarks/size/.tmp/components/badge/bundle.css 1.18 kB +1.18 kB (new file) 🆕
benchmarks/size/.tmp/components/badge/bundle.js 350 B +350 B (new file) 🆕
benchmarks/size/.tmp/components/breadcrumb/bundle.css 1.03 kB +1.03 kB (new file) 🆕
benchmarks/size/.tmp/components/breadcrumb/bundle.js 411 B +411 B (new file) 🆕
benchmarks/size/.tmp/components/button/bundle.css 1.57 kB +1.57 kB (new file) 🆕
benchmarks/size/.tmp/components/button/bundle.js 359 B +359 B (new file) 🆕
benchmarks/size/.tmp/components/calendar/bundle.css 941 B +941 B (new file) 🆕
benchmarks/size/.tmp/components/calendar/bundle.js 524 B +524 B (new file) 🆕
benchmarks/size/.tmp/components/card/bundle.css 1.01 kB +1.01 kB (new file) 🆕
benchmarks/size/.tmp/components/card/bundle.js 345 B +345 B (new file) 🆕
benchmarks/size/.tmp/components/carousel/bundle.css 1.21 kB +1.21 kB (new file) 🆕
benchmarks/size/.tmp/components/carousel/bundle.js 1.42 kB +1.42 kB (new file) 🆕
benchmarks/size/.tmp/components/center/bundle.css 942 B +942 B (new file) 🆕
benchmarks/size/.tmp/components/center/bundle.js 347 B +347 B (new file) 🆕
benchmarks/size/.tmp/components/checkbox/bundle.css 1.21 kB +1.21 kB (new file) 🆕
benchmarks/size/.tmp/components/checkbox/bundle.js 523 B +523 B (new file) 🆕
benchmarks/size/.tmp/components/chip/bundle.css 1.4 kB +1.4 kB (new file) 🆕
benchmarks/size/.tmp/components/chip/bundle.js 614 B +614 B (new file) 🆕
benchmarks/size/.tmp/components/cluster/bundle.css 1.13 kB +1.13 kB (new file) 🆕
benchmarks/size/.tmp/components/cluster/bundle.js 349 B +349 B (new file) 🆕
benchmarks/size/.tmp/components/code/bundle.css 1.3 kB +1.3 kB (new file) 🆕
benchmarks/size/.tmp/components/code/bundle.js 778 B +778 B (new file) 🆕
benchmarks/size/.tmp/components/collapsible/bundle.css 1.07 kB +1.07 kB (new file) 🆕
benchmarks/size/.tmp/components/collapsible/bundle.js 621 B +621 B (new file) 🆕
benchmarks/size/.tmp/components/color-picker/bundle.css 1.11 kB +1.11 kB (new file) 🆕
benchmarks/size/.tmp/components/color-picker/bundle.js 529 B +529 B (new file) 🆕
benchmarks/size/.tmp/components/combobox/bundle.css 2.36 kB +2.36 kB (new file) 🆕
benchmarks/size/.tmp/components/combobox/bundle.js 1.68 kB +1.68 kB (new file) 🆕
benchmarks/size/.tmp/components/command/bundle.css 1.74 kB +1.74 kB (new file) 🆕
benchmarks/size/.tmp/components/command/bundle.js 2.39 kB +2.39 kB (new file) 🆕
benchmarks/size/.tmp/components/composer/bundle.css 1.27 kB +1.27 kB (new file) 🆕
benchmarks/size/.tmp/components/composer/bundle.js 737 B +737 B (new file) 🆕
benchmarks/size/.tmp/components/context-menu/bundle.css 2.43 kB +2.43 kB (new file) 🆕
benchmarks/size/.tmp/components/context-menu/bundle.js 1.49 kB +1.49 kB (new file) 🆕
benchmarks/size/.tmp/components/copy-button/bundle.css 1.2 kB +1.2 kB (new file) 🆕
benchmarks/size/.tmp/components/copy-button/bundle.js 908 B +908 B (new file) 🆕
benchmarks/size/.tmp/components/date-picker/bundle.css 944 B +944 B (new file) 🆕
benchmarks/size/.tmp/components/date-picker/bundle.js 528 B +528 B (new file) 🆕
benchmarks/size/.tmp/components/dialog/bundle.css 1.23 kB +1.23 kB (new file) 🆕
benchmarks/size/.tmp/components/dialog/bundle.js 1.28 kB +1.28 kB (new file) 🆕
benchmarks/size/.tmp/components/drawer/bundle.css 1.18 kB +1.18 kB (new file) 🆕
benchmarks/size/.tmp/components/drawer/bundle.js 1.18 kB +1.18 kB (new file) 🆕
benchmarks/size/.tmp/components/dropdown-menu/bundle.css 2.29 kB +2.29 kB (new file) 🆕
benchmarks/size/.tmp/components/dropdown-menu/bundle.js 2.14 kB +2.14 kB (new file) 🆕
benchmarks/size/.tmp/components/empty/bundle.css 1.03 kB +1.03 kB (new file) 🆕
benchmarks/size/.tmp/components/empty/bundle.js 343 B +343 B (new file) 🆕
benchmarks/size/.tmp/components/field/bundle.css 1.08 kB +1.08 kB (new file) 🆕
benchmarks/size/.tmp/components/field/bundle.js 586 B +586 B (new file) 🆕
benchmarks/size/.tmp/components/file-upload/bundle.css 1.07 kB +1.07 kB (new file) 🆕
benchmarks/size/.tmp/components/file-upload/bundle.js 529 B +529 B (new file) 🆕
benchmarks/size/.tmp/components/form/bundle.css 920 B +920 B (new file) 🆕
benchmarks/size/.tmp/components/form/bundle.js 527 B +527 B (new file) 🆕
benchmarks/size/.tmp/components/grid/bundle.css 1.11 kB +1.11 kB (new file) 🆕
benchmarks/size/.tmp/components/grid/bundle.js 345 B +345 B (new file) 🆕
benchmarks/size/.tmp/components/hotkey/bundle.css 915 B +915 B (new file) 🆕
benchmarks/size/.tmp/components/hotkey/bundle.js 1.51 kB +1.51 kB (new file) 🆕
benchmarks/size/.tmp/components/hover-card/bundle.css 1.17 kB +1.17 kB (new file) 🆕
benchmarks/size/.tmp/components/hover-card/bundle.js 404 B +404 B (new file) 🆕
benchmarks/size/.tmp/components/indicator/bundle.css 1.14 kB +1.14 kB (new file) 🆕
benchmarks/size/.tmp/components/indicator/bundle.js 353 B +353 B (new file) 🆕
benchmarks/size/.tmp/components/input-group/bundle.css 1.24 kB +1.24 kB (new file) 🆕
benchmarks/size/.tmp/components/input-group/bundle.js 359 B +359 B (new file) 🆕
benchmarks/size/.tmp/components/input/bundle.css 1.25 kB +1.25 kB (new file) 🆕
benchmarks/size/.tmp/components/input/bundle.js 571 B +571 B (new file) 🆕
benchmarks/size/.tmp/components/item/bundle.css 1.22 kB +1.22 kB (new file) 🆕
benchmarks/size/.tmp/components/item/bundle.js 619 B +619 B (new file) 🆕
benchmarks/size/.tmp/components/kbd/bundle.css 1.07 kB +1.07 kB (new file) 🆕
benchmarks/size/.tmp/components/kbd/bundle.js 345 B +345 B (new file) 🆕
benchmarks/size/.tmp/components/label/bundle.css 977 B +977 B (new file) 🆕
benchmarks/size/.tmp/components/label/bundle.js 347 B +347 B (new file) 🆕
benchmarks/size/.tmp/components/list/bundle.css 1.3 kB +1.3 kB (new file) 🆕
benchmarks/size/.tmp/components/list/bundle.js 1.14 kB +1.14 kB (new file) 🆕
benchmarks/size/.tmp/components/listbox/bundle.css 1.37 kB +1.37 kB (new file) 🆕
benchmarks/size/.tmp/components/listbox/bundle.js 1.39 kB +1.39 kB (new file) 🆕
benchmarks/size/.tmp/components/menubar/bundle.css 993 B +993 B (new file) 🆕
benchmarks/size/.tmp/components/menubar/bundle.js 645 B +645 B (new file) 🆕
benchmarks/size/.tmp/components/message/bundle.css 1.17 kB +1.17 kB (new file) 🆕
benchmarks/size/.tmp/components/message/bundle.js 401 B +401 B (new file) 🆕
benchmarks/size/.tmp/components/meter/bundle.css 1.08 kB +1.08 kB (new file) 🆕
benchmarks/size/.tmp/components/meter/bundle.js 346 B +346 B (new file) 🆕
benchmarks/size/.tmp/components/navigation-menu/bundle.css 1.02 kB +1.02 kB (new file) 🆕
benchmarks/size/.tmp/components/navigation-menu/bundle.js 409 B +409 B (new file) 🆕
benchmarks/size/.tmp/components/number-field/bundle.css 2.04 kB +2.04 kB (new file) 🆕
benchmarks/size/.tmp/components/number-field/bundle.js 1.36 kB +1.36 kB (new file) 🆕
benchmarks/size/.tmp/components/otp/bundle.css 1.22 kB +1.22 kB (new file) 🆕
benchmarks/size/.tmp/components/otp/bundle.js 578 B +578 B (new file) 🆕
benchmarks/size/.tmp/components/pagination/bundle.css 1.05 kB +1.05 kB (new file) 🆕
benchmarks/size/.tmp/components/pagination/bundle.js 410 B +410 B (new file) 🆕
benchmarks/size/.tmp/components/password-input/bundle.css 1.48 kB +1.48 kB (new file) 🆕
benchmarks/size/.tmp/components/password-input/bundle.js 1.32 kB +1.32 kB (new file) 🆕
benchmarks/size/.tmp/components/popover/bundle.css 1.87 kB +1.87 kB (new file) 🆕
benchmarks/size/.tmp/components/popover/bundle.js 1.26 kB +1.26 kB (new file) 🆕
benchmarks/size/.tmp/components/progress-ring/bundle.css 1.39 kB +1.39 kB (new file) 🆕
benchmarks/size/.tmp/components/progress-ring/bundle.js 356 B +356 B (new file) 🆕
benchmarks/size/.tmp/components/progress/bundle.css 1.03 kB +1.03 kB (new file) 🆕
benchmarks/size/.tmp/components/progress/bundle.js 347 B +347 B (new file) 🆕
benchmarks/size/.tmp/components/prose/bundle.css 1.29 kB +1.29 kB (new file) 🆕
benchmarks/size/.tmp/components/prose/bundle.js 342 B +342 B (new file) 🆕
benchmarks/size/.tmp/components/radio-group/bundle.css 1.19 kB +1.19 kB (new file) 🆕
benchmarks/size/.tmp/components/radio-group/bundle.js 540 B +540 B (new file) 🆕
benchmarks/size/.tmp/components/rating/bundle.css 1.4 kB +1.4 kB (new file) 🆕
benchmarks/size/.tmp/components/rating/bundle.js 728 B +728 B (new file) 🆕
benchmarks/size/.tmp/components/resizable/bundle.css 975 B +975 B (new file) 🆕
benchmarks/size/.tmp/components/resizable/bundle.js 353 B +353 B (new file) 🆕
benchmarks/size/.tmp/components/row/bundle.css 1.13 kB +1.13 kB (new file) 🆕
benchmarks/size/.tmp/components/row/bundle.js 345 B +345 B (new file) 🆕
benchmarks/size/.tmp/components/scroll-area/bundle.css 51 B +51 B (new file) 🆕
benchmarks/size/.tmp/components/scroll-area/bundle.js 355 B +355 B (new file) 🆕
benchmarks/size/.tmp/components/select/bundle.css 1.57 kB +1.57 kB (new file) 🆕
benchmarks/size/.tmp/components/select/bundle.js 347 B +347 B (new file) 🆕
benchmarks/size/.tmp/components/separator/bundle.css 936 B +936 B (new file) 🆕
benchmarks/size/.tmp/components/separator/bundle.js 351 B +351 B (new file) 🆕
benchmarks/size/.tmp/components/sheet/bundle.css 1.2 kB +1.2 kB (new file) 🆕
benchmarks/size/.tmp/components/sheet/bundle.js 1.18 kB +1.18 kB (new file) 🆕
benchmarks/size/.tmp/components/sidebar/bundle.css 1.52 kB +1.52 kB (new file) 🆕
benchmarks/size/.tmp/components/sidebar/bundle.js 1.44 kB +1.44 kB (new file) 🆕
benchmarks/size/.tmp/components/skeleton/bundle.css 1.08 kB +1.08 kB (new file) 🆕
benchmarks/size/.tmp/components/skeleton/bundle.js 349 B +349 B (new file) 🆕
benchmarks/size/.tmp/components/slider/bundle.css 1.18 kB +1.18 kB (new file) 🆕
benchmarks/size/.tmp/components/slider/bundle.js 657 B +657 B (new file) 🆕
benchmarks/size/.tmp/components/spacer/bundle.css 958 B +958 B (new file) 🆕
benchmarks/size/.tmp/components/spacer/bundle.js 347 B +347 B (new file) 🆕
benchmarks/size/.tmp/components/spinner/bundle.css 2.31 kB +2.31 kB (new file) 🆕
benchmarks/size/.tmp/components/spinner/bundle.js 350 B +350 B (new file) 🆕
benchmarks/size/.tmp/components/stack/bundle.css 1.11 kB +1.11 kB (new file) 🆕
benchmarks/size/.tmp/components/stack/bundle.js 343 B +343 B (new file) 🆕
benchmarks/size/.tmp/components/stat/bundle.css 1.06 kB +1.06 kB (new file) 🆕
benchmarks/size/.tmp/components/stat/bundle.js 420 B +420 B (new file) 🆕
benchmarks/size/.tmp/components/status/bundle.css 1.55 kB +1.55 kB (new file) 🆕
benchmarks/size/.tmp/components/status/bundle.js 348 B +348 B (new file) 🆕
benchmarks/size/.tmp/components/stepper/bundle.css 1.28 kB +1.28 kB (new file) 🆕
benchmarks/size/.tmp/components/stepper/bundle.js 460 B +460 B (new file) 🆕
benchmarks/size/.tmp/components/switch/bundle.css 1.2 kB +1.2 kB (new file) 🆕
benchmarks/size/.tmp/components/switch/bundle.js 536 B +536 B (new file) 🆕
benchmarks/size/.tmp/components/table/bundle.css 1.03 kB +1.03 kB (new file) 🆕
benchmarks/size/.tmp/components/table/bundle.js 345 B +345 B (new file) 🆕
benchmarks/size/.tmp/components/tabs/bundle.css 1.5 kB +1.5 kB (new file) 🆕
benchmarks/size/.tmp/components/tabs/bundle.js 389 B +389 B (new file) 🆕
benchmarks/size/.tmp/components/tags-input/bundle.css 1.58 kB +1.58 kB (new file) 🆕
benchmarks/size/.tmp/components/tags-input/bundle.js 1.56 kB +1.56 kB (new file) 🆕
benchmarks/size/.tmp/components/textarea/bundle.css 1.22 kB +1.22 kB (new file) 🆕
benchmarks/size/.tmp/components/textarea/bundle.js 349 B +349 B (new file) 🆕
benchmarks/size/.tmp/components/thread/bundle.css 1.01 kB +1.01 kB (new file) 🆕
benchmarks/size/.tmp/components/thread/bundle.js 462 B +462 B (new file) 🆕
benchmarks/size/.tmp/components/time-picker/bundle.css 944 B +944 B (new file) 🆕
benchmarks/size/.tmp/components/time-picker/bundle.js 529 B +529 B (new file) 🆕
benchmarks/size/.tmp/components/timeline/bundle.css 1.23 kB +1.23 kB (new file) 🆕
benchmarks/size/.tmp/components/timeline/bundle.js 372 B +372 B (new file) 🆕
benchmarks/size/.tmp/components/toggle-group/bundle.css 1.05 kB +1.05 kB (new file) 🆕
benchmarks/size/.tmp/components/toggle-group/bundle.js 355 B +355 B (new file) 🆕
benchmarks/size/.tmp/components/toggle/bundle.css 1.18 kB +1.18 kB (new file) 🆕
benchmarks/size/.tmp/components/toggle/bundle.js 676 B +676 B (new file) 🆕
benchmarks/size/.tmp/components/tooltip/bundle.css 1.34 kB +1.34 kB (new file) 🆕
benchmarks/size/.tmp/components/tooltip/bundle.js 349 B +349 B (new file) 🆕
benchmarks/size/.tmp/components/tree/bundle.css 1.45 kB +1.45 kB (new file) 🆕
benchmarks/size/.tmp/components/tree/bundle.js 449 B +449 B (new file) 🆕
benchmarks/size/.tmp/components/typography/bundle.css 958 B +958 B (new file) 🆕
benchmarks/size/.tmp/components/typography/bundle.js 21 B +21 B (new file) 🆕
benchmarks/size/.tmp/few-components/bundle.css 3.1 kB +64 B (+2.11%)
benchmarks/size/.tmp/nearly-all-components/bundle.css 14 kB +3.12 kB (+28.61%) 🚨
benchmarks/size/.tmp/nearly-all-components/bundle.js 5.77 kB +1.77 kB (+44.3%) 🚨
benchmarks/size/.tmp/one-component/bundle.css 1.57 kB +56 B (+3.69%)
dist/index.css 14.1 kB +3.15 kB (+28.84%) 🚨
dist/index.js 9.21 kB +2.87 kB (+45.18%) 🚨
ℹ️ View Unchanged
Filename Size
benchmarks/size/.tmp/few-components/bundle.js 637 B
benchmarks/size/.tmp/one-component/bundle.js 341 B

compressed-size-action

Replace the N-radio + :has() star widget with a single styled
<input type="range"> and ZERO JavaScript. The fill follows the live value
entirely in CSS: a 1px thumb's huge box-shadow paints the filled stars on
WebKit, ::-moz-range-progress does it on Firefox, both masked into a star
row; the star count reads from `max` via typed attr() like ProgressRing.
One form-associated, keyboard-accessible element instead of 11.

Verified in-browser (Chrome): renders correctly across value/count/size/
readOnly, and the fill tracks the live value on native arrow-key input with
no script. API unchanged (name/value/count/readOnly/size).

Net vs the radio group: JS Δ -225 B · CSS Δ +124 B (gzip) — the
render loop + useId are gone.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants