# @kuhyx/web-ui
The shared token + component layer for kuhy's web apps — the web counterpart to
`~/src/utils/design_system` (Dart). Owns the frozen palette, the spacing/radius/type
scales, and the components that were each reimplemented in two or more repos.
Consumers import the tokens rather than transcribing the token table by hand.
Source of truth for the *values* is `~/src/utils/unified-design-system/DOCS-tokens.md`;
this package is its executable form for the web.
## Install
```jsonc
// package.json — pnpm only, see "Why the &path: suffix" below.
"dependencies": {
"@kuhyx/web-ui": "github:kuhyx/utils#web_ui-v0.5.0&path:/web_ui"
}
```
Astro is the only supported framework (`peerDependencies.astro >=7.4.0`).
```astro
---
// Layout / page frontmatter
import RangeSlider from "@kuhyx/web-ui/RangeSlider.astro";
import "@kuhyx/web-ui/tokens.css"; // once, in the shared layout
import "@kuhyx/web-ui/range-slider.css"; // only if you use RangeSlider
---
```
Pure helpers (`fuzzyMatch`, `quantileValue`, ...) come from
`import { fuzzyMatch } from "@kuhyx/web-ui";`. That entry point touches no DOM,
so it is safe in frontmatter.
### Why the `&path:/web_ui` suffix
`utils` is a monorepo with no root `package.json`, and **npm cannot install from
a subdirectory of a git repo** — `github:user/repo#tag` clones the root, looks
for `package.json` there, and fails with `ENOENT` (verified against npm 11.16).
pnpm supports the subdirectory via `&path:/
`, which is why both consumers
are pnpm. This is the only difference from the Dart (`git: {url, ref, path}`) and
Python (`#subdirectory=`) conventions the rest of `utils` follows.
### Why `dist/` is committed, and why `.astro` ships as source
tsc cannot emit `.astro`, so `src/RangeSlider.astro` ships as it is and Astro
compiles it from the dependency. Everything TypeScript ships prebuilt: the tag
carries `dist/` (ESM + `.d.ts`, `.ts` specifiers rewritten to `.js`), and the
`.astro` file imports `../dist/...`, never the `.ts` source. **`pnpm build`
before tagging, always** — a tag whose `dist/` is stale ships old code to every
consumer with no error.
## What's here
| Export | Notes |
| --- | --- |
| `tokens.css` | The `:root` block: palette, spacing, radius, type, shadows, focus ring. Also sets `:focus-visible` globally. |
| `RangeSlider.astro` | Server-rendered shell for ``. Props: `values`, `lo`, `hi`, `label`, `format` (server-side, first paint of the head only). Its `