@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.
Files changed (126) hide show
  1. package/DESIGN-SYSTEM.md +190 -0
  2. package/INSTRUCTIONS.md +694 -0
  3. package/LICENSE +21 -0
  4. package/README.md +53 -0
  5. package/errors.d.ts +24 -0
  6. package/forms/Form/Form.d.ts +30 -0
  7. package/forms/Form/index.d.ts +1 -0
  8. package/forms/index.d.ts +1 -0
  9. package/hooks/index.d.ts +1 -0
  10. package/hooks/useMediaQuery.d.ts +8 -0
  11. package/index.d.ts +24 -0
  12. package/index.js +1679 -0
  13. package/index.js.map +1 -0
  14. package/internal/env.d.ts +1 -0
  15. package/internal/registry.d.ts +3 -0
  16. package/internal/type-utils.d.ts +6 -0
  17. package/layout/AppLayout/AppLayout.d.ts +18 -0
  18. package/layout/AppLayout/index.d.ts +1 -0
  19. package/layout/CenteredLayout/CenteredLayout.d.ts +12 -0
  20. package/layout/CenteredLayout/index.d.ts +1 -0
  21. package/layout/Columns/Columns.d.ts +35 -0
  22. package/layout/Columns/index.d.ts +1 -0
  23. package/layout/Container/Container.d.ts +5 -0
  24. package/layout/Container/index.d.ts +1 -0
  25. package/layout/DashboardGrid/DashboardGrid.d.ts +37 -0
  26. package/layout/DashboardGrid/index.d.ts +1 -0
  27. package/layout/FillHeight/FillHeight.d.ts +16 -0
  28. package/layout/FillHeight/index.d.ts +1 -0
  29. package/layout/Footer/Footer.d.ts +5 -0
  30. package/layout/Footer/index.d.ts +1 -0
  31. package/layout/Header/Header.d.ts +13 -0
  32. package/layout/Header/index.d.ts +1 -0
  33. package/layout/SideBar/SideBar.d.ts +6 -0
  34. package/layout/SideBar/index.d.ts +1 -0
  35. package/layout/SiteLayout/SiteLayout.d.ts +27 -0
  36. package/layout/SiteLayout/index.d.ts +1 -0
  37. package/layout/SkipLink/SkipLink.d.ts +9 -0
  38. package/layout/SkipLink/index.d.ts +1 -0
  39. package/layout/TopBar/TopBar.d.ts +32 -0
  40. package/layout/TopBar/index.d.ts +1 -0
  41. package/layout/index.d.ts +12 -0
  42. package/package.json +52 -0
  43. package/query/index.d.ts +1 -0
  44. package/query/sort.d.ts +19 -0
  45. package/router/DefaultErrorBoundary.d.ts +5 -0
  46. package/router/TypedLink/TypedLink.d.ts +22 -0
  47. package/router/TypedLink/index.d.ts +1 -0
  48. package/router/adapter.d.ts +27 -0
  49. package/router/chain.d.ts +17 -0
  50. package/router/context.d.ts +24 -0
  51. package/router/createAppRouter.d.ts +15 -0
  52. package/router/defineRoute.d.ts +11 -0
  53. package/router/index.d.ts +11 -0
  54. package/router/menu.d.ts +51 -0
  55. package/router/pathTo.d.ts +21 -0
  56. package/router/types.d.ts +72 -0
  57. package/router/useRoute.d.ts +22 -0
  58. package/style.css +3 -0
  59. package/theme/ModeToggle/ModeToggle.d.ts +6 -0
  60. package/theme/ModeToggle/index.d.ts +1 -0
  61. package/theme/ThemeProvider/ThemeProvider.d.ts +25 -0
  62. package/theme/ThemeProvider/index.d.ts +1 -0
  63. package/theme/Toaster/Toaster.d.ts +9 -0
  64. package/theme/Toaster/index.d.ts +2 -0
  65. package/theme/Toaster/toast.d.ts +38 -0
  66. package/theme/index.d.ts +3 -0
  67. package/ui/Accordion/Accordion.d.ts +7 -0
  68. package/ui/Accordion/index.d.ts +1 -0
  69. package/ui/Alert/Alert.d.ts +11 -0
  70. package/ui/Alert/index.d.ts +1 -0
  71. package/ui/AlertDialog/AlertDialog.d.ts +19 -0
  72. package/ui/AlertDialog/index.d.ts +1 -0
  73. package/ui/Avatar/Avatar.d.ts +7 -0
  74. package/ui/Avatar/index.d.ts +1 -0
  75. package/ui/AwaitErrorBlock/AwaitErrorBlock.d.ts +11 -0
  76. package/ui/AwaitErrorBlock/index.d.ts +1 -0
  77. package/ui/Badge/Badge.d.ts +10 -0
  78. package/ui/Badge/index.d.ts +1 -0
  79. package/ui/Button/Button.d.ts +13 -0
  80. package/ui/Button/index.d.ts +1 -0
  81. package/ui/Card/Card.d.ts +11 -0
  82. package/ui/Card/index.d.ts +1 -0
  83. package/ui/Checkbox/Checkbox.d.ts +5 -0
  84. package/ui/Checkbox/index.d.ts +1 -0
  85. package/ui/Command/Command.d.ts +19 -0
  86. package/ui/Command/index.d.ts +1 -0
  87. package/ui/Dialog/Dialog.d.ts +17 -0
  88. package/ui/Dialog/index.d.ts +1 -0
  89. package/ui/DropdownMenu/DropdownMenu.d.ts +28 -0
  90. package/ui/DropdownMenu/index.d.ts +1 -0
  91. package/ui/ErrorBlock/ErrorBlock.d.ts +21 -0
  92. package/ui/ErrorBlock/index.d.ts +1 -0
  93. package/ui/Input/Input.d.ts +4 -0
  94. package/ui/Input/index.d.ts +1 -0
  95. package/ui/Label/Label.d.ts +5 -0
  96. package/ui/Label/index.d.ts +1 -0
  97. package/ui/Pagination/Pagination.d.ts +17 -0
  98. package/ui/Pagination/index.d.ts +1 -0
  99. package/ui/Popover/Popover.d.ts +7 -0
  100. package/ui/Popover/index.d.ts +1 -0
  101. package/ui/Progress/Progress.d.ts +16 -0
  102. package/ui/Progress/index.d.ts +1 -0
  103. package/ui/RadioGroup/RadioGroup.d.ts +7 -0
  104. package/ui/RadioGroup/index.d.ts +1 -0
  105. package/ui/Select/Select.d.ts +16 -0
  106. package/ui/Select/index.d.ts +1 -0
  107. package/ui/Separator/Separator.d.ts +5 -0
  108. package/ui/Separator/index.d.ts +1 -0
  109. package/ui/Sheet/Sheet.d.ts +17 -0
  110. package/ui/Sheet/index.d.ts +1 -0
  111. package/ui/Skeleton/Skeleton.d.ts +4 -0
  112. package/ui/Skeleton/index.d.ts +1 -0
  113. package/ui/Spinner/Spinner.d.ts +35 -0
  114. package/ui/Spinner/index.d.ts +1 -0
  115. package/ui/Switch/Switch.d.ts +5 -0
  116. package/ui/Switch/index.d.ts +1 -0
  117. package/ui/Table/Table.d.ts +11 -0
  118. package/ui/Table/index.d.ts +1 -0
  119. package/ui/Tabs/Tabs.d.ts +8 -0
  120. package/ui/Tabs/index.d.ts +1 -0
  121. package/ui/Textarea/Textarea.d.ts +4 -0
  122. package/ui/Textarea/index.d.ts +1 -0
  123. package/ui/Tooltip/Tooltip.d.ts +7 -0
  124. package/ui/Tooltip/index.d.ts +1 -0
  125. package/ui/index.d.ts +29 -0
  126. package/utils.d.ts +8 -0
@@ -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".