first commit
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
# @wrnexus/ui
|
||||
|
||||
> First-party Wire UI component library — a set of themeable `.wrn` components plus a single tokenized stylesheet.
|
||||
|
||||
Part of the **WrNexus** framework — an SSR-first, Bun-native full-stack web framework.
|
||||
|
||||
## Overview
|
||||
|
||||
`@wrnexus/ui` ships a library of server-rendered `.wrn` components (layout, form
|
||||
controls, and feedback UI) together with one themeable stylesheet, `ui.css`. The
|
||||
components are **auto-discovered** by the framework router — you don't import them
|
||||
in code. Once the package's component directory is on the router's scan path, you
|
||||
mount any component in a page with `data-component="<name>"`. Every visual is
|
||||
driven by `var(--wire-*)` theme tokens, so components restyle instantly when the
|
||||
theme changes. The tiny JS surface (`src/index.ts`) exists only so the toolchain
|
||||
(CLI build + dev server) can locate the component directory and stylesheet.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
bun add @wrnexus/ui
|
||||
```
|
||||
|
||||
> Private package — the machine must be authenticated to the `wrnexus` npm org
|
||||
> (a read token in `~/.npmrc`). Requires **Bun** (Node is not supported).
|
||||
|
||||
In practice you rarely install this directly: `@wrnexus/cli` and
|
||||
`@wrnexus/dev-server` already depend on it and wire it into the router for you
|
||||
(see [Auto-discovery](#auto-discovery)).
|
||||
|
||||
## Components
|
||||
|
||||
Components live as `.wrn` files under `packages/ui/components/`. The mount name
|
||||
is the **lowercase file basename** (e.g. `button.wrn` → `data-component="button"`).
|
||||
Each accepts a `class` prop (appended to its root element) and most render their
|
||||
body from either a named prop or the default slot.
|
||||
|
||||
### Layout
|
||||
|
||||
| Name | Purpose | Key props |
|
||||
| ----------- | ---------------------------------- | ----------- |
|
||||
| `container` | Max-width centered content wrapper | `class` |
|
||||
| `stack` | Vertical column with gap | `gap` (0–8) |
|
||||
| `hstack` | Horizontal row with gap | `gap` (0–8) |
|
||||
| `grid` | CSS grid container | see source |
|
||||
| `divider` | Horizontal rule | `class` |
|
||||
| `spacer` | Flexible/empty spacing element | see source |
|
||||
|
||||
### Core / feedback
|
||||
|
||||
| Name | Purpose | Key props |
|
||||
| -------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| `button` | Button | `label`, `variant` (`default`\|`primary`\|`danger`\|`ghost`), `size` (`sm`\|`md`\|`lg`), `type` |
|
||||
| `input` | Text input | see source |
|
||||
| `textarea` | Multi-line input | see source |
|
||||
| `checkbox` | Checkbox | see source |
|
||||
| `badge` | Small status badge | `label`, `variant` |
|
||||
| `alert` | Callout box | `variant` (`info`\|`success`\|`danger`\|`warning`), `title`, `message` |
|
||||
| `card` | Padded, bordered surface | `class` |
|
||||
| `avatar` | User avatar | see source |
|
||||
| `spinner` | Loading indicator | see source |
|
||||
| `disclosure` | Expandable details/summary | see source |
|
||||
| `theme-toggle` | Theme switch button (binds `data-wire-theme-toggle`) | `label` |
|
||||
|
||||
### Additional controls & data display
|
||||
|
||||
Also shipped: `select`, `radio`, `switch`, `progress`, `tag`, `skeleton`,
|
||||
`tooltip`, and `table`.
|
||||
|
||||
The authoritative, always-current list is `uiComponentNames()` (below), which reads
|
||||
the component directory at runtime.
|
||||
|
||||
## API
|
||||
|
||||
The JS module (`@wrnexus/ui`) exposes four helpers used by the build tooling to
|
||||
locate the component assets. There is no component code to import — the components
|
||||
are `.wrn` files rendered server-side.
|
||||
|
||||
| Export | Signature | Returns |
|
||||
| ------------------ | ---------------- | ------------------------------------------------------------------------------------------ |
|
||||
| `uiComponentsDir` | `() => string` | Absolute path to the `.wrn` component directory (feed to `buildRouter`'s `componentDirs`). |
|
||||
| `uiCssPath` | `() => string` | Absolute path to `ui.css`. |
|
||||
| `uiCss` | `() => string` | The `ui.css` file contents (all `.wire-*` classes, themed via tokens). |
|
||||
| `uiComponentNames` | `() => string[]` | Sorted list of built-in component names (e.g. for `wrnexus eject` listing). |
|
||||
|
||||
### `./ui.css` asset export
|
||||
|
||||
`package.json` also exposes the raw stylesheet as a subpath asset:
|
||||
|
||||
```json
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./ui.css": "./ui.css"
|
||||
}
|
||||
```
|
||||
|
||||
The framework serves this stylesheet once at `/__wrnexus/ui.css`, so pages get all
|
||||
component styles from a single request.
|
||||
|
||||
## Usage
|
||||
|
||||
### Auto-discovery
|
||||
|
||||
The router scans extra `componentDirs` (in addition to the app's own
|
||||
`app/components`) and keys components by name. Library dirs are scanned **first**
|
||||
and `app/components` **last**, so an app component of the same name shadows the
|
||||
library's. The CLI build (`@wrnexus/cli`) and dev server (`@wrnexus/dev-server`)
|
||||
both wire the UI directory in for you:
|
||||
|
||||
```ts
|
||||
import { buildRouter } from "@wrnexus/router";
|
||||
import { uiComponentsDir } from "@wrnexus/ui";
|
||||
|
||||
const router = buildRouter(appDir, { componentDirs: [uiComponentsDir()] });
|
||||
```
|
||||
|
||||
### Mounting components in a page
|
||||
|
||||
Once discovered, mount any component by name via `data-component`. Quoted
|
||||
attributes (other than `data-component`) become string props:
|
||||
|
||||
```html
|
||||
<div data-component="card">
|
||||
<div data-component="badge" label="New"></div>
|
||||
<button data-component="button" label="Save" variant="primary" size="lg"></button>
|
||||
<div data-component="alert" variant="success" title="Done" message="Saved."></div>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Overrides
|
||||
|
||||
Ways to customize the components, in increasing order of power:
|
||||
|
||||
1. **Theme tokens** — override CSS custom properties such as `--wire-color-primary`,
|
||||
`--wire-color-surface`, `--wire-radius-sm`, etc. Every component style resolves
|
||||
through `var(--wire-*)`, so changing a token restyles everything instantly
|
||||
(including across theme switches).
|
||||
2. **App CSS** — redefine a `.wire-*` class in your own stylesheet, which is loaded
|
||||
after `ui.css` and therefore wins.
|
||||
3. **`class` prop** — pass a `class` prop to a component; it is appended to the
|
||||
component's root element, letting you add per-instance classes without touching
|
||||
the base styles.
|
||||
4. **`wrnexus eject <name>`** — copy the component's `.wrn` source into your
|
||||
`app/components`, where (because app components shadow library ones) you fully
|
||||
own and can edit it. Use `uiComponentNames()` for the list of ejectable names.
|
||||
|
||||
## Requirements / Notes
|
||||
|
||||
- **Bun-only** — the package uses standard fs/path/url APIs but is published and
|
||||
consumed within the Bun-native WrNexus toolchain (Node is not supported).
|
||||
- Peer packages: components are discovered and rendered by
|
||||
[`@wrnexus/router`](../router) (via `componentDirs`) and served by
|
||||
[`@wrnexus/dev-server`](../dev-server) / built by [`@wrnexus/cli`](../cli).
|
||||
- Depends on [`@wrnexus/core`](../core) (`dependencies`).
|
||||
- `theme-toggle` relies on the framework's theme runtime, which binds the
|
||||
`data-wire-theme-toggle` attribute — no per-component JS is required.
|
||||
Reference in New Issue
Block a user