castlecraftstudios-ui 1.0.0 → 1.0.1
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 +345 -72
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,73 +1,346 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
##
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
1
|
+
# castlecraftstudios-ui
|
|
2
|
+
|
|
3
|
+
Accessible, zero-dependency React component library with built-in dark mode support.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/castlecraftstudios-ui)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](https://react.dev)
|
|
8
|
+
[](https://www.typescriptlang.org)
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- 16 fully typed components — buttons, forms, overlays, feedback, and more
|
|
13
|
+
- Dark mode out of the box — respects `prefers-color-scheme` or a `data-theme` attribute
|
|
14
|
+
- Zero runtime dependencies — no UI library bloat
|
|
15
|
+
- Accessible by default — ARIA attributes, keyboard navigation, focus management
|
|
16
|
+
- Tree-shakable — ESM + CJS dual build
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install castlecraftstudios-ui
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Then import the stylesheet once at your app root:
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
import 'castlecraftstudios-ui/styles'
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import { Button, Input, Modal } from 'castlecraftstudios-ui'
|
|
34
|
+
import 'castlecraftstudios-ui/styles'
|
|
35
|
+
|
|
36
|
+
export default function App() {
|
|
37
|
+
return <Button variant="primary">Get started</Button>
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Components
|
|
42
|
+
|
|
43
|
+
### Button
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import { Button } from 'castlecraftstudios-ui'
|
|
47
|
+
|
|
48
|
+
<Button variant="primary" size="md">Save</Button>
|
|
49
|
+
<Button variant="outline" disabled>Cancel</Button>
|
|
50
|
+
<Button variant="ghost" size="sm">Learn more</Button>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
| Prop | Type | Default |
|
|
54
|
+
|------|------|---------|
|
|
55
|
+
| `variant` | `'primary' \| 'secondary' \| 'outline' \| 'ghost'` | `'primary'` |
|
|
56
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` |
|
|
57
|
+
| + all `<button>` HTML attributes | | |
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
### Input / Textarea / Select
|
|
62
|
+
|
|
63
|
+
All three share the same API surface.
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
import { Input, Textarea, Select } from 'castlecraftstudios-ui'
|
|
67
|
+
|
|
68
|
+
<Input label="Email" type="email" placeholder="you@example.com" />
|
|
69
|
+
<Input label="Username" error="Already taken" />
|
|
70
|
+
<Input label="Bio" helperText="Keep it short" />
|
|
71
|
+
|
|
72
|
+
<Textarea label="Description" rows={6} />
|
|
73
|
+
|
|
74
|
+
<Select label="Country">
|
|
75
|
+
<option value="us">United States</option>
|
|
76
|
+
<option value="uk">United Kingdom</option>
|
|
77
|
+
</Select>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
| Prop | Type |
|
|
81
|
+
|------|------|
|
|
82
|
+
| `label` | `string` |
|
|
83
|
+
| `helperText` | `string` |
|
|
84
|
+
| `error` | `string` |
|
|
85
|
+
| `size` | `'sm' \| 'md' \| 'lg'` |
|
|
86
|
+
| + native HTML attributes | |
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
### Toggle / Checkbox / Radio
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
import { Toggle, Checkbox, Radio } from 'castlecraftstudios-ui'
|
|
94
|
+
|
|
95
|
+
<Toggle label="Enable notifications" defaultChecked />
|
|
96
|
+
<Checkbox label="I agree to the terms" />
|
|
97
|
+
<Radio label="Option A" name="group" value="a" />
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
### Card
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
import { Card } from 'castlecraftstudios-ui'
|
|
106
|
+
|
|
107
|
+
<Card variant="elevated" header="Title" footer={<Button>Action</Button>}>
|
|
108
|
+
Card content goes here.
|
|
109
|
+
</Card>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
| Prop | Type | Default |
|
|
113
|
+
|------|------|---------|
|
|
114
|
+
| `variant` | `'default' \| 'elevated' \| 'outline' \| 'flat'` | `'default'` |
|
|
115
|
+
| `header` | `ReactNode` | — |
|
|
116
|
+
| `footer` | `ReactNode` | — |
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
### Modal
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
import { useState } from 'react'
|
|
124
|
+
import { Modal, Button } from 'castlecraftstudios-ui'
|
|
125
|
+
|
|
126
|
+
function Example() {
|
|
127
|
+
const [open, setOpen] = useState(false)
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<>
|
|
131
|
+
<Button onClick={() => setOpen(true)}>Open modal</Button>
|
|
132
|
+
<Modal
|
|
133
|
+
open={open}
|
|
134
|
+
onClose={() => setOpen(false)}
|
|
135
|
+
title="Confirm action"
|
|
136
|
+
size="md"
|
|
137
|
+
footer={<Button onClick={() => setOpen(false)}>Done</Button>}
|
|
138
|
+
>
|
|
139
|
+
Are you sure you want to continue?
|
|
140
|
+
</Modal>
|
|
141
|
+
</>
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
| Prop | Type |
|
|
147
|
+
|------|------|
|
|
148
|
+
| `open` | `boolean` |
|
|
149
|
+
| `onClose` | `() => void` |
|
|
150
|
+
| `title` | `string` |
|
|
151
|
+
| `size` | `'sm' \| 'md' \| 'lg'` |
|
|
152
|
+
| `footer` | `ReactNode` |
|
|
153
|
+
|
|
154
|
+
Closes on Escape key press or backdrop click.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
### Alert
|
|
159
|
+
|
|
160
|
+
```tsx
|
|
161
|
+
import { Alert } from 'castlecraftstudios-ui'
|
|
162
|
+
|
|
163
|
+
<Alert variant="success" title="Saved!">Your changes have been saved.</Alert>
|
|
164
|
+
<Alert variant="error" title="Error" onDismiss={() => {}}>Something went wrong.</Alert>
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
| Prop | Type |
|
|
168
|
+
|------|------|
|
|
169
|
+
| `variant` | `'success' \| 'warning' \| 'error' \| 'info'` |
|
|
170
|
+
| `title` | `string` |
|
|
171
|
+
| `onDismiss` | `() => void` |
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
### Toast
|
|
176
|
+
|
|
177
|
+
```tsx
|
|
178
|
+
import { useState } from 'react'
|
|
179
|
+
import { Toast, Button } from 'castlecraftstudios-ui'
|
|
180
|
+
|
|
181
|
+
function Example() {
|
|
182
|
+
const [open, setOpen] = useState(false)
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
<>
|
|
186
|
+
<Button onClick={() => setOpen(true)}>Show toast</Button>
|
|
187
|
+
<Toast
|
|
188
|
+
open={open}
|
|
189
|
+
variant="success"
|
|
190
|
+
title="Done!"
|
|
191
|
+
onDismiss={() => setOpen(false)}
|
|
192
|
+
>
|
|
193
|
+
Your item was created.
|
|
194
|
+
</Toast>
|
|
195
|
+
</>
|
|
196
|
+
)
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Renders in a portal at the bottom-right of the viewport.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
### Badge
|
|
205
|
+
|
|
206
|
+
```tsx
|
|
207
|
+
import { Badge } from 'castlecraftstudios-ui'
|
|
208
|
+
|
|
209
|
+
<Badge variant="success">Active</Badge>
|
|
210
|
+
<Badge variant="warning" dot />
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
| Prop | Type |
|
|
214
|
+
|------|------|
|
|
215
|
+
| `variant` | `'default' \| 'success' \| 'warning' \| 'error' \| 'info'` |
|
|
216
|
+
| `dot` | `boolean` |
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
### Spinner
|
|
221
|
+
|
|
222
|
+
```tsx
|
|
223
|
+
import { Spinner } from 'castlecraftstudios-ui'
|
|
224
|
+
|
|
225
|
+
<Spinner size="md" />
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
| Prop | Type |
|
|
229
|
+
|------|------|
|
|
230
|
+
| `size` | `'sm' \| 'md' \| 'lg'` |
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
### Tooltip
|
|
235
|
+
|
|
236
|
+
```tsx
|
|
237
|
+
import { Tooltip, Button } from 'castlecraftstudios-ui'
|
|
238
|
+
|
|
239
|
+
<Tooltip content="Save your changes" position="top">
|
|
240
|
+
<Button>Save</Button>
|
|
241
|
+
</Tooltip>
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
| Prop | Type | Default |
|
|
245
|
+
|------|------|---------|
|
|
246
|
+
| `content` | `string` | — |
|
|
247
|
+
| `position` | `'top' \| 'bottom' \| 'left' \| 'right'` | `'top'` |
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
### DatePicker
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
import { useState } from 'react'
|
|
255
|
+
import { DatePicker } from 'castlecraftstudios-ui'
|
|
256
|
+
|
|
257
|
+
function Example() {
|
|
258
|
+
const [date, setDate] = useState<Date | null>(null)
|
|
259
|
+
|
|
260
|
+
return (
|
|
261
|
+
<DatePicker
|
|
262
|
+
label="Appointment date"
|
|
263
|
+
value={date}
|
|
264
|
+
onChange={setDate}
|
|
265
|
+
min={new Date()}
|
|
266
|
+
/>
|
|
267
|
+
)
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
| Prop | Type |
|
|
272
|
+
|------|------|
|
|
273
|
+
| `label` | `string` |
|
|
274
|
+
| `value` | `Date \| null` |
|
|
275
|
+
| `onChange` | `(date: Date \| null) => void` |
|
|
276
|
+
| `min` | `Date` |
|
|
277
|
+
| `max` | `Date` |
|
|
278
|
+
| `placeholder` | `string` |
|
|
279
|
+
| `disabled` | `boolean` |
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
### Tabs
|
|
284
|
+
|
|
285
|
+
```tsx
|
|
286
|
+
import { Tabs, TabList, Tab, TabPanel } from 'castlecraftstudios-ui'
|
|
287
|
+
|
|
288
|
+
<Tabs defaultValue="overview">
|
|
289
|
+
<TabList>
|
|
290
|
+
<Tab value="overview">Overview</Tab>
|
|
291
|
+
<Tab value="settings">Settings</Tab>
|
|
292
|
+
<Tab value="billing" disabled>Billing</Tab>
|
|
293
|
+
</TabList>
|
|
294
|
+
|
|
295
|
+
<TabPanel value="overview">Overview content</TabPanel>
|
|
296
|
+
<TabPanel value="settings">Settings content</TabPanel>
|
|
297
|
+
<TabPanel value="billing">Billing content</TabPanel>
|
|
298
|
+
</Tabs>
|
|
73
299
|
```
|
|
300
|
+
|
|
301
|
+
Supports controlled mode via `value` + `onChange`. Arrow keys, Home, and End navigate between tabs.
|
|
302
|
+
|
|
303
|
+
## Dark Mode
|
|
304
|
+
|
|
305
|
+
The library respects the system `prefers-color-scheme` media query automatically. To override explicitly, set a `data-theme` attribute on the root element:
|
|
306
|
+
|
|
307
|
+
```tsx
|
|
308
|
+
// Force dark mode
|
|
309
|
+
document.documentElement.setAttribute('data-theme', 'dark')
|
|
310
|
+
|
|
311
|
+
// Force light mode
|
|
312
|
+
document.documentElement.setAttribute('data-theme', 'light')
|
|
313
|
+
|
|
314
|
+
// Reset to system preference
|
|
315
|
+
document.documentElement.removeAttribute('data-theme')
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
All colors are driven by CSS custom properties, making it easy to override individual tokens:
|
|
319
|
+
|
|
320
|
+
```css
|
|
321
|
+
:root {
|
|
322
|
+
--accent: #7c3aed; /* primary brand color */
|
|
323
|
+
--bg: #ffffff; /* surface background */
|
|
324
|
+
--text: #374151; /* body text */
|
|
325
|
+
--text-h: #111827; /* heading text */
|
|
326
|
+
--border: #e5e7eb; /* borders and dividers */
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## TypeScript
|
|
331
|
+
|
|
332
|
+
Full TypeScript definitions are included. Each component extends its corresponding HTML element's attribute types, so all native props work as expected:
|
|
333
|
+
|
|
334
|
+
```tsx
|
|
335
|
+
import type { ComponentProps } from 'react'
|
|
336
|
+
import { Button } from 'castlecraftstudios-ui'
|
|
337
|
+
|
|
338
|
+
// Works — onClick, aria-label, data-*, etc. are all valid
|
|
339
|
+
<Button onClick={handleClick} aria-label="Submit form" data-testid="submit">
|
|
340
|
+
Submit
|
|
341
|
+
</Button>
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
## License
|
|
345
|
+
|
|
346
|
+
MIT
|