@kode4/react-foundation 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DESIGN-SYSTEM.md +190 -0
- package/INSTRUCTIONS.md +694 -0
- package/LICENSE +21 -0
- package/README.md +53 -0
- package/errors.d.ts +24 -0
- package/forms/Form/Form.d.ts +30 -0
- package/forms/Form/index.d.ts +1 -0
- package/forms/index.d.ts +1 -0
- package/hooks/index.d.ts +1 -0
- package/hooks/useMediaQuery.d.ts +8 -0
- package/index.d.ts +24 -0
- package/index.js +1679 -0
- package/index.js.map +1 -0
- package/internal/env.d.ts +1 -0
- package/internal/registry.d.ts +3 -0
- package/internal/type-utils.d.ts +6 -0
- package/layout/AppLayout/AppLayout.d.ts +18 -0
- package/layout/AppLayout/index.d.ts +1 -0
- package/layout/CenteredLayout/CenteredLayout.d.ts +12 -0
- package/layout/CenteredLayout/index.d.ts +1 -0
- package/layout/Columns/Columns.d.ts +35 -0
- package/layout/Columns/index.d.ts +1 -0
- package/layout/Container/Container.d.ts +5 -0
- package/layout/Container/index.d.ts +1 -0
- package/layout/DashboardGrid/DashboardGrid.d.ts +37 -0
- package/layout/DashboardGrid/index.d.ts +1 -0
- package/layout/FillHeight/FillHeight.d.ts +16 -0
- package/layout/FillHeight/index.d.ts +1 -0
- package/layout/Footer/Footer.d.ts +5 -0
- package/layout/Footer/index.d.ts +1 -0
- package/layout/Header/Header.d.ts +13 -0
- package/layout/Header/index.d.ts +1 -0
- package/layout/SideBar/SideBar.d.ts +6 -0
- package/layout/SideBar/index.d.ts +1 -0
- package/layout/SiteLayout/SiteLayout.d.ts +27 -0
- package/layout/SiteLayout/index.d.ts +1 -0
- package/layout/SkipLink/SkipLink.d.ts +9 -0
- package/layout/SkipLink/index.d.ts +1 -0
- package/layout/TopBar/TopBar.d.ts +32 -0
- package/layout/TopBar/index.d.ts +1 -0
- package/layout/index.d.ts +12 -0
- package/package.json +52 -0
- package/query/index.d.ts +1 -0
- package/query/sort.d.ts +19 -0
- package/router/DefaultErrorBoundary.d.ts +5 -0
- package/router/TypedLink/TypedLink.d.ts +22 -0
- package/router/TypedLink/index.d.ts +1 -0
- package/router/adapter.d.ts +27 -0
- package/router/chain.d.ts +17 -0
- package/router/context.d.ts +24 -0
- package/router/createAppRouter.d.ts +15 -0
- package/router/defineRoute.d.ts +11 -0
- package/router/index.d.ts +11 -0
- package/router/menu.d.ts +51 -0
- package/router/pathTo.d.ts +21 -0
- package/router/types.d.ts +72 -0
- package/router/useRoute.d.ts +22 -0
- package/style.css +3 -0
- package/theme/ModeToggle/ModeToggle.d.ts +6 -0
- package/theme/ModeToggle/index.d.ts +1 -0
- package/theme/ThemeProvider/ThemeProvider.d.ts +25 -0
- package/theme/ThemeProvider/index.d.ts +1 -0
- package/theme/Toaster/Toaster.d.ts +9 -0
- package/theme/Toaster/index.d.ts +2 -0
- package/theme/Toaster/toast.d.ts +38 -0
- package/theme/index.d.ts +3 -0
- package/ui/Accordion/Accordion.d.ts +7 -0
- package/ui/Accordion/index.d.ts +1 -0
- package/ui/Alert/Alert.d.ts +11 -0
- package/ui/Alert/index.d.ts +1 -0
- package/ui/AlertDialog/AlertDialog.d.ts +19 -0
- package/ui/AlertDialog/index.d.ts +1 -0
- package/ui/Avatar/Avatar.d.ts +7 -0
- package/ui/Avatar/index.d.ts +1 -0
- package/ui/AwaitErrorBlock/AwaitErrorBlock.d.ts +11 -0
- package/ui/AwaitErrorBlock/index.d.ts +1 -0
- package/ui/Badge/Badge.d.ts +10 -0
- package/ui/Badge/index.d.ts +1 -0
- package/ui/Button/Button.d.ts +13 -0
- package/ui/Button/index.d.ts +1 -0
- package/ui/Card/Card.d.ts +11 -0
- package/ui/Card/index.d.ts +1 -0
- package/ui/Checkbox/Checkbox.d.ts +5 -0
- package/ui/Checkbox/index.d.ts +1 -0
- package/ui/Command/Command.d.ts +19 -0
- package/ui/Command/index.d.ts +1 -0
- package/ui/Dialog/Dialog.d.ts +17 -0
- package/ui/Dialog/index.d.ts +1 -0
- package/ui/DropdownMenu/DropdownMenu.d.ts +28 -0
- package/ui/DropdownMenu/index.d.ts +1 -0
- package/ui/ErrorBlock/ErrorBlock.d.ts +21 -0
- package/ui/ErrorBlock/index.d.ts +1 -0
- package/ui/Input/Input.d.ts +4 -0
- package/ui/Input/index.d.ts +1 -0
- package/ui/Label/Label.d.ts +5 -0
- package/ui/Label/index.d.ts +1 -0
- package/ui/Pagination/Pagination.d.ts +17 -0
- package/ui/Pagination/index.d.ts +1 -0
- package/ui/Popover/Popover.d.ts +7 -0
- package/ui/Popover/index.d.ts +1 -0
- package/ui/Progress/Progress.d.ts +16 -0
- package/ui/Progress/index.d.ts +1 -0
- package/ui/RadioGroup/RadioGroup.d.ts +7 -0
- package/ui/RadioGroup/index.d.ts +1 -0
- package/ui/Select/Select.d.ts +16 -0
- package/ui/Select/index.d.ts +1 -0
- package/ui/Separator/Separator.d.ts +5 -0
- package/ui/Separator/index.d.ts +1 -0
- package/ui/Sheet/Sheet.d.ts +17 -0
- package/ui/Sheet/index.d.ts +1 -0
- package/ui/Skeleton/Skeleton.d.ts +4 -0
- package/ui/Skeleton/index.d.ts +1 -0
- package/ui/Spinner/Spinner.d.ts +35 -0
- package/ui/Spinner/index.d.ts +1 -0
- package/ui/Switch/Switch.d.ts +5 -0
- package/ui/Switch/index.d.ts +1 -0
- package/ui/Table/Table.d.ts +11 -0
- package/ui/Table/index.d.ts +1 -0
- package/ui/Tabs/Tabs.d.ts +8 -0
- package/ui/Tabs/index.d.ts +1 -0
- package/ui/Textarea/Textarea.d.ts +4 -0
- package/ui/Textarea/index.d.ts +1 -0
- package/ui/Tooltip/Tooltip.d.ts +7 -0
- package/ui/Tooltip/index.d.ts +1 -0
- package/ui/index.d.ts +29 -0
- package/utils.d.ts +8 -0
package/DESIGN-SYSTEM.md
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# @kode4/react-foundation — Design System
|
|
2
|
+
|
|
3
|
+
This document is the **theming contract** for apps consuming the library.
|
|
4
|
+
The system follows the **shadcn/ui CSS-variable convention** — if you've
|
|
5
|
+
themed a shadcn project, you already know how this works, and shadcn-
|
|
6
|
+
compatible theme generators (e.g. [tweakcn](https://tweakcn.com)) produce
|
|
7
|
+
values you can paste here.
|
|
8
|
+
|
|
9
|
+
## The model
|
|
10
|
+
|
|
11
|
+
- All components are styled against **semantic design tokens** — CSS custom
|
|
12
|
+
properties declared in `src/lib/theme.css`.
|
|
13
|
+
- Tokens come in pairs: the **base** token is a surface color, its
|
|
14
|
+
**`-foreground`** partner is the text/icon color that sits on that
|
|
15
|
+
surface. Example: a primary button uses `background: var(--primary)` and
|
|
16
|
+
`color: var(--primary-foreground)`.
|
|
17
|
+
- **Light** values live in `:root`; **dark** values override the same
|
|
18
|
+
tokens inside a `.dark` selector on `<html>`. Components never know which
|
|
19
|
+
mode is active.
|
|
20
|
+
- Colors use the **oklch** color space (perceptually uniform; any valid CSS
|
|
21
|
+
color works if you prefer hex/hsl).
|
|
22
|
+
|
|
23
|
+
## Token reference
|
|
24
|
+
|
|
25
|
+
| Token | Pair | Role |
|
|
26
|
+
| ------------------------- | -------------------------- | -------------------------------------------- |
|
|
27
|
+
| `--background` | `--foreground` | App background and default text |
|
|
28
|
+
| `--card` | `--card-foreground` | Elevated surfaces (cards, panels) |
|
|
29
|
+
| `--popover` | `--popover-foreground` | Floating surfaces (menus, popovers) |
|
|
30
|
+
| `--primary` | `--primary-foreground` | High-emphasis actions |
|
|
31
|
+
| `--secondary` | `--secondary-foreground` | Low-emphasis actions |
|
|
32
|
+
| `--muted` | `--muted-foreground` | Subtle surfaces, secondary text |
|
|
33
|
+
| `--accent` | `--accent-foreground` | Hover / interactive highlight states |
|
|
34
|
+
| `--destructive` | `--destructive-foreground` | Errors, dangerous actions |
|
|
35
|
+
| `--success` | `--success-foreground` | Positive outcomes, confirmations |
|
|
36
|
+
| `--border` | — | Borders and separators |
|
|
37
|
+
| `--input` | — | Form-control borders |
|
|
38
|
+
| `--ring` | — | Focus rings |
|
|
39
|
+
| `--chart-1` … `--chart-5` | — | Data-visualization palette |
|
|
40
|
+
| `--radius` | — | Base corner radius (derived: sm/md/lg/xl) |
|
|
41
|
+
| `--font-sans` | — | Standard UI font (also Tailwind `font-sans`) |
|
|
42
|
+
| `--font-mono` | — | Monospace font (code, tabular data) |
|
|
43
|
+
|
|
44
|
+
Colors live in `:root` (light) and `.dark` (dark overrides). The **dimension
|
|
45
|
+
tokens** below are mode-independent — defined once in `:root`:
|
|
46
|
+
|
|
47
|
+
| Token | Role |
|
|
48
|
+
| ------------------------------ | ----------------------------------------------------------------------------------------------------------- |
|
|
49
|
+
| `--spacing` | Base spacing unit (default `0.25rem`). Scales **every** padding/margin/gap/size — the global density lever. |
|
|
50
|
+
| `--radius` | Base corner radius (also above). |
|
|
51
|
+
| `--k4-control-height-sm/md/lg` | Shared height of form controls (Button, Input, Select). Derive from `--spacing`. |
|
|
52
|
+
| `--k4-button-padding-x` | Default Button horizontal padding. |
|
|
53
|
+
| `--k4-card-padding` | Card section padding. |
|
|
54
|
+
|
|
55
|
+
Convention: standard shadcn token names stay unprefixed (`--primary`,
|
|
56
|
+
`--radius`, `--spacing`); library-specific tokens use the **`--k4-`** prefix
|
|
57
|
+
to avoid clashing with a consumer's own variables. The `--k4-*` sizes derive
|
|
58
|
+
from `--spacing`, so overriding `--spacing` alone rescales the whole UI.
|
|
59
|
+
|
|
60
|
+
The live swatch board is in the demo app under **UI Kit → Tokens** (`/ui/tokens`).
|
|
61
|
+
|
|
62
|
+
## Theming your app
|
|
63
|
+
|
|
64
|
+
Import the library (the barrel import loads the design system), then
|
|
65
|
+
re-declare any tokens in a stylesheet that loads **after** it:
|
|
66
|
+
|
|
67
|
+
```css
|
|
68
|
+
/* app.css — a blue brand with a softer radius */
|
|
69
|
+
:root {
|
|
70
|
+
--primary: oklch(0.55 0.2 260);
|
|
71
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
72
|
+
--radius: 0.5rem;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.dark {
|
|
76
|
+
--primary: oklch(0.7 0.18 260);
|
|
77
|
+
--primary-foreground: oklch(0.15 0 0);
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
That's the entire mechanism — no build configuration, no component changes.
|
|
82
|
+
The demo app does exactly this in `src/demo/demo.css` (it maps its own
|
|
83
|
+
legacy variables onto the semantic tokens).
|
|
84
|
+
|
|
85
|
+
**Caution:** only re-declare a system token when you mean to re-theme it
|
|
86
|
+
everywhere. If your app has its own variable that happens to share a token
|
|
87
|
+
name (e.g. an `--accent` brand color), rename yours — assigning it would
|
|
88
|
+
silently restyle every component that consumes that token. (The demo hit
|
|
89
|
+
exactly this and renamed its variable to `--brand`.)
|
|
90
|
+
|
|
91
|
+
## Typography
|
|
92
|
+
|
|
93
|
+
The standard theme font is **Open Sans** (a humanist sans-serif, highly
|
|
94
|
+
legible at UI sizes). It's wired through the `--font-sans` token, which the
|
|
95
|
+
base layer applies to `<body>` and which also backs Tailwind's `font-sans`
|
|
96
|
+
utility. The token ships a full **system fallback stack**, so the UI is
|
|
97
|
+
never unstyled while the webfont loads (or if you choose not to load it):
|
|
98
|
+
|
|
99
|
+
```css
|
|
100
|
+
--font-sans:
|
|
101
|
+
'Open Sans Variable', 'Open Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto,
|
|
102
|
+
'Helvetica Neue', Arial, sans-serif;
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Loading the font — self-host, don't hotlink Google
|
|
106
|
+
|
|
107
|
+
The library defines the font _contract_ (the family name + fallbacks) but
|
|
108
|
+
does **not** download any font files — loading them is the app's job, so
|
|
109
|
+
you stay in control of which fonts ship. We **self-host** via the
|
|
110
|
+
[`@fontsource`](https://fontsource.org) packages (the same Google Fonts,
|
|
111
|
+
vendored as local `.woff2`) rather than `<link>`-ing `fonts.googleapis.com`.
|
|
112
|
+
|
|
113
|
+
Why: hotlinking Google Fonts sends every visitor's IP to Google, which in
|
|
114
|
+
the EU/Germany requires consent (the well-known Google-Fonts GDPR rulings).
|
|
115
|
+
Self-hosting avoids that, removes a render-blocking third-party round-trip,
|
|
116
|
+
and works offline. It also fits the published-package model — the lib ships
|
|
117
|
+
compiled CSS and never reaches out to a CDN.
|
|
118
|
+
|
|
119
|
+
The demo does exactly this — **one import in `src/demo/main.tsx`**:
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
import '@fontsource-variable/open-sans'; // registers @font-face, all weights
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Swapping in a different font (the repeatable process)
|
|
126
|
+
|
|
127
|
+
1. Install the family: `npm i @fontsource-variable/<font>` (use the
|
|
128
|
+
`@fontsource-variable/*` package for a variable font — one file, all
|
|
129
|
+
weights; or `@fontsource/<font>` for static weights).
|
|
130
|
+
2. Import it once at your app entry (alongside the Open Sans line above),
|
|
131
|
+
or remove that line to drop Open Sans.
|
|
132
|
+
3. Point the token at it in a stylesheet that loads **after** the lib —
|
|
133
|
+
put the loaded family first, keep a system fallback last:
|
|
134
|
+
|
|
135
|
+
```css
|
|
136
|
+
:root {
|
|
137
|
+
--font-sans: 'Roboto', ui-sans-serif, system-ui, sans-serif;
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
That's the whole mechanism: install → import → re-declare `--font-sans`.
|
|
142
|
+
Check the [Fontsource directory](https://fontsource.org/fonts) for the
|
|
143
|
+
exact package name and the `@font-face` family it registers (variable
|
|
144
|
+
packages use a `… Variable` suffix, e.g. `'Open Sans Variable'`).
|
|
145
|
+
|
|
146
|
+
## Light / dark mode
|
|
147
|
+
|
|
148
|
+
- Mechanics: the `.dark` class on `<html>` switches every token.
|
|
149
|
+
- Ship `<ThemeProvider>` near your app root and `<ModeToggle />` anywhere
|
|
150
|
+
inside it. Modes: `'light' | 'dark' | 'system'` (system follows
|
|
151
|
+
`prefers-color-scheme` live). The choice persists in `localStorage`
|
|
152
|
+
(key `k4-ui-theme`, overridable via the `storageKey` prop).
|
|
153
|
+
- Programmatic access: `const { mode, resolvedMode, setMode } = useTheme()`.
|
|
154
|
+
|
|
155
|
+
## Class architecture (BEM)
|
|
156
|
+
|
|
157
|
+
Component markup uses semantic **BEM** classes with the `k4-` prefix:
|
|
158
|
+
block `k4-button`, element `k4-card__header`, modifier
|
|
159
|
+
`k4-button--outline`. Variants map 1:1 to modifiers, so the rendered DOM is
|
|
160
|
+
self-describing.
|
|
161
|
+
|
|
162
|
+
- **Preferred customization is always tokens** (above).
|
|
163
|
+
- As a documented last resort, apps may target the BEM classes
|
|
164
|
+
(`.k4-button--outline { … }`) — they are part of the public API and
|
|
165
|
+
follow semver.
|
|
166
|
+
- Every component also accepts `className` for per-instance additions, and
|
|
167
|
+
exports its props type (`ButtonProps`, `ShellProps`, …).
|
|
168
|
+
|
|
169
|
+
Internally the stylesheets compose Tailwind v4 utilities via `@apply`, but
|
|
170
|
+
that is an implementation detail: **no utility classes appear in markup**
|
|
171
|
+
(CI-enforced), and consuming apps never need Tailwind.
|
|
172
|
+
|
|
173
|
+
## Extending the system
|
|
174
|
+
|
|
175
|
+
New tokens: declare them in your `:root`/`.dark` and use them in your own
|
|
176
|
+
CSS — or add them to `src/lib/theme.css` (plus the `@theme inline` block if
|
|
177
|
+
lib stylesheets should `@apply` them).
|
|
178
|
+
|
|
179
|
+
New component variants: add a BEM modifier class in the component's CSS and
|
|
180
|
+
extend its `cva` map (e.g. `k4-button--brand` in `Button.css` +
|
|
181
|
+
`variant: { brand: 'k4-button--brand' }`).
|
|
182
|
+
|
|
183
|
+
## Relationship to shadcn/ui
|
|
184
|
+
|
|
185
|
+
shadcn/ui is the **blueprint**: component anatomy, variant APIs, Radix
|
|
186
|
+
primitives, and this token convention come from it. The implementation
|
|
187
|
+
differs deliberately — components are hand-authored with BEM classes and
|
|
188
|
+
per-component CSS instead of utility classes in JSX. When adding a new
|
|
189
|
+
component, transcribe shadcn's current design (structure + class lists)
|
|
190
|
+
into this pattern; see CLAUDE.md → "Adding a lib component".
|