@kbach/react 0.5.1 → 0.5.2

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 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`)