@simple-base/solid 0.1.0 → 0.1.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.
Files changed (2) hide show
  1. package/README.md +247 -0
  2. package/package.json +7 -2
package/README.md ADDED
@@ -0,0 +1,247 @@
1
+ # @simple-base/solid
2
+
3
+ Accessible [SolidJS](https://www.solidjs.com/) components for Simple Base — native element behavior, a small props surface, and styling that lives in plain CSS.
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ pnpm add @simple-base/solid
9
+ ```
10
+
11
+ Install the stylesheet alongside it, since the components only emit class names and attributes:
12
+
13
+ ```sh
14
+ pnpm add @simple-base/css
15
+ ```
16
+
17
+ `solid-js` is a peer dependency and is not bundled.
18
+
19
+ ## Quick start
20
+
21
+ Import the stylesheet once in your entry point:
22
+
23
+ ```ts
24
+ import "@simple-base/css";
25
+ ```
26
+
27
+ Then use the components. Every component accepts `class` plus the native attributes for the element it renders:
28
+
29
+ ```tsx
30
+ import { Badge, Button, Input } from "@simple-base/solid";
31
+
32
+ export function Toolbar() {
33
+ return (
34
+ <form>
35
+ <Input name="email" type="email" placeholder="you@example.com" required />
36
+ <Button type="submit">Save</Button>
37
+ <Button variant="ghost" size="small">
38
+ Cancel
39
+ </Button>
40
+ <Badge variant="success">Active</Badge>
41
+ </form>
42
+ );
43
+ }
44
+ ```
45
+
46
+ Prefer importing only the stylesheets you use:
47
+
48
+ ```ts
49
+ import "@simple-base/tokens/css";
50
+ import "@simple-base/css/button";
51
+ import "@simple-base/css/badge";
52
+ ```
53
+
54
+ ## Components
55
+
56
+ **Simple components** render one element and take native props:
57
+
58
+ | Component | Renders | Options |
59
+ | ---------- | ---------------------- | ---------------------------------------------------------- |
60
+ | `Button` | `button` | `variant`, `size` |
61
+ | `Badge` | `span` | `variant`, `size` |
62
+ | `Input` | `input` | Native input props; `type` excludes `radio` and `checkbox` |
63
+ | `TextArea` | `textarea` | Native props |
64
+ | `Checkbox` | `input[type=checkbox]` | Native props |
65
+ | `Radio` | `input[type=radio]` | Native props |
66
+ | `Switch` | `input[role=switch]` | Native props; requires `aria-label` or `aria-labelledby` |
67
+
68
+ **Compound components** expose parts as properties on the root (`Select.Label`, `Table.Cell`, and so on):
69
+
70
+ | Component | Parts |
71
+ | ------------- | --------------------------------------------------------------------------------------------------------------------------- |
72
+ | `AlertDialog` | `Root`, `Icon`, `Content`, `Kicker`, `Title`, `Description`, `Actions` |
73
+ | `Combobox` | `Root`, `Label`, `Control`, `Input`, `Trigger`, `Portal`, `Positioner`, `Content`, `List`, `Empty`, `Item` |
74
+ | `Select` | `Root`, `Label`, `Control`, `Trigger`, `ValueText`, `Indicator`, `Portal`, `Positioner`, `Content`, `List`, `Empty`, `Item` |
75
+ | `Table` | `Root`, `Wrap`, `Caption`, `Header`, `Body`, `Footer`, `Row`, `ColumnHeader`, `RowHeader`, `Cell` |
76
+
77
+ The CSS package ships more components than this adapter currently covers. Breadcrumb, card, dialog, disclosure, empty state, field, keyboard shortcut, menu, pagination, progress, range, segmented control, status, tabs, and typography are available as styles with selector-level APIs.
78
+
79
+ ## Select
80
+
81
+ `id`, `label`, `options`, and `onValueChange` are required. `onValueChange` receives the selected option's value, not its label.
82
+
83
+ ```tsx
84
+ import { createSignal } from "solid-js";
85
+ import { Select } from "@simple-base/solid";
86
+
87
+ const timezones = [
88
+ { label: "Central European Time (UTC+01:00)", value: "cet" },
89
+ { label: "Coordinated Universal Time", value: "utc" },
90
+ { label: "Japan Standard Time", value: "jst", disabled: true },
91
+ ];
92
+
93
+ export function TimezonePicker() {
94
+ const [timezone, setTimezone] = createSignal("");
95
+
96
+ return (
97
+ <Select
98
+ id="timezone"
99
+ label="Timezone"
100
+ placeholder="Select a timezone"
101
+ options={timezones}
102
+ onValueChange={setTimezone}
103
+ >
104
+ <Select.Label />
105
+ <Select.Control>
106
+ <Select.Trigger>
107
+ <Select.ValueText />
108
+ <Select.Indicator>
109
+ <svg
110
+ aria-hidden="true"
111
+ viewBox="0 0 24 24"
112
+ fill="none"
113
+ stroke="currentColor"
114
+ stroke-width="2"
115
+ >
116
+ <path d="m6 9 6 6 6-6" />
117
+ </svg>
118
+ </Select.Indicator>
119
+ </Select.Trigger>
120
+ </Select.Control>
121
+ <Select.Portal>
122
+ <Select.Positioner>
123
+ <Select.Content>
124
+ <Select.List>{(option) => <Select.Item option={option} />}</Select.List>
125
+ </Select.Content>
126
+ </Select.Positioner>
127
+ </Select.Portal>
128
+ </Select>
129
+ );
130
+ }
131
+ ```
132
+
133
+ Additional root props: `value` makes selection controlled (`""` means cleared), `name` adds a hidden native select so the value submits with the form, `disabled`, `invalid`, and `required` drive state styling and labeling, `placement` picks the popup side, and `onOpenChange` reports visibility.
134
+
135
+ `Select.Empty` renders beside `Select.List` and appears only while the popup is open with no options. `Select.Portal` accepts `mount` — pass a dialog element's node to keep the popup interactive inside a native modal.
136
+
137
+ ## Combobox
138
+
139
+ Same root props as `Select`, with a text input that filters options by label.
140
+
141
+ ```tsx
142
+ <Combobox
143
+ id="country"
144
+ label="Country"
145
+ placeholder="Search countries"
146
+ options={countries}
147
+ onValueChange={setCountry}
148
+ >
149
+ <Combobox.Label />
150
+ <Combobox.Control>
151
+ <Combobox.Input />
152
+ <Combobox.Trigger>
153
+ <svg
154
+ aria-hidden="true"
155
+ viewBox="0 0 24 24"
156
+ fill="none"
157
+ stroke="currentColor"
158
+ stroke-width="2"
159
+ >
160
+ <path d="m6 9 6 6 6-6" />
161
+ </svg>
162
+ </Combobox.Trigger>
163
+ </Combobox.Control>
164
+ <Combobox.Portal>
165
+ <Combobox.Positioner>
166
+ <Combobox.Content>
167
+ <Combobox.List>{(option) => <Combobox.Item option={option} />}</Combobox.List>
168
+ <Combobox.Empty>No countries found. Try another search.</Combobox.Empty>
169
+ </Combobox.Content>
170
+ </Combobox.Positioner>
171
+ </Combobox.Portal>
172
+ </Combobox>
173
+ ```
174
+
175
+ ## Table
176
+
177
+ `ColumnHeader` defaults `scope` to `col` and `RowHeader` to `row`. `Cell` accepts `variant`: `code` or `number`.
178
+
179
+ ```tsx
180
+ import { Table } from "@simple-base/solid";
181
+
182
+ <Table.Wrap>
183
+ <Table>
184
+ <Table.Caption>Recent invoices</Table.Caption>
185
+ <Table.Header>
186
+ <Table.Row>
187
+ <Table.ColumnHeader>Invoice</Table.ColumnHeader>
188
+ <Table.ColumnHeader>Status</Table.ColumnHeader>
189
+ <Table.ColumnHeader>Amount</Table.ColumnHeader>
190
+ </Table.Row>
191
+ </Table.Header>
192
+ <Table.Body>
193
+ <Table.Row>
194
+ <Table.RowHeader>INV-001</Table.RowHeader>
195
+ <Table.Cell>Paid</Table.Cell>
196
+ <Table.Cell variant="number">$250.00</Table.Cell>
197
+ </Table.Row>
198
+ </Table.Body>
199
+ </Table>
200
+ </Table.Wrap>;
201
+ ```
202
+
203
+ `Table.Wrap` provides the horizontal scroll container the table styles expect.
204
+
205
+ ## AlertDialog
206
+
207
+ Renders a native `<dialog>` with `role="alertdialog"`, wiring `aria-labelledby` and `aria-describedby` to the title and description automatically.
208
+
209
+ ```tsx
210
+ import { AlertDialog, Button } from "@simple-base/solid";
211
+
212
+ <AlertDialog open>
213
+ <AlertDialog.Content>
214
+ <AlertDialog.Title>Delete project?</AlertDialog.Title>
215
+ <AlertDialog.Description>This action cannot be undone.</AlertDialog.Description>
216
+ </AlertDialog.Content>
217
+ <AlertDialog.Actions>
218
+ <Button variant="ghost">Cancel</Button>
219
+ <Button variant="danger">Delete</Button>
220
+ </AlertDialog.Actions>
221
+ </AlertDialog>;
222
+ ```
223
+
224
+ ## Props conventions
225
+
226
+ - `class` is reactive and merged with the component's own classes; it never replaces them.
227
+ - Native attributes pass through, except the ones the component owns (such as `id`, `role`, and `aria-*` that describe the widget's own structure).
228
+ - Event handlers compose: your `onClick` runs alongside the component's internal handling, not instead of it.
229
+ - Shared option names and defaults come from [@simple-base/contracts](https://www.npmjs.com/package/@simple-base/contracts), and the unmodified option types are re-exported from this package.
230
+
231
+ ## Themes
232
+
233
+ Themes come from the token layer. Set `data-theme` on the root or any nested region:
234
+
235
+ ```html
236
+ <html data-theme="nord"></html>
237
+ ```
238
+
239
+ ## Links
240
+
241
+ - [Repository](https://github.com/redasalmi/simple-base)
242
+ - [Styles and selector API](https://www.npmjs.com/package/@simple-base/css)
243
+ - [Design tokens](https://www.npmjs.com/package/@simple-base/tokens)
244
+
245
+ ## License
246
+
247
+ [MIT](https://github.com/redasalmi/simple-base/blob/main/LICENSE)
package/package.json CHANGED
@@ -1,7 +1,12 @@
1
1
  {
2
2
  "name": "@simple-base/solid",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "license": "MIT",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/redasalmi/simple-base.git",
8
+ "directory": "packages/solid"
9
+ },
5
10
  "files": [
6
11
  "dist"
7
12
  ],
@@ -21,7 +26,7 @@
21
26
  "registry": "https://registry.npmjs.org/"
22
27
  },
23
28
  "dependencies": {
24
- "@simple-base/contracts": "0.1.0",
29
+ "@simple-base/contracts": "0.1.1",
25
30
  "@zag-js/combobox": "^1.43.3",
26
31
  "@zag-js/select": "^1.43.3",
27
32
  "@zag-js/solid": "^1.43.3",