@kbach/react 0.1.0 → 0.1.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/README.md +270 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# @kbach/react
|
|
2
|
+
|
|
3
|
+
Tailwind-like utility classes for **React (web)**. Classes are converted to inline styles at render time through a custom JSX runtime — no stylesheet required.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
/** @jsxImportSource @kbach/react */
|
|
7
|
+
|
|
8
|
+
<div className="bg-white dark:bg-gray-10 p-4 rounded-xl shadow" />
|
|
9
|
+
<div className="bg-blue-7 hover:bg-blue-8 dark:bg-indigo-6 rounded-lg px-6 py-3" />
|
|
10
|
+
<div className="bg-[#6366f1] p-[14px] rounded-[20px]" />
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @kbach/react
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Setup
|
|
20
|
+
|
|
21
|
+
### 1. Configure the JSX runtime
|
|
22
|
+
|
|
23
|
+
**tsconfig.json**
|
|
24
|
+
|
|
25
|
+
```jsonc
|
|
26
|
+
{
|
|
27
|
+
"compilerOptions": {
|
|
28
|
+
"jsx": "react-jsx",
|
|
29
|
+
"jsxImportSource": "@kbach/react"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Vite**
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
// vite.config.ts
|
|
38
|
+
import { defineConfig } from 'vite';
|
|
39
|
+
import react from '@vitejs/plugin-react';
|
|
40
|
+
|
|
41
|
+
export default defineConfig({
|
|
42
|
+
plugins: [react({ jsxImportSource: '@kbach/react' })],
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Babel**
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
// babel.config.js
|
|
50
|
+
module.exports = {
|
|
51
|
+
presets: [
|
|
52
|
+
['@babel/preset-react', { runtime: 'automatic', importSource: '@kbach/react' }],
|
|
53
|
+
],
|
|
54
|
+
};
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Per-file pragma** (no config change required)
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
/** @jsxImportSource @kbach/react */
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 2. Wrap your app
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
import { ThemeProvider } from '@kbach/react';
|
|
67
|
+
|
|
68
|
+
export default function Root() {
|
|
69
|
+
return (
|
|
70
|
+
<ThemeProvider defaultMode="system">
|
|
71
|
+
<App />
|
|
72
|
+
</ThemeProvider>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## API
|
|
78
|
+
|
|
79
|
+
### className prop
|
|
80
|
+
|
|
81
|
+
Works on any HTML element or React component once the JSX runtime is configured.
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
<div className="bg-white dark:bg-gray-10 p-4 rounded-xl" />
|
|
85
|
+
<p className="text-gray-10 dark:text-white text-lg font-bold" />
|
|
86
|
+
<button className="bg-blue-7 hover:bg-blue-8 pressed:bg-blue-8 rounded-lg px-4 py-2" />
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### styled(Component, classes)
|
|
90
|
+
|
|
91
|
+
Pre-style any component. Returns a new component that merges the base classes with any `className` or `tw` prop passed at use time.
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
import { styled } from '@kbach/react';
|
|
95
|
+
|
|
96
|
+
const Card = styled('div', 'bg-white dark:bg-gray-9 rounded-2xl p-6 shadow');
|
|
97
|
+
const Title = styled('h2', 'text-2xl font-bold text-gray-10 dark:text-white');
|
|
98
|
+
const Button = styled(
|
|
99
|
+
'button',
|
|
100
|
+
'bg-blue-7 hover:bg-blue-8 dark:bg-indigo-6 rounded-xl px-6 py-3'
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
// Pass extra classes at use time
|
|
104
|
+
<Card tw="mt-4 mb-2">
|
|
105
|
+
<Title tw="text-3xl">Hello</Title>
|
|
106
|
+
</Card>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### useStyles(classes)
|
|
110
|
+
|
|
111
|
+
Resolve classes to a style object inside a component.
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
import { useStyles } from '@kbach/react';
|
|
115
|
+
|
|
116
|
+
function Badge() {
|
|
117
|
+
const style = useStyles('bg-blue-6 dark:bg-indigo-6 px-3 py-1 rounded-full');
|
|
118
|
+
return <span style={style}>New</span>;
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### tw(classes)
|
|
123
|
+
|
|
124
|
+
Resolve classes outside a component (static contexts).
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
import { tw } from '@kbach/react';
|
|
128
|
+
|
|
129
|
+
const cardStyle = tw('bg-white p-4 rounded-xl') as React.CSSProperties;
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### cx(...classes)
|
|
133
|
+
|
|
134
|
+
Conditionally join class strings. Falsy values are ignored.
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
import { cx } from '@kbach/react';
|
|
138
|
+
|
|
139
|
+
<div className={cx(
|
|
140
|
+
'p-4 rounded-xl',
|
|
141
|
+
isSelected && 'border-2 border-blue-6',
|
|
142
|
+
isDisabled && 'opacity-50',
|
|
143
|
+
)} />
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### useTheme()
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
import { useTheme } from '@kbach/react';
|
|
150
|
+
|
|
151
|
+
const { mode, resolvedMode, isDark, setMode, toggle } = useTheme();
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
| Value | Type | Description |
|
|
155
|
+
|---|---|---|
|
|
156
|
+
| mode | `'light' \| 'dark' \| 'system'` | User-selected mode |
|
|
157
|
+
| resolvedMode | `'light' \| 'dark'` | Resolved after system lookup |
|
|
158
|
+
| isDark | boolean | Shorthand for `resolvedMode === 'dark'` |
|
|
159
|
+
| setMode | function | Set mode explicitly |
|
|
160
|
+
| toggle | function | Toggle between light and dark |
|
|
161
|
+
|
|
162
|
+
### ThemeToggle
|
|
163
|
+
|
|
164
|
+
Drop-in toggle component.
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
<ThemeToggle /> // button (default)
|
|
168
|
+
<ThemeToggle variant="switch" /> // toggle switch
|
|
169
|
+
<ThemeToggle variant="icon-button" /> // icon button
|
|
170
|
+
<ThemeToggle variant="button" includeSystem /> // three-way selector
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Modifiers
|
|
174
|
+
|
|
175
|
+
Up to 3 modifiers can be chained in any order.
|
|
176
|
+
|
|
177
|
+
| Modifier | Trigger |
|
|
178
|
+
|---|---|
|
|
179
|
+
| dark: | Dark mode active |
|
|
180
|
+
| light: | Light mode active |
|
|
181
|
+
| hover: | Mouse hover |
|
|
182
|
+
| pressed: | Click or touch |
|
|
183
|
+
| focus: | Element focused |
|
|
184
|
+
| active: | Element active |
|
|
185
|
+
| disabled: | Element disabled |
|
|
186
|
+
|
|
187
|
+
```tsx
|
|
188
|
+
<div className="dark:hover:bg-gray-9" />
|
|
189
|
+
<button className="dark:pressed:bg-indigo-8" />
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Arbitrary values
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
<div className="bg-[#6366f1]" />
|
|
196
|
+
<div className="p-[14px]" />
|
|
197
|
+
<div className="text-[18px]" />
|
|
198
|
+
<div className="bg-[rgba(99,102,241,0.15)]" />
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Color with opacity
|
|
202
|
+
|
|
203
|
+
```tsx
|
|
204
|
+
<div className="bg-blue-6/50" /> // 50% opacity
|
|
205
|
+
<div className="bg-gray-10/75" /> // 75% opacity
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Color scale
|
|
209
|
+
|
|
210
|
+
Colors use an 11-shade scale — 1 is lightest, 11 is darkest.
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
shade 1 · 2 · 3 · 4 · 5 · 6 · 7 · 8 · 9 · 10 · 11
|
|
214
|
+
light ─────────────────────────────────────────────────────────── dark
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Available families: slate, gray, zinc, neutral, stone, red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose.
|
|
218
|
+
|
|
219
|
+
## Common utilities
|
|
220
|
+
|
|
221
|
+
| Category | Examples |
|
|
222
|
+
|---|---|
|
|
223
|
+
| Background | `bg-white`, `bg-gray-10`, `bg-blue-6`, `bg-[#fff]` |
|
|
224
|
+
| Text | `text-sm`, `text-2xl`, `text-gray-10`, `font-bold` |
|
|
225
|
+
| Padding | `p-4`, `px-6`, `py-3` |
|
|
226
|
+
| Margin | `m-4`, `mx-auto`, `mt-2`, `-mt-4` |
|
|
227
|
+
| Size | `w-full`, `h-12`, `w-[200px]` |
|
|
228
|
+
| Flex | `flex-1`, `flex-row`, `items-center`, `justify-between`, `gap-4` |
|
|
229
|
+
| Border | `border`, `border-2`, `border-gray-4`, `rounded-xl` |
|
|
230
|
+
| Shadow | `shadow`, `shadow-md`, `shadow-lg` |
|
|
231
|
+
| Opacity | `opacity-50`, `opacity-75` |
|
|
232
|
+
|
|
233
|
+
## Configuration
|
|
234
|
+
|
|
235
|
+
```js
|
|
236
|
+
// kbach.config.js
|
|
237
|
+
module.exports = {
|
|
238
|
+
darkMode: 'attribute', // 'attribute' | 'class' | 'media'
|
|
239
|
+
|
|
240
|
+
theme: {
|
|
241
|
+
colors: {
|
|
242
|
+
brand: { 1: '#eff6ff', 6: '#3b82f6', 10: '#1e3a5f' },
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
|
|
246
|
+
extend: {
|
|
247
|
+
theme: {
|
|
248
|
+
colors: { brand: { 6: '#6366f1' } },
|
|
249
|
+
spacing: { 18: '72px' },
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
|
|
253
|
+
plugins: [
|
|
254
|
+
({ addUtility, theme }) => {
|
|
255
|
+
addUtility('border-brand', {
|
|
256
|
+
borderColor: theme('colors.brand.6'),
|
|
257
|
+
borderWidth: 2,
|
|
258
|
+
});
|
|
259
|
+
},
|
|
260
|
+
],
|
|
261
|
+
};
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Apply at runtime:
|
|
265
|
+
|
|
266
|
+
```tsx
|
|
267
|
+
import { updateConfig } from '@kbach/react';
|
|
268
|
+
|
|
269
|
+
updateConfig({ extend: { theme: { colors: { brand: { 6: '#6366f1' } } } } });
|
|
270
|
+
```
|