@kbach/react 0.5.1 → 0.5.3
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/KBACH.md +952 -0
- package/README.md +3 -3
- package/dist/{chunk-EBISJEHP.mjs → chunk-7C3WGTMN.mjs} +4 -9
- package/dist/{chunk-M3LZVDYD.mjs → chunk-OKK7AJ2G.mjs} +386 -245
- package/dist/index.js +386 -245
- package/dist/index.mjs +1 -1
- package/dist/jsx-dev-runtime.js +389 -253
- package/dist/jsx-dev-runtime.mjs +2 -2
- package/dist/jsx-runtime.js +389 -253
- package/dist/jsx-runtime.mjs +2 -2
- package/package.json +6 -3
- package/scripts/postinstall.js +28 -0
package/KBACH.md
ADDED
|
@@ -0,0 +1,952 @@
|
|
|
1
|
+
# Kbach Framework — Complete AI Reference
|
|
2
|
+
|
|
3
|
+
Kbach is a Tailwind-like utility CSS framework for React (web) and React Native. Classes are written as `className` strings and resolved to inline styles at render time. On web, stateful and structural CSS rules are injected into a `<style>` tag so they work with the browser cascade. On native, only inline-compatible styles are applied.
|
|
4
|
+
|
|
5
|
+
Two packages:
|
|
6
|
+
- `@kbach/react` — React web (uses custom JSX runtime)
|
|
7
|
+
- `@kbach/native` — React Native / Expo (wraps `@kbach/react`, adds Babel preset + Metro config)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Setup — @kbach/react (web)
|
|
12
|
+
|
|
13
|
+
### tsconfig.json
|
|
14
|
+
```json
|
|
15
|
+
{ "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "@kbach/react" } }
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### vite.config.ts
|
|
19
|
+
```ts
|
|
20
|
+
import react from '@vitejs/plugin-react';
|
|
21
|
+
export default { plugins: [react({ jsxImportSource: '@kbach/react' })] };
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Per-file (no config needed)
|
|
25
|
+
```jsx
|
|
26
|
+
/** @jsxImportSource @kbach/react */
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Wrap app
|
|
30
|
+
```jsx
|
|
31
|
+
import { ThemeProvider } from '@kbach/react';
|
|
32
|
+
<ThemeProvider defaultMode="system"><App /></ThemeProvider>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Setup — @kbach/native (React Native / Expo)
|
|
38
|
+
|
|
39
|
+
### babel.config.js
|
|
40
|
+
```js
|
|
41
|
+
const { createKbachConfig } = require('@kbach/native');
|
|
42
|
+
module.exports = createKbachConfig();
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Wrap app
|
|
46
|
+
```jsx
|
|
47
|
+
import { ThemeProvider } from '@kbach/native';
|
|
48
|
+
<ThemeProvider defaultMode="system"><AppContent /></ThemeProvider>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
After changing babel.config.js: `npx expo start --clear`
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Core API
|
|
56
|
+
|
|
57
|
+
### className prop
|
|
58
|
+
Works on any element once the JSX runtime is active.
|
|
59
|
+
```jsx
|
|
60
|
+
<div className="bg-white dark:bg-gray-10 p-4 rounded-xl shadow" />
|
|
61
|
+
<p className="text-gray-10 text-lg font-bold" />
|
|
62
|
+
<button className="bg-blue-7 hover:bg-blue-8 rounded-lg px-4 py-2" />
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### styled(Component, baseClasses)
|
|
66
|
+
Pre-style a component. Returns a new component that accepts a `kb` prop for extra classes.
|
|
67
|
+
```jsx
|
|
68
|
+
import { styled } from '@kbach/react'; // or @kbach/native
|
|
69
|
+
|
|
70
|
+
const Card = styled('div', 'bg-white dark:bg-gray-9 rounded-2xl p-6 shadow');
|
|
71
|
+
const Button = styled('button', 'bg-blue-7 hover:bg-blue-8 rounded-xl px-6 py-3');
|
|
72
|
+
|
|
73
|
+
<Card kb="mt-4"> // merges mt-4 with base classes
|
|
74
|
+
<Button kb="w-full" /> // merges w-full with base classes
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
On web, `styled()` forwards the full class string as `className` so CSS rules (group-hover:, before:, print:) match the element.
|
|
78
|
+
|
|
79
|
+
### useStyles(classes)
|
|
80
|
+
Resolve classes to a style object inside a component.
|
|
81
|
+
```jsx
|
|
82
|
+
import { useStyles } from '@kbach/react';
|
|
83
|
+
const style = useStyles('bg-blue-6 px-3 py-1 rounded-full');
|
|
84
|
+
return <span style={style}>Badge</span>;
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### kb(classes)
|
|
88
|
+
Resolve outside a component (static contexts).
|
|
89
|
+
```js
|
|
90
|
+
import { kb } from '@kbach/react';
|
|
91
|
+
const cardStyle = kb('bg-white p-4 rounded-xl') as React.CSSProperties;
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### cx(...classes)
|
|
95
|
+
Conditionally join class strings. Falsy values ignored.
|
|
96
|
+
```jsx
|
|
97
|
+
import { cx } from '@kbach/react';
|
|
98
|
+
<div className={cx('p-4', isActive && 'border-2 border-blue-6', isDisabled && 'opacity-50')} />
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### useTheme()
|
|
102
|
+
```ts
|
|
103
|
+
const { mode, resolvedMode, isDark, setMode, toggle, config } = useTheme();
|
|
104
|
+
// mode: 'light' | 'dark' | 'system'
|
|
105
|
+
// resolvedMode: 'light' | 'dark'
|
|
106
|
+
// isDark: boolean
|
|
107
|
+
// setMode(mode): void
|
|
108
|
+
// toggle(): void
|
|
109
|
+
// config: ResolvedConfig
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### useIsDark()
|
|
113
|
+
```ts
|
|
114
|
+
const isDark = useIsDark(); // boolean
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### useColors()
|
|
118
|
+
Returns a proxy over the active theme's color palette.
|
|
119
|
+
```ts
|
|
120
|
+
const colors = useColors();
|
|
121
|
+
colors.blue[6] // '#3b82f6'
|
|
122
|
+
colors.blue['6/50'] // 'rgba(59,130,246,0.5)'
|
|
123
|
+
colors.white // '#ffffff'
|
|
124
|
+
colors['white/20'] // 'rgba(255,255,255,0.2)'
|
|
125
|
+
colors.alpha('#ff6b35', 60) // 'rgba(255,107,53,0.6)'
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### ThemeToggle
|
|
129
|
+
```jsx
|
|
130
|
+
<ThemeToggle /> // button (default)
|
|
131
|
+
<ThemeToggle variant="switch" /> // toggle switch
|
|
132
|
+
<ThemeToggle variant="icon-button" /> // icon button
|
|
133
|
+
<ThemeToggle variant="button" includeSystem /> // three-way light/dark/system
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Modifier System
|
|
139
|
+
|
|
140
|
+
Up to 3 modifiers can be chained in any order before the utility name.
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
[modifier:][modifier:][modifier:]utility-value
|
|
144
|
+
dark:hover:bg-blue-8
|
|
145
|
+
sm:dark:text-lg
|
|
146
|
+
motion-reduce:transition-none
|
|
147
|
+
rtl:text-right
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Theme modifiers
|
|
151
|
+
| Modifier | Condition |
|
|
152
|
+
|---|---|
|
|
153
|
+
| `dark:` | Dark mode active |
|
|
154
|
+
| `light:` | Light mode active |
|
|
155
|
+
| `not-dark:` | Light mode active (alias) |
|
|
156
|
+
| `not-light:` | Dark mode active (alias) |
|
|
157
|
+
|
|
158
|
+
Dark mode strategy set in `ThemeProvider` or `kbach.config.js`:
|
|
159
|
+
- `'attribute'` (default) — `[data-theme="dark"]` on a wrapper element
|
|
160
|
+
- `'class'` — `.dark` class on a wrapper element
|
|
161
|
+
- `'media'` — `@media (prefers-color-scheme: dark)`
|
|
162
|
+
|
|
163
|
+
### Interaction modifiers
|
|
164
|
+
| Modifier | Triggers on |
|
|
165
|
+
|---|---|
|
|
166
|
+
| `hover:` | Mouse hover |
|
|
167
|
+
| `focus:` | Element focused |
|
|
168
|
+
| `focus-within:` | Focus anywhere inside element |
|
|
169
|
+
| `focus-visible:` | Keyboard focus ring |
|
|
170
|
+
| `active:` | Active state |
|
|
171
|
+
| `pressed:` | Click / touch pressed (alias for active on native) |
|
|
172
|
+
| `visited:` | Visited link |
|
|
173
|
+
| `disabled:` | Disabled element |
|
|
174
|
+
| `checked:` | Checkbox / radio checked |
|
|
175
|
+
| `placeholder:` | Input placeholder text |
|
|
176
|
+
|
|
177
|
+
Negated: `not-hover:`, `not-focus:`, `not-active:`, `not-pressed:`, `not-visited:`, `not-disabled:`, `not-checked:`
|
|
178
|
+
|
|
179
|
+
### Structural modifiers (CSS-injection only)
|
|
180
|
+
| Modifier | Pseudo-class |
|
|
181
|
+
|---|---|
|
|
182
|
+
| `first:` | `:first-child` |
|
|
183
|
+
| `last:` | `:last-child` |
|
|
184
|
+
| `odd:` | `:nth-child(odd)` |
|
|
185
|
+
| `even:` | `:nth-child(even)` |
|
|
186
|
+
| `only:` | `:only-child` |
|
|
187
|
+
|
|
188
|
+
### Responsive modifiers
|
|
189
|
+
| Modifier | Min-width |
|
|
190
|
+
|---|---|
|
|
191
|
+
| `sm:` | 576 px |
|
|
192
|
+
| `md:` | 768 px |
|
|
193
|
+
| `lg:` | 1024 px |
|
|
194
|
+
| `xl:` | 1280 px |
|
|
195
|
+
| `2xl:` | 1536 px |
|
|
196
|
+
|
|
197
|
+
On web, responsive styles are handled entirely via `@media (min-width)` CSS rules — no JS breakpoint tracking needed. On native, breakpoints are resolved from the current window width.
|
|
198
|
+
|
|
199
|
+
### Group / peer modifiers (CSS-injection only, web only)
|
|
200
|
+
Mark a parent with `group` (standalone class), then use `group-hover:` etc. on children.
|
|
201
|
+
Mark a previous sibling with `peer`, then use `peer-hover:` etc. on the next sibling.
|
|
202
|
+
|
|
203
|
+
```jsx
|
|
204
|
+
<div className="group">
|
|
205
|
+
<span className="opacity-0 group-hover:opacity-100 transition" />
|
|
206
|
+
</div>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
| Modifier | Fires when |
|
|
210
|
+
|---|---|
|
|
211
|
+
| `group-hover:` | Ancestor `.group` is hovered |
|
|
212
|
+
| `group-focus:` | Ancestor `.group` is focused |
|
|
213
|
+
| `peer-hover:` | Previous sibling `.peer` is hovered |
|
|
214
|
+
| `peer-focus:` | Previous sibling `.peer` is focused |
|
|
215
|
+
|
|
216
|
+
### Pseudo-element modifiers (CSS-injection only, web only)
|
|
217
|
+
```jsx
|
|
218
|
+
<div className="before:content-['*'] before:text-red-6 relative" />
|
|
219
|
+
<p className="first-letter:text-4xl first-letter:font-bold" />
|
|
220
|
+
<p className="selection:bg-blue-3" />
|
|
221
|
+
<input className="placeholder:text-gray-5" />
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
| Modifier | CSS selector |
|
|
225
|
+
|---|---|
|
|
226
|
+
| `before:` | `::before` |
|
|
227
|
+
| `after:` | `::after` |
|
|
228
|
+
| `selection:` | `::selection` |
|
|
229
|
+
| `first-letter:` | `::first-letter` |
|
|
230
|
+
| `first-line:` | `::first-line` |
|
|
231
|
+
| `marker:` | `::marker` |
|
|
232
|
+
| `placeholder:` | `::placeholder` |
|
|
233
|
+
|
|
234
|
+
### Print modifier (CSS-injection only, web only)
|
|
235
|
+
```jsx
|
|
236
|
+
<div className="print:hidden" />
|
|
237
|
+
<div className="print:text-black print:bg-white" />
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Orientation modifiers (CSS-injection only, web only)
|
|
241
|
+
```jsx
|
|
242
|
+
<div className="landscape:flex-row portrait:flex-col" />
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
| Modifier | Media query |
|
|
246
|
+
|---|---|
|
|
247
|
+
| `landscape:` | `@media (orientation: landscape)` |
|
|
248
|
+
| `portrait:` | `@media (orientation: portrait)` |
|
|
249
|
+
|
|
250
|
+
### Accessibility modifiers (CSS-injection only, web only)
|
|
251
|
+
```jsx
|
|
252
|
+
<div className="motion-reduce:transition-none motion-safe:transition-all duration-300" />
|
|
253
|
+
<div className="contrast-more:border-2 contrast-more:border-black" />
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
| Modifier | Media query |
|
|
257
|
+
|---|---|
|
|
258
|
+
| `motion-reduce:` | `@media (prefers-reduced-motion: reduce)` |
|
|
259
|
+
| `motion-safe:` | `@media (prefers-reduced-motion: no-preference)` |
|
|
260
|
+
| `contrast-more:` | `@media (prefers-contrast: more)` |
|
|
261
|
+
| `contrast-less:` | `@media (prefers-contrast: less)` |
|
|
262
|
+
|
|
263
|
+
### Directionality modifiers (CSS-injection only, web only)
|
|
264
|
+
```jsx
|
|
265
|
+
<div className="rtl:text-right ltr:text-left" />
|
|
266
|
+
<div className="rtl:pl-4 ltr:pr-4" />
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
| Modifier | CSS selector scope |
|
|
270
|
+
|---|---|
|
|
271
|
+
| `rtl:` | `[dir="rtl"] .cls` |
|
|
272
|
+
| `ltr:` | `[dir="ltr"] .cls` |
|
|
273
|
+
|
|
274
|
+
### Important modifier
|
|
275
|
+
Prefix any class with `!` to add `!important` to every CSS declaration it produces.
|
|
276
|
+
```jsx
|
|
277
|
+
<div className="!p-0 !m-0 !bg-transparent" />
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Arbitrary Values
|
|
283
|
+
|
|
284
|
+
Wrap any value in `[]` to use it directly.
|
|
285
|
+
```jsx
|
|
286
|
+
<div className="bg-[#6366f1]" />
|
|
287
|
+
<div className="p-[14px]" />
|
|
288
|
+
<div className="w-[calc(100%-2rem)]" />
|
|
289
|
+
<div className="text-[18px]" />
|
|
290
|
+
<div className="rounded-[20px]" />
|
|
291
|
+
<div className="bg-[rgba(99,102,241,0.15)]" />
|
|
292
|
+
<div className="grid-cols-[1fr_2fr_1fr]" />
|
|
293
|
+
<div className="will-change-[transform,opacity]" />
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## Negative Values
|
|
299
|
+
Prefix any spacing utility with `-` for negative values.
|
|
300
|
+
```jsx
|
|
301
|
+
<div className="-mt-4" /> // marginTop: -16
|
|
302
|
+
<div className="-mx-2" /> // marginHorizontal: -8
|
|
303
|
+
<div className="-translate-x-2" />
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## Color with Opacity
|
|
309
|
+
Append `/opacity` to any color utility. Opacity is 0–100 (integer) or arbitrary.
|
|
310
|
+
```jsx
|
|
311
|
+
<div className="bg-blue-6/50" /> // 50% opacity
|
|
312
|
+
<div className="text-gray-10/75" /> // 75% opacity
|
|
313
|
+
<div className="bg-black/[0.15]" /> // arbitrary opacity
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Color System
|
|
319
|
+
|
|
320
|
+
### 12-shade scale
|
|
321
|
+
1 = lightest, 12 = darkest. Maps to Tailwind v3 (50 → 1, 100 → 2, … 950 → 11, extra-dark → 12).
|
|
322
|
+
|
|
323
|
+
```
|
|
324
|
+
shade 1 2 3 4 5 6 7 8 9 10 11 12
|
|
325
|
+
─────────────────────────────────────────────
|
|
326
|
+
light dark
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Usage: `bg-blue-6`, `text-gray-10`, `border-red-4/50`
|
|
330
|
+
|
|
331
|
+
### Color families (22 total)
|
|
332
|
+
Grays: `slate`, `gray`, `zinc`, `neutral`, `stone`
|
|
333
|
+
Colors: `red`, `orange`, `amber`, `yellow`, `lime`, `green`, `emerald`, `teal`, `cyan`, `sky`, `blue`, `indigo`, `violet`, `purple`, `fuchsia`, `pink`, `rose`
|
|
334
|
+
Special: `transparent`, `current` (currentColor), `black`, `white`
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## Utility Reference
|
|
339
|
+
|
|
340
|
+
### Background
|
|
341
|
+
```
|
|
342
|
+
bg-{color} backgroundColor
|
|
343
|
+
bg-{color}/{opacity} backgroundColor with alpha
|
|
344
|
+
bg-transparent backgroundColor: transparent
|
|
345
|
+
bg-clip-border -webkit-background-clip: border-box
|
|
346
|
+
bg-clip-padding -webkit-background-clip: padding-box
|
|
347
|
+
bg-clip-content -webkit-background-clip: content-box
|
|
348
|
+
bg-clip-text -webkit-background-clip: text (web only)
|
|
349
|
+
bg-gradient-to-{dir} background linear gradient direction (web only)
|
|
350
|
+
directions: t, tr, r, br, b, bl, l, tl
|
|
351
|
+
use with: from-{color}, via-{color}, to-{color}
|
|
352
|
+
bg-blend-{mode} background-blend-mode (web only)
|
|
353
|
+
modes: normal, multiply, screen, overlay, darken, lighten,
|
|
354
|
+
color-dodge, color-burn, hard-light, soft-light,
|
|
355
|
+
difference, exclusion, hue, saturation, color, luminosity
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Text
|
|
359
|
+
```
|
|
360
|
+
text-{size} fontSize: xs(12) sm(14) base(16) lg(18) xl(20)
|
|
361
|
+
2xl(24) 3xl(30) 4xl(36) 5xl(48)
|
|
362
|
+
6xl(60) 7xl(72) 8xl(96) 9xl(128)
|
|
363
|
+
text-{color} color
|
|
364
|
+
text-left/right/center/justify textAlign
|
|
365
|
+
text-wrap text-wrap: wrap (web only)
|
|
366
|
+
text-nowrap text-wrap: nowrap (web only)
|
|
367
|
+
text-balance text-wrap: balance (web only)
|
|
368
|
+
text-pretty text-wrap: pretty (web only)
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Font
|
|
372
|
+
```
|
|
373
|
+
font-thin/extralight/light/normal/medium/semibold/bold/extrabold/black
|
|
374
|
+
font-{family} fontFamily (sans, mono, serif, or custom)
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### Text decoration
|
|
378
|
+
```
|
|
379
|
+
underline textDecorationLine: underline
|
|
380
|
+
overline textDecorationLine: overline (web only)
|
|
381
|
+
line-through textDecorationLine: line-through
|
|
382
|
+
no-underline textDecorationLine: none
|
|
383
|
+
decoration-{color} textDecorationColor (web only)
|
|
384
|
+
decoration-solid/dashed/dotted/double/wavy textDecorationStyle (web only)
|
|
385
|
+
decoration-0/1/2/4/8/auto/from-font textDecorationThickness (web only)
|
|
386
|
+
underline-offset-0/1/2/4/8/auto textUnderlineOffset (web only)
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### Text transform / case
|
|
390
|
+
```
|
|
391
|
+
uppercase textTransform: uppercase
|
|
392
|
+
lowercase textTransform: lowercase
|
|
393
|
+
capitalize textTransform: capitalize
|
|
394
|
+
normal-case textTransform: none
|
|
395
|
+
italic fontStyle: italic
|
|
396
|
+
not-italic fontStyle: normal
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### Text overflow
|
|
400
|
+
```
|
|
401
|
+
truncate overflow: hidden; white-space: nowrap; text-overflow: ellipsis
|
|
402
|
+
overflow-ellipsis text-overflow: ellipsis (web only)
|
|
403
|
+
line-clamp-{n} -webkit-line-clamp (web only, n = 1–20)
|
|
404
|
+
line-clamp-none removes line-clamp (web only)
|
|
405
|
+
whitespace-normal/nowrap/pre/pre-wrap/pre-line whiteSpace
|
|
406
|
+
break-normal/words/all/keep word-break / overflow-wrap
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### Typography misc
|
|
410
|
+
```
|
|
411
|
+
leading-{value} lineHeight: none(1) tight(1.25) snug(1.375) normal(1.5)
|
|
412
|
+
relaxed(1.625) loose(2), or numeric 3–10 (12–40px)
|
|
413
|
+
tracking-{value} letterSpacing: tighter(-0.8) tight(-0.4) normal(0)
|
|
414
|
+
wide(0.4) wider(0.8) widest(1.6)
|
|
415
|
+
antialiased -webkit-font-smoothing: antialiased (web only)
|
|
416
|
+
subpixel-antialiased -webkit-font-smoothing: subpixel-antialiased (web only)
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### Spacing — Padding
|
|
420
|
+
```
|
|
421
|
+
p-{n} padding (all sides)
|
|
422
|
+
px-{n} paddingHorizontal
|
|
423
|
+
py-{n} paddingVertical
|
|
424
|
+
pt-{n} paddingTop
|
|
425
|
+
pr-{n} paddingRight
|
|
426
|
+
pb-{n} paddingBottom
|
|
427
|
+
pl-{n} paddingLeft
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### Spacing — Margin
|
|
431
|
+
```
|
|
432
|
+
m-{n} margin (all sides)
|
|
433
|
+
mx-{n} marginHorizontal (mx-auto centers on web)
|
|
434
|
+
my-{n} marginVertical
|
|
435
|
+
mt-{n} marginTop
|
|
436
|
+
mr-{n} marginRight
|
|
437
|
+
mb-{n} marginBottom
|
|
438
|
+
ml-{n} marginLeft
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
Spacing scale (1 unit = 4px):
|
|
442
|
+
`px(1) 0 0.5(2) 1(4) 1.5(6) 2(8) 2.5(10) 3(12) 3.5(14) 4(16) 5(20) 6(24) 7(28) 8(32) 9(36) 10(40) 11(44) 12(48) 14(56) 16(64) 20(80) 24(96) 28(112) 32(128) 36(144) 40(160) 44(176) 48(192) 52(208) 56(224) 60(240) 64(256) 72(288) 80(320) 96(384) auto full(100%) 1/2 1/3 2/3 1/4 3/4 screen(100vh) min max fit`
|
|
443
|
+
|
|
444
|
+
### Sizing
|
|
445
|
+
```
|
|
446
|
+
w-{n} width
|
|
447
|
+
h-{n} height
|
|
448
|
+
size-{n} width + height
|
|
449
|
+
min-w-{n} minWidth
|
|
450
|
+
min-h-{n} minHeight
|
|
451
|
+
max-w-{n} maxWidth
|
|
452
|
+
max-h-{n} maxHeight
|
|
453
|
+
|
|
454
|
+
Named max-w sizes:
|
|
455
|
+
max-w-none(none) max-w-xs(320) max-w-sm(384) max-w-md(448)
|
|
456
|
+
max-w-lg(512) max-w-xl(576) max-w-2xl(672) max-w-3xl(768)
|
|
457
|
+
max-w-4xl(896) max-w-5xl(1024) max-w-6xl(1152) max-w-7xl(1280)
|
|
458
|
+
max-w-prose(65ch, web only)
|
|
459
|
+
|
|
460
|
+
Screen sizes:
|
|
461
|
+
w-screen(100vw) h-screen(100vh) size-screen not available
|
|
462
|
+
min-w-screen(100vw) max-w-screen(100vw)
|
|
463
|
+
min-h-screen(100vh) max-h-screen(100vh)
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
### Display
|
|
467
|
+
```
|
|
468
|
+
block display: block
|
|
469
|
+
inline display: inline
|
|
470
|
+
inline-block display: inline-block
|
|
471
|
+
flex display: flex
|
|
472
|
+
inline-flex display: inline-flex
|
|
473
|
+
grid display: grid (web only)
|
|
474
|
+
inline-grid display: inline-grid (web only)
|
|
475
|
+
hidden display: none
|
|
476
|
+
contents display: contents (web only)
|
|
477
|
+
flow-root display: flow-root (web only)
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
### Flex
|
|
481
|
+
```
|
|
482
|
+
flex-row/col/row-reverse/col-reverse flexDirection
|
|
483
|
+
flex-wrap/nowrap/wrap-reverse flexWrap
|
|
484
|
+
flex-1 flex: 1
|
|
485
|
+
flex-auto flex: 1 1 auto
|
|
486
|
+
flex-initial flex: 0 1 auto
|
|
487
|
+
flex-none flex: none
|
|
488
|
+
flex-grow / flex-grow-0
|
|
489
|
+
flex-shrink / flex-shrink-0
|
|
490
|
+
grow / grow-0 flexGrow: 1/0
|
|
491
|
+
shrink / shrink-0 flexShrink: 1/0
|
|
492
|
+
basis-{n} flexBasis
|
|
493
|
+
items-start/end/center/baseline/stretch alignItems
|
|
494
|
+
justify-start/end/center/between/around/evenly justifyContent
|
|
495
|
+
self-start/end/center/auto/stretch alignSelf
|
|
496
|
+
content-start/end/center/between/around/evenly alignContent
|
|
497
|
+
justify-items-start/end/center/stretch justifyItems (web only)
|
|
498
|
+
justify-self-start/end/center/auto justifySelf (web only)
|
|
499
|
+
order-{n} order
|
|
500
|
+
gap-{n} gap
|
|
501
|
+
gap-x-{n} columnGap
|
|
502
|
+
gap-y-{n} rowGap
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
### Grid (web only)
|
|
506
|
+
```
|
|
507
|
+
grid-cols-{n} gridTemplateColumns: repeat(n, minmax(0,1fr))
|
|
508
|
+
grid-cols-none gridTemplateColumns: none
|
|
509
|
+
grid-rows-{n} gridTemplateRows
|
|
510
|
+
grid-rows-none gridTemplateRows: none
|
|
511
|
+
grid-flow-row/col/dense/row-dense/col-dense gridAutoFlow
|
|
512
|
+
auto-cols-auto/min/max/fr gridAutoColumns
|
|
513
|
+
auto-rows-auto/min/max/fr gridAutoRows
|
|
514
|
+
col-span-{n} gridColumn: span n / span n
|
|
515
|
+
col-span-full gridColumn: 1 / -1
|
|
516
|
+
col-start-{n}/auto gridColumnStart
|
|
517
|
+
col-end-{n}/auto gridColumnEnd
|
|
518
|
+
row-span-{n} gridRow: span n / span n
|
|
519
|
+
row-span-full gridRow: 1 / -1
|
|
520
|
+
row-start-{n}/auto gridRowStart
|
|
521
|
+
row-end-{n}/auto gridRowEnd
|
|
522
|
+
place-items-start/end/center/stretch place-items
|
|
523
|
+
place-content-start/end/center/between/around/evenly/stretch place-content
|
|
524
|
+
place-self-start/end/center/auto/stretch place-self
|
|
525
|
+
|
|
526
|
+
Responsive grid example:
|
|
527
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
528
|
+
<div className="col-span-1 md:col-span-2">wide card</div>
|
|
529
|
+
</div>
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
### Position
|
|
533
|
+
```
|
|
534
|
+
static / relative / absolute / fixed / sticky position
|
|
535
|
+
inset-{n} top + right + bottom + left
|
|
536
|
+
inset-x-{n} left + right
|
|
537
|
+
inset-y-{n} top + bottom
|
|
538
|
+
top-{n} / right-{n} / bottom-{n} / left-{n}
|
|
539
|
+
z-{n} zIndex: 0 10 20 30 40 50 auto
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
### Overflow
|
|
543
|
+
```
|
|
544
|
+
overflow-hidden/visible/scroll/auto/clip
|
|
545
|
+
overflow-x-hidden/visible/scroll/auto/clip
|
|
546
|
+
overflow-y-hidden/visible/scroll/auto/clip
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
### Border
|
|
550
|
+
```
|
|
551
|
+
border borderWidth: 1
|
|
552
|
+
border-{n} borderWidth: 0 2 4 8
|
|
553
|
+
border-t/r/b/l border on one side
|
|
554
|
+
border-{color} borderColor
|
|
555
|
+
border-opacity-{n} border color opacity
|
|
556
|
+
border-solid/dashed/dotted/none borderStyle
|
|
557
|
+
rounded borderRadius: 4
|
|
558
|
+
rounded-none/sm/md/lg/xl/2xl/3xl/full
|
|
559
|
+
rounded-t/r/b/l border radius on one side
|
|
560
|
+
rounded-tl/tr/bl/br border radius on one corner
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
### Shadow
|
|
564
|
+
```
|
|
565
|
+
shadow-sm/DEFAULT/md/lg/xl/2xl/none
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
### Opacity
|
|
569
|
+
```
|
|
570
|
+
opacity-0/5/10/15/20/25/30/40/50/60/70/75/80/90/95/100
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
### Ring (web only)
|
|
574
|
+
```
|
|
575
|
+
ring box-shadow ring (2px)
|
|
576
|
+
ring-{n} ring width: 0 1 2 4 8
|
|
577
|
+
ring-{color} ring color
|
|
578
|
+
ring-opacity-{n} ring opacity
|
|
579
|
+
ring-offset-{n} ring offset: 0 1 2 4 8
|
|
580
|
+
ring-offset-{color}
|
|
581
|
+
ring-inset inset ring
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
### Outline (web only)
|
|
585
|
+
```
|
|
586
|
+
outline-none outline: none
|
|
587
|
+
outline outline: 2px solid transparent + offset 2px
|
|
588
|
+
outline-{n} outlineWidth: 0 1 2 4 8
|
|
589
|
+
outline-{color} outlineColor
|
|
590
|
+
outline-offset-{n} outlineOffset: 0 1 2 4 8
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
### Transforms
|
|
594
|
+
```
|
|
595
|
+
scale-{n} scale (0–150, step varies)
|
|
596
|
+
scale-x-{n} scaleX
|
|
597
|
+
scale-y-{n} scaleY
|
|
598
|
+
rotate-{n} rotate in degrees
|
|
599
|
+
translate-x-{n} translateX (uses spacing scale)
|
|
600
|
+
translate-y-{n} translateY
|
|
601
|
+
skew-x-{n} skewX
|
|
602
|
+
skew-y-{n} skewY
|
|
603
|
+
origin-center/top/top-right/right/bottom-right/bottom/bottom-left/left/top-left
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
### Filters (web only)
|
|
607
|
+
```
|
|
608
|
+
blur-{n} filter: blur
|
|
609
|
+
brightness-{n} filter: brightness
|
|
610
|
+
contrast-{n} filter: contrast
|
|
611
|
+
grayscale / grayscale-0
|
|
612
|
+
hue-rotate-{n} filter: hue-rotate
|
|
613
|
+
invert / invert-0
|
|
614
|
+
saturate-{n} filter: saturate
|
|
615
|
+
sepia / sepia-0
|
|
616
|
+
drop-shadow-{size} filter: drop-shadow
|
|
617
|
+
|
|
618
|
+
backdrop-blur-{n}
|
|
619
|
+
backdrop-brightness-{n}
|
|
620
|
+
backdrop-contrast-{n}
|
|
621
|
+
backdrop-grayscale
|
|
622
|
+
backdrop-hue-rotate-{n}
|
|
623
|
+
backdrop-invert
|
|
624
|
+
backdrop-opacity-{n}
|
|
625
|
+
backdrop-saturate-{n}
|
|
626
|
+
backdrop-sepia
|
|
627
|
+
backdrop-filter (enable backdrop filter)
|
|
628
|
+
filter (enable filter)
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
### Animation & Transition
|
|
632
|
+
```
|
|
633
|
+
animate-spin rotate 360deg loop
|
|
634
|
+
animate-ping scale + fade ping
|
|
635
|
+
animate-pulse opacity pulse
|
|
636
|
+
animate-bounce translate-y bounce
|
|
637
|
+
|
|
638
|
+
transition transition: all 150ms ease (web only)
|
|
639
|
+
duration-{n} transitionDuration: 75 100 150 200 300 500 700 1000
|
|
640
|
+
delay-{n} transitionDelay: 75 100 150 200 300 500 700 1000
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
### Cursor (web only)
|
|
644
|
+
```
|
|
645
|
+
cursor-auto / cursor-default / cursor-pointer / cursor-wait
|
|
646
|
+
cursor-text / cursor-move / cursor-not-allowed
|
|
647
|
+
cursor-grab / cursor-grabbing
|
|
648
|
+
cursor-zoom-in / cursor-zoom-out
|
|
649
|
+
cursor-crosshair / cursor-help / cursor-none
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
### Pointer events / User select (web only)
|
|
653
|
+
```
|
|
654
|
+
pointer-events-none / pointer-events-auto
|
|
655
|
+
select-none / select-text / select-all / select-auto
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
### Touch action (web only)
|
|
659
|
+
```
|
|
660
|
+
touch-auto / touch-none / touch-pan-x / touch-pan-y
|
|
661
|
+
touch-pan-left / touch-pan-right / touch-pan-up / touch-pan-down
|
|
662
|
+
touch-pinch-zoom / touch-manipulation
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
### Scroll (web only)
|
|
666
|
+
```
|
|
667
|
+
scroll-smooth scroll-behavior: smooth
|
|
668
|
+
scroll-auto scroll-behavior: auto
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
### Float & Clear (web only)
|
|
672
|
+
```
|
|
673
|
+
float-left / float-right / float-start / float-end / float-none
|
|
674
|
+
clear-left / clear-right / clear-both / clear-start / clear-end / clear-none
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
### Vertical align (web only)
|
|
678
|
+
```
|
|
679
|
+
align-baseline / align-top / align-middle / align-bottom
|
|
680
|
+
align-text-top / align-text-bottom / align-sub / align-super
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
### Visibility
|
|
684
|
+
```
|
|
685
|
+
visible visibility: visible
|
|
686
|
+
invisible visibility: hidden
|
|
687
|
+
sr-only visually hidden but screen-reader accessible
|
|
688
|
+
not-sr-only reverses sr-only
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
### List style
|
|
692
|
+
```
|
|
693
|
+
list-none / list-disc / list-decimal
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
### Appearance / Resize (web only)
|
|
697
|
+
```
|
|
698
|
+
appearance-none
|
|
699
|
+
resize / resize-none / resize-x / resize-y
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
### Box sizing (web only)
|
|
703
|
+
```
|
|
704
|
+
box-border box-sizing: border-box
|
|
705
|
+
box-content box-sizing: content-box
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
### Object fit (web only)
|
|
709
|
+
```
|
|
710
|
+
object-contain / object-cover / object-fill / object-none / object-scale-down
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
### Aspect ratio (web only)
|
|
714
|
+
```
|
|
715
|
+
aspect-auto aspect-ratio: auto
|
|
716
|
+
aspect-square aspect-ratio: 1 / 1
|
|
717
|
+
aspect-video aspect-ratio: 16 / 9
|
|
718
|
+
aspect-{arbitrary} e.g. aspect-[4/3]
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
### Columns (web only)
|
|
722
|
+
```
|
|
723
|
+
columns-{n} column-count: 1–12
|
|
724
|
+
columns-auto column-count: auto
|
|
725
|
+
columns-{size} column-width: 3xs(16rem) 2xs(18rem) xs(20rem) sm(24rem)
|
|
726
|
+
md(28rem) lg(32rem) xl(36rem) 2xl(42rem)
|
|
727
|
+
3xl(48rem) 4xl(56rem) 5xl(64rem) 6xl(72rem) 7xl(80rem)
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
### Caret / Accent (web only)
|
|
731
|
+
```
|
|
732
|
+
caret-{color} caret-color
|
|
733
|
+
caret-auto caret-color: auto
|
|
734
|
+
caret-transparent caret-color: transparent
|
|
735
|
+
accent-{color} accent-color
|
|
736
|
+
accent-auto accent-color: auto
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
### Mix blend / Background blend (web only)
|
|
740
|
+
```
|
|
741
|
+
mix-blend-{mode} mix-blend-mode
|
|
742
|
+
bg-blend-{mode} background-blend-mode
|
|
743
|
+
modes: normal multiply screen overlay darken lighten color-dodge
|
|
744
|
+
color-burn hard-light soft-light difference exclusion
|
|
745
|
+
hue saturation color luminosity (plus-lighter for mix-blend only)
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
### Will-change (web only)
|
|
749
|
+
```
|
|
750
|
+
will-change-auto / will-change-scroll / will-change-contents / will-change-transform
|
|
751
|
+
will-change-[transform,opacity] arbitrary
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
### Divide (web only, uses child combinator CSS)
|
|
755
|
+
```
|
|
756
|
+
divide-x-{n} border between horizontal children
|
|
757
|
+
divide-y-{n} border between vertical children
|
|
758
|
+
divide-{color} divider color
|
|
759
|
+
divide-solid/dashed/dotted
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
### Space between
|
|
763
|
+
```
|
|
764
|
+
space-x-{n} margin-left on children (> * + *)
|
|
765
|
+
space-y-{n} margin-top on children
|
|
766
|
+
```
|
|
767
|
+
|
|
768
|
+
### Group / Peer standalones
|
|
769
|
+
```
|
|
770
|
+
group standalone marker class (no styles, silences dev warning)
|
|
771
|
+
peer standalone marker class
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
---
|
|
775
|
+
|
|
776
|
+
## Native-only Utilities
|
|
777
|
+
|
|
778
|
+
These only work in `@kbach/native` / React Native:
|
|
779
|
+
```
|
|
780
|
+
tint-{color} tintColor (Image / icon tinting)
|
|
781
|
+
perspective-{n} perspective transform
|
|
782
|
+
backface-hidden backfaceVisibility: hidden
|
|
783
|
+
text-shadow text shadow (small)
|
|
784
|
+
text-shadow-lg text shadow (large)
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
---
|
|
788
|
+
|
|
789
|
+
## Web-only Utilities (gracefully ignored on native)
|
|
790
|
+
|
|
791
|
+
The following resolve to `null` on React Native and produce no warning:
|
|
792
|
+
`caret-*`, `accent-*`, `touch-*`, `float-*`, `clear-*`, `align-*` (vertical),
|
|
793
|
+
`line-clamp-*`, `scroll-smooth`, `scroll-auto`, `overflow-clip`,
|
|
794
|
+
`overflow-ellipsis`, `bg-clip-text`, `bg-gradient-to-*`,
|
|
795
|
+
`animate-*`, `transition`, `filter`, `backdrop-filter`,
|
|
796
|
+
`print:`, `before:`, `after:`, `selection:`, `first-letter:`, `first-line:`, `marker:`,
|
|
797
|
+
`landscape:`, `portrait:`, `motion-reduce:`, `motion-safe:`,
|
|
798
|
+
`contrast-more:`, `contrast-less:`, `rtl:`, `ltr:`,
|
|
799
|
+
`mix-blend-*`, `bg-blend-*`, `will-change-*`, `columns-*`, `aspect-*`,
|
|
800
|
+
`object-*`, `resize-*`, `appearance-none`, `box-border`, `box-content`,
|
|
801
|
+
`subpixel-antialiased`, `overflow-ellipsis`, `flow-root`, `contents`,
|
|
802
|
+
`grid`, `inline-grid`, `grid-cols-*`, etc.
|
|
803
|
+
|
|
804
|
+
---
|
|
805
|
+
|
|
806
|
+
## Theme Configuration
|
|
807
|
+
|
|
808
|
+
### kbach.config.js (project root)
|
|
809
|
+
```js
|
|
810
|
+
module.exports = {
|
|
811
|
+
darkMode: 'attribute', // 'attribute' | 'class' | 'media'
|
|
812
|
+
|
|
813
|
+
theme: {
|
|
814
|
+
// Fully replace a scale
|
|
815
|
+
colors: {
|
|
816
|
+
brand: { 1: '#eff6ff', 6: '#3b82f6', 10: '#1e3a8a' },
|
|
817
|
+
},
|
|
818
|
+
},
|
|
819
|
+
|
|
820
|
+
extend: {
|
|
821
|
+
theme: {
|
|
822
|
+
// Merge into existing scale
|
|
823
|
+
colors: { brand: { 6: '#6366f1' } },
|
|
824
|
+
spacing: { 18: 72, 22: 88 },
|
|
825
|
+
fontSize: { '10xl': 160 },
|
|
826
|
+
},
|
|
827
|
+
},
|
|
828
|
+
|
|
829
|
+
plugins: [
|
|
830
|
+
({ addUtility, theme }) => {
|
|
831
|
+
addUtility('border-brand', {
|
|
832
|
+
borderColor: theme('colors.brand.6'),
|
|
833
|
+
borderWidth: 2,
|
|
834
|
+
});
|
|
835
|
+
},
|
|
836
|
+
],
|
|
837
|
+
};
|
|
838
|
+
```
|
|
839
|
+
|
|
840
|
+
### Runtime update
|
|
841
|
+
```js
|
|
842
|
+
import { updateConfig } from '@kbach/react';
|
|
843
|
+
updateConfig({ extend: { theme: { colors: { brand: { 6: '#6366f1' } } } } });
|
|
844
|
+
// Always call clearCache() after updateConfig() to flush stale resolved styles.
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
### Default theme values
|
|
848
|
+
```
|
|
849
|
+
spacing: 1 unit = 4px (see Spacing section above)
|
|
850
|
+
fontSize: xs–9xl (12–128px)
|
|
851
|
+
fontFamily: sans('System') mono('Courier New') serif('Georgia')
|
|
852
|
+
fontWeight: thin(100) extralight(200) light(300) normal(400) medium(500)
|
|
853
|
+
semibold(600) bold(700) extrabold(800) black(900)
|
|
854
|
+
borderRadius: none(0) sm(2) DEFAULT(4) md(6) lg(8) xl(12) 2xl(16) 3xl(24) full(9999)
|
|
855
|
+
borderWidth: DEFAULT(1) 0 2 4 8
|
|
856
|
+
opacity: 0 5 10 15 20 25 30 40 50 60 70 75 80 90 95 100
|
|
857
|
+
lineHeight: none(1) tight(1.25) snug(1.375) normal(1.5) relaxed(1.625) loose(2) + 3–10 (12–40px)
|
|
858
|
+
letterSpacing:tighter(-0.8) tight(-0.4) normal(0) wide(0.4) wider(0.8) widest(1.6)
|
|
859
|
+
zIndex: auto 0 10 20 30 40 50
|
|
860
|
+
screens: sm(576) md(768) lg(1024) xl(1280) 2xl(1536)
|
|
861
|
+
```
|
|
862
|
+
|
|
863
|
+
---
|
|
864
|
+
|
|
865
|
+
## Common Patterns
|
|
866
|
+
|
|
867
|
+
### Dark mode card
|
|
868
|
+
```jsx
|
|
869
|
+
<div className="bg-white dark:bg-gray-9 rounded-2xl p-6 shadow-md">
|
|
870
|
+
<h2 className="text-2xl font-bold text-gray-10 dark:text-white">Title</h2>
|
|
871
|
+
<p className="text-gray-6 dark:text-gray-4 mt-2">Body text</p>
|
|
872
|
+
</div>
|
|
873
|
+
```
|
|
874
|
+
|
|
875
|
+
### Interactive button
|
|
876
|
+
```jsx
|
|
877
|
+
<button className="bg-blue-7 hover:bg-blue-8 active:bg-blue-9 disabled:opacity-50 disabled:cursor-not-allowed text-white font-semibold px-6 py-3 rounded-xl transition" />
|
|
878
|
+
```
|
|
879
|
+
|
|
880
|
+
### Responsive layout
|
|
881
|
+
```jsx
|
|
882
|
+
<div className="flex flex-col md:flex-row gap-4">
|
|
883
|
+
<aside className="w-full md:w-64 lg:w-80">…</aside>
|
|
884
|
+
<main className="flex-1">…</main>
|
|
885
|
+
</div>
|
|
886
|
+
```
|
|
887
|
+
|
|
888
|
+
### Responsive grid
|
|
889
|
+
```jsx
|
|
890
|
+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
|
|
891
|
+
{items.map(item => <Card key={item.id} />)}
|
|
892
|
+
</div>
|
|
893
|
+
```
|
|
894
|
+
|
|
895
|
+
### Group hover reveal
|
|
896
|
+
```jsx
|
|
897
|
+
<div className="group relative overflow-hidden rounded-xl">
|
|
898
|
+
<img src="…" className="transition group-hover:scale-105" />
|
|
899
|
+
<div className="absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition flex items-center justify-center">
|
|
900
|
+
<span className="text-white font-bold">View</span>
|
|
901
|
+
</div>
|
|
902
|
+
</div>
|
|
903
|
+
```
|
|
904
|
+
|
|
905
|
+
### Reduced-motion safe animation
|
|
906
|
+
```jsx
|
|
907
|
+
<div className="motion-safe:animate-spin motion-reduce:opacity-75" />
|
|
908
|
+
```
|
|
909
|
+
|
|
910
|
+
### RTL-aware spacing
|
|
911
|
+
```jsx
|
|
912
|
+
<div className="ltr:pl-4 rtl:pr-4 ltr:text-left rtl:text-right" />
|
|
913
|
+
```
|
|
914
|
+
|
|
915
|
+
### Before/after pseudo-elements
|
|
916
|
+
```jsx
|
|
917
|
+
<div className="relative before:absolute before:inset-0 before:bg-blue-6/10 before:rounded-xl" />
|
|
918
|
+
```
|
|
919
|
+
|
|
920
|
+
### Input with caret and focus ring
|
|
921
|
+
```jsx
|
|
922
|
+
<input className="caret-blue-6 focus:ring-2 focus:ring-blue-5 focus:outline-none border border-gray-4 rounded-lg px-4 py-2" />
|
|
923
|
+
```
|
|
924
|
+
|
|
925
|
+
### Print-specific styles
|
|
926
|
+
```jsx
|
|
927
|
+
<nav className="print:hidden" />
|
|
928
|
+
<article className="print:text-black print:bg-white print:shadow-none" />
|
|
929
|
+
```
|
|
930
|
+
|
|
931
|
+
### Contrast accessibility
|
|
932
|
+
```jsx
|
|
933
|
+
<button className="bg-blue-6 contrast-more:bg-blue-9 contrast-more:border-2 contrast-more:border-blue-11 text-white">
|
|
934
|
+
Submit
|
|
935
|
+
</button>
|
|
936
|
+
```
|
|
937
|
+
|
|
938
|
+
---
|
|
939
|
+
|
|
940
|
+
## Caching
|
|
941
|
+
|
|
942
|
+
The resolver uses an LRU cache (10,000 entries). Cache is automatically cleared on `updateConfig()`. Manually:
|
|
943
|
+
```js
|
|
944
|
+
import { clearCache } from '@kbach/react';
|
|
945
|
+
clearCache();
|
|
946
|
+
```
|
|
947
|
+
|
|
948
|
+
---
|
|
949
|
+
|
|
950
|
+
## Package Versions
|
|
951
|
+
- `@kbach/react`: see `packages/react/package.json`
|
|
952
|
+
- `@kbach/native`: see `packages/native/package.json` (depends on `@kbach/react`)
|