@ibis-design/svelte 0.7.0 → 0.7.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.
Files changed (2) hide show
  1. package/README.md +355 -77
  2. package/package.json +49 -49
package/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # @ibis-design/svelte
2
2
 
3
- Svelte 5 component library for the IBIS design system. Provides primitives (Button, Card) and full layout shells (AuthLayout, AppLayout, DashboardLayout) styled via CSS custom properties from `@ibis-design/css`.
3
+ Svelte 5 component library for the IBIS design system—buttons, inputs, feedback, and app shellsstyled with tokens from [@ibis-design/css](https://www.npmjs.com/package/@ibis-design/css).
4
4
 
5
5
  ## Requirements
6
6
 
7
- - **Svelte 5** (runes and snippets; no slots).
8
- - **@ibis-design/css** design tokens. Load the stylesheet once and set `data-theme` on `<html>` (`ib-light`, `ib-dark`, `alc-light`, `alc-dark`).
7
+ - **Svelte 5** (runes, snippets; not compatible with Svelte 4 slots API)
8
+ - **@ibis-design/css** (peer dependency for tokens and component styles)
9
9
 
10
10
  ## Installation
11
11
 
@@ -13,91 +13,365 @@ Svelte 5 component library for the IBIS design system. Provides primitives (Butt
13
13
  npm install @ibis-design/svelte @ibis-design/css
14
14
  ```
15
15
 
16
- ## Token CSS
16
+ ## App setup
17
17
 
18
- Import tokens and set the theme on the document root:
18
+ Load tokens once at the root of your app and set the theme on `<html>`.
19
19
 
20
20
  ```svelte
21
- <script>
21
+ <!-- src/routes/+layout.svelte (SvelteKit) or App.svelte -->
22
+ <script lang="ts">
22
23
  import '@ibis-design/css';
24
+ import { onMount } from 'svelte';
23
25
 
24
- if (typeof document !== 'undefined') {
25
- document.documentElement.dataset.theme = 'ib-light'; // or alc-dark, etc.
26
- }
26
+ onMount(() => {
27
+ document.documentElement.dataset.theme = 'ib-light';
28
+ });
27
29
  </script>
28
- ```
29
30
 
30
- Without the CSS import and `data-theme`, components will not resolve design-system variables.
31
+ <slot />
32
+ ```
31
33
 
32
- ### Canonical variable names
34
+ ```svelte
35
+ <script lang="ts">
36
+ import { Button, TextInput, Banner } from '@ibis-design/svelte';
37
+ </script>
33
38
 
34
- Use semantic tokens from the active theme, for example:
39
+ <Button variant="primary" size="md">Continue</Button>
40
+ ```
35
41
 
36
- - `--font-size-body-sm` (not legacy `normal-text` names)
37
- - `--color-brand-secondary` for secondary actions
38
- - `--shadow-focus-default` for focus rings
39
- - `--border-radius-md`, `--border-color-button`
42
+ | `data-theme` | Brand | Mode |
43
+ |--------------|-------|------|
44
+ | `ib-light` | Ibis | Light |
45
+ | `ib-dark` | Ibis | Dark |
46
+ | `alc-light` | Alchemy | Light |
47
+ | `alc-dark` | Alchemy | Dark |
40
48
 
41
- ### Shared component CSS
49
+ Switch at runtime: `document.documentElement.dataset.theme = 'alc-dark'`.
42
50
 
43
- All component styles live in `@ibis-design/css` (`packages/css/src/styles/components/`). Each Svelte component imports its stylesheet from the CSS package, for example in `Button.svelte`:
51
+ ---
44
52
 
45
- ```ts
46
- import '@ibis-design/css/components/button.css';
47
- ```
53
+ ## Components
48
54
 
49
- Consumers get styles automatically when they import the component; no separate CSS import is required unless you use the classes outside these components.
55
+ All components use **snippets** for labels and rich content (Svelte 5). Put text between tags or pass a `label` prop when available.
50
56
 
51
- ## Usage
57
+ ### Button
52
58
 
53
- ### Primitives
59
+ Primary actions, form submit, and secondary cancel flows.
54
60
 
55
- **Button** use the `children` snippet for the label:
61
+ | Prop | Type | Default | Description |
62
+ |------|------|---------|-------------|
63
+ | `variant` | `'primary' \| 'secondary'` | `'primary'` | Visual style |
64
+ | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Padding and type size |
65
+ | `type` | `'button' \| 'submit' \| 'reset'` | `'button'` | Native button type |
66
+ | `disabled` | `boolean` | `false` | Disables interaction |
67
+ | `loading` | `boolean` | `false` | Spinner + disabled |
68
+ | `skeleton` | `boolean` | `false` | Placeholder shimmer |
69
+ | `iconOnly` | `boolean` | `false` | Square icon button |
70
+ | `label` | `string` | — | Text if no children snippet |
56
71
 
57
72
  ```svelte
58
73
  <script>
59
74
  import { Button } from '@ibis-design/svelte';
60
75
  </script>
61
76
 
62
- <Button variant="primary" size="md">Submit</Button>
77
+ <Button variant="primary" size="md">Submit payment</Button>
63
78
  <Button variant="secondary" size="sm">Cancel</Button>
79
+ <Button type="submit" loading={isSaving}>Saving…</Button>
80
+ <Button iconOnly aria-label="Search">🔍</Button>
64
81
  ```
65
82
 
66
- **Card** — use the `children` snippet for content:
83
+ ---
84
+
85
+ ### TextInput
86
+
87
+ Labeled text fields with help, error, prefix/suffix, and prepend blocks.
88
+
89
+ | Prop | Type | Default | Description |
90
+ |------|------|---------|-------------|
91
+ | `label` | `string` | — | Field label |
92
+ | `inputSize` | `'sm' \| 'md' \| 'lg'` | `'md'` | Size scale |
93
+ | `invalid` | `boolean` | `false` | Error styling |
94
+ | `error` | `string` | — | Shown when `invalid` |
95
+ | `description` | `string` | — | Below label |
96
+ | `helpText` | `string` | — | Below field |
97
+ | `loading` | `boolean` | `false` | Loading state |
98
+ | `prefixSnippet` / `suffixSnippet` | `Snippet` | — | Icons inside field |
99
+ | `prependSnippet` | `Snippet` | — | Block before field |
100
+ | `bind:value` | `string` | — | Input value |
67
101
 
68
102
  ```svelte
69
103
  <script>
70
- import { Card } from '@ibis-design/svelte';
104
+ import { TextInput } from '@ibis-design/svelte';
105
+
106
+ let email = $state('');
107
+ let emailError = $state('');
71
108
  </script>
72
109
 
73
- <Card>
74
- <p>Card content</p>
75
- </Card>
110
+ <TextInput
111
+ label="Email"
112
+ type="email"
113
+ placeholder="you@example.com"
114
+ description="Used for receipts."
115
+ helpText="We never share your email."
116
+ bind:value={email}
117
+ />
118
+
119
+ <TextInput
120
+ label="Amount"
121
+ invalid={!!emailError}
122
+ error={emailError}
123
+ bind:value={email}
124
+ />
76
125
  ```
77
126
 
78
- ### Layouts
127
+ ---
79
128
 
80
- Layouts use **snippets** (Svelte 5). Pass snippet props for header, sidebar, and main content. Content between the component tags is the `children` snippet.
129
+ ### TextArea
81
130
 
82
- **AppLayout** generic app shell with optional header, sidebar, main, and footer:
131
+ Multi-line input; same sizing and validation props as `TextInput` (`inputSize`, `invalid`, `error`, `loading`, `rows`).
83
132
 
84
133
  ```svelte
85
134
  <script>
86
- import { AppLayout } from '@ibis-design/svelte';
135
+ import { TextArea } from '@ibis-design/svelte';
136
+ let notes = $state('');
137
+ </script>
138
+
139
+ <TextArea label="Notes" rows={4} placeholder="Optional details…" bind:value={notes} />
140
+ ```
141
+
142
+ ---
87
143
 
88
- // Define snippets and pass as props; content between tags is children
144
+ ### Checkbox
145
+
146
+ | Prop | Type | Default | Description |
147
+ |------|------|---------|-------------|
148
+ | `label` | `string` | — | Label text |
149
+ | `bind:checked` | `boolean` | `false` | Checked state |
150
+ | `inputSize` | `'sm' \| 'md' \| 'lg'` | `'md'` | Control size |
151
+ | `disabled` | `boolean` | `false` | |
152
+ | `invalid` | `boolean` | `false` | |
153
+ | `description` / `helpText` / `error` | `string` | — | Helper copy |
154
+ | `checkboxSnippet` | `Snippet` | — | Custom check icon |
155
+
156
+ ```svelte
157
+ <script>
158
+ import { Checkbox } from '@ibis-design/svelte';
159
+ let accepted = $state(false);
89
160
  </script>
90
161
 
91
- <AppLayout
92
- header={headerSnippet}
93
- sidebar={sidebarSnippet}
94
- footer={footerSnippet}
95
- >
96
- <p>Main page content</p>
97
- </AppLayout>
162
+ <Checkbox
163
+ label="I accept the terms"
164
+ description="Required to open an account."
165
+ bind:checked={accepted}
166
+ />
98
167
  ```
99
168
 
100
- With inline snippets:
169
+ ---
170
+
171
+ ### Radio
172
+
173
+ | Prop | Type | Default | Description |
174
+ |------|------|---------|-------------|
175
+ | `label` | `string` | — | Option label |
176
+ | `value` | `string \| number` | **required** | Option value |
177
+ | `group` | `string \| number` | — | Selected value (`bind:group`) |
178
+ | `name` | `string` | — | Radio group name |
179
+ | `inputSize` | `'sm' \| 'md' \| 'lg'` | `'md'` | |
180
+ | `disabled` / `invalid` | `boolean` | | |
181
+
182
+ ```svelte
183
+ <script>
184
+ import { Radio } from '@ibis-design/svelte';
185
+ let accountType = $state('personal');
186
+ </script>
187
+
188
+ <Radio name="account" label="Personal" value="personal" bind:group={accountType} />
189
+ <Radio name="account" label="Business" value="business" bind:group={accountType} />
190
+ ```
191
+
192
+ ---
193
+
194
+ ### Switch
195
+
196
+ Toggle for settings; uses `bind:checked`.
197
+
198
+ ```svelte
199
+ <script>
200
+ import { Switch } from '@ibis-design/svelte';
201
+ let enabled = $state(true);
202
+ </script>
203
+
204
+ <Switch label="Notifications" bind:checked={enabled} />
205
+ ```
206
+
207
+ ---
208
+
209
+ ### Dropdown
210
+
211
+ Select-style control with `options: { label, value }[]` and `bind:value`.
212
+
213
+ ```svelte
214
+ <script>
215
+ import { Dropdown } from '@ibis-design/svelte';
216
+
217
+ let currency = $state('usd');
218
+ const options = [
219
+ { label: 'US Dollar', value: 'usd' },
220
+ { label: 'Euro', value: 'eur' },
221
+ ];
222
+ </script>
223
+
224
+ <Dropdown label="Currency" {options} bind:value={currency} placeholder="Choose currency" />
225
+ ```
226
+
227
+ ---
228
+
229
+ ### DropdownButton
230
+
231
+ Menu anchored to a button; pass `menu` snippet with a `close` callback.
232
+
233
+ ```svelte
234
+ <script>
235
+ import { DropdownButton } from '@ibis-design/svelte';
236
+ </script>
237
+
238
+ <DropdownButton label="Account">
239
+ {#snippet menu(close)}
240
+ <button type="button" class="ibis-dropdown-menu__item" onclick={close}>Profile</button>
241
+ <button type="button" class="ibis-dropdown-menu__item" onclick={close}>Sign out</button>
242
+ {/snippet}
243
+ </DropdownButton>
244
+ ```
245
+
246
+ ---
247
+
248
+ ### Chips
249
+
250
+ Filter or toggle chips; supports `bind:selected`, `loading`, `skeleton`, and icon snippets.
251
+
252
+ ```svelte
253
+ <script>
254
+ import { Chips } from '@ibis-design/svelte';
255
+ let active = $state(false);
256
+ </script>
257
+
258
+ <Chips label="Pending" bind:selected={active} />
259
+ <Chips label="With icon" iconText="★" size="sm" />
260
+ ```
261
+
262
+ ---
263
+
264
+ ### PillTab & PillTabs
265
+
266
+ Segmented control built on radio inputs. Wrap tabs in `PillTabs`; share `name` and `bind:group`.
267
+
268
+ ```svelte
269
+ <script>
270
+ import { PillTabs, PillTab } from '@ibis-design/svelte';
271
+ let tab = $state('overview');
272
+ </script>
273
+
274
+ <PillTabs>
275
+ <PillTab name="main" label="Overview" value="overview" bind:group={tab} />
276
+ <PillTab name="main" label="Activity" value="activity" bind:group={tab} />
277
+ <PillTab name="main" label="Settings" value="settings" bind:group={tab} />
278
+ </PillTabs>
279
+ ```
280
+
281
+ ---
282
+
283
+ ### TextLink
284
+
285
+ Styled anchor with underline modes and optional icons.
286
+
287
+ | Prop | Type | Default |
288
+ |------|------|---------|
289
+ | `href` | `string` | — |
290
+ | `underline` | `'always' \| 'hover' \| 'none'` | `'hover'` |
291
+ | `linkSize` | `'sm' \| 'md' \| 'lg'` | `'md'` |
292
+ | `disabled` / `loading` / `skeleton` | `boolean` | |
293
+
294
+ ```svelte
295
+ <script>
296
+ import { TextLink } from '@ibis-design/svelte';
297
+ </script>
298
+
299
+ <TextLink href="/help" underline="hover">Need help?</TextLink>
300
+ ```
301
+
302
+ ---
303
+
304
+ ### Banner
305
+
306
+ Inline page-level message. Types: `success`, `error`, `default`. Optional `closable`, `loading`, `icon` snippet.
307
+
308
+ ```svelte
309
+ <script>
310
+ import { Banner } from '@ibis-design/svelte';
311
+ </script>
312
+
313
+ <Banner type="success" title="Transfer complete" message="Funds will arrive in 1–2 days." closable />
314
+ <Banner type="error" title="Payment failed">
315
+ {#snippet children()}
316
+ Check your card details and try again.
317
+ {/snippet}
318
+ </Banner>
319
+ ```
320
+
321
+ ---
322
+
323
+ ### Toaster
324
+
325
+ Compact toast-style message. Types: `success`, `error`, `accent`, `default`.
326
+
327
+ ```svelte
328
+ <script>
329
+ import { Toaster } from '@ibis-design/svelte';
330
+ </script>
331
+
332
+ <Toaster type="accent" title="Session expiring" message="Sign in again to continue." closable />
333
+ ```
334
+
335
+ ---
336
+
337
+ ### TipIndicator
338
+
339
+ Hover/focus tooltip on an indicator. **Requires** `text` prop.
340
+
341
+ ```svelte
342
+ <script>
343
+ import { TipIndicator } from '@ibis-design/svelte';
344
+ </script>
345
+
346
+ <TipIndicator text="International transfers may include fees." position="top" width="240" />
347
+ ```
348
+
349
+ ---
350
+
351
+ ### Card
352
+
353
+ Simple surfaced container (styles ship with the component).
354
+
355
+ ```svelte
356
+ <script>
357
+ import { Card } from '@ibis-design/svelte';
358
+ </script>
359
+
360
+ <Card>
361
+ <h2>Account summary</h2>
362
+ <p>Balance and recent activity.</p>
363
+ </Card>
364
+ ```
365
+
366
+ ---
367
+
368
+ ## Layouts
369
+
370
+ Layouts use **snippet props** for regions. Content between the layout tags is the main `children` area.
371
+
372
+ ### AppLayout
373
+
374
+ Optional `header`, `sidebar`, `footer` snippets.
101
375
 
102
376
  ```svelte
103
377
  <script>
@@ -105,64 +379,68 @@ With inline snippets:
105
379
  </script>
106
380
 
107
381
  {#snippet header()}
108
- <nav>App header</nav>
382
+ <nav>My app</nav>
109
383
  {/snippet}
384
+
110
385
  {#snippet sidebar()}
111
- <aside>Sidebar</aside>
386
+ <aside>Navigation</aside>
112
387
  {/snippet}
113
388
 
114
- <AppLayout header={header} sidebar={sidebar}>
115
- <p>Main content</p>
389
+ <AppLayout {header} {sidebar}>
390
+ <h1>Dashboard</h1>
391
+ <p>Main content.</p>
116
392
  </AppLayout>
117
393
  ```
118
394
 
119
- **AuthLayout** — centered single-column layout for login/signup:
395
+ ### AuthLayout
396
+
397
+ Centered column for sign-in / sign-up.
120
398
 
121
399
  ```svelte
122
400
  <script>
123
401
  import { AuthLayout } from '@ibis-design/svelte';
124
402
  </script>
125
403
 
126
- <AuthLayout logo={logoSnippet} footer={footerSnippet}>
127
- <form>Login form</form>
404
+ <AuthLayout>
405
+ <form>
406
+ <h1>Sign in</h1>
407
+ <!-- fields -->
408
+ </form>
128
409
  </AuthLayout>
129
410
  ```
130
411
 
131
- **DashboardLayout** — dashboard shell with themed header and sidebar (same snippet props as AppLayout).
132
-
133
- ## Exports
412
+ ### DashboardLayout
134
413
 
135
- - **Components:** `Button`, `Card`, `AuthLayout`, `AppLayout`, `DashboardLayout`
136
- - **Types:** `ButtonVariant`, `ButtonSize`, `AuthLayoutProps`, `AppLayoutProps`, `DashboardLayoutProps` (from `@ibis-design/svelte`)
414
+ Dashboard shell with themed header and sidebar (same snippet API as `AppLayout`).
137
415
 
138
- ## Build
139
-
140
- This package is built with **`@sveltejs/package`** (`svelte-package`), the supported Svelte library pipeline. It preprocesses Svelte, transpiles TypeScript, and emits **`.d.ts` next to outputs** so consumers get correct component prop types (not a separate Vite “library mode” + `vite-plugin-dts` flow).
416
+ ```svelte
417
+ <script>
418
+ import { DashboardLayout } from '@ibis-design/svelte';
419
+ </script>
141
420
 
142
- From the package directory:
421
+ {#snippet header()}
422
+ <header>Dashboard</header>
423
+ {/snippet}
143
424
 
144
- ```bash
145
- npm run build
425
+ <DashboardLayout {header}>
426
+ <p>Widgets and charts.</p>
427
+ </DashboardLayout>
146
428
  ```
147
429
 
148
- This runs `svelte-kit sync` (generates `.svelte-kit` types for the minimal Kit shell) then `svelte-package`, writing output to `dist/`.
430
+ ---
149
431
 
150
- Watch mode during development:
432
+ ## Vanilla HTML / other frameworks
151
433
 
152
- ```bash
153
- npm run dev
154
- ```
434
+ Component **classes** and tokens live in `@ibis-design/css`. Use this package when you want ready-made Svelte 5 components; use the CSS package directly for React, Vue, or plain HTML. See the [@ibis-design/css README](https://www.npmjs.com/package/@ibis-design/css) for `.ibis-*` markup examples.
155
435
 
156
- From the monorepo root:
436
+ ---
157
437
 
158
- ```bash
159
- npm run build -w @ibis-design/svelte
160
- ```
438
+ ## Exports
161
439
 
162
- ## Type checking
440
+ **Components:** `Button`, `DropdownButton`, `PillTab`, `PillTabs`, `TextInput`, `TextArea`, `Checkbox`, `Radio`, `Switch`, `Dropdown`, `Chips`, `TextLink`, `Banner`, `Toaster`, `TipIndicator`, `Card`, `Tooltip`, `AuthLayout`, `AppLayout`, `DashboardLayout`
163
441
 
164
- ```bash
165
- npm run check
166
- ```
442
+ **Types:** `ButtonVariant`, `ButtonSize`, `AuthLayoutProps`, `AppLayoutProps`, `DashboardLayoutProps`
167
443
 
168
- Runs `svelte-kit sync` then `svelte-check` with the package `tsconfig.json`.
444
+ ```ts
445
+ import { Button, type ButtonVariant } from '@ibis-design/svelte';
446
+ ```
package/package.json CHANGED
@@ -1,49 +1,49 @@
1
- {
2
- "name": "@ibis-design/svelte",
3
- "version": "0.7.0",
4
- "description": "Svelte component library for the IBIS design system.",
5
- "type": "module",
6
- "main": "./dist/index.js",
7
- "module": "./dist/index.js",
8
- "types": "./dist/index.d.ts",
9
- "svelte": "./dist/index.js",
10
- "exports": {
11
- ".": {
12
- "types": "./dist/index.d.ts",
13
- "svelte": "./dist/index.js",
14
- "import": "./dist/index.js",
15
- "default": "./dist/index.js"
16
- }
17
- },
18
- "files": [
19
- "dist"
20
- ],
21
- "sideEffects": [
22
- "**/*.css"
23
- ],
24
- "peerDependencies": {
25
- "@ibis-design/css": "^0.7.0",
26
- "svelte": "^5.54.0"
27
- },
28
- "devDependencies": {
29
- "@ibis-design/css": "0.7.0",
30
- "@sveltejs/adapter-auto": "7.0.1",
31
- "@sveltejs/kit": "2.60.1",
32
- "@sveltejs/package": "2.5.7",
33
- "@sveltejs/vite-plugin-svelte": "^7.1.2",
34
- "@types/node": "25.9.0",
35
- "svelte": "5.55.8",
36
- "svelte-check": "^4.4.8",
37
- "typescript": "^5.9.3",
38
- "vite": "^8.0.13"
39
- },
40
- "scripts": {
41
- "build": "svelte-kit sync && svelte-package",
42
- "prepublishOnly": "npm run build",
43
- "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
44
- "dev": "svelte-package -w"
45
- },
46
- "dependencies": {
47
- "@solar-icons/svelte": "^1.1.1"
48
- }
49
- }
1
+ {
2
+ "name": "@ibis-design/svelte",
3
+ "version": "0.7.2",
4
+ "description": "Svelte component library for the IBIS design system.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "svelte": "./dist/index.js",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "svelte": "./dist/index.js",
14
+ "import": "./dist/index.js",
15
+ "default": "./dist/index.js"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "sideEffects": [
22
+ "**/*.css"
23
+ ],
24
+ "peerDependencies": {
25
+ "@ibis-design/css": "^0.7.2",
26
+ "svelte": "^5.54.0"
27
+ },
28
+ "devDependencies": {
29
+ "@ibis-design/css": "0.7.2",
30
+ "@sveltejs/adapter-auto": "7.0.1",
31
+ "@sveltejs/kit": "2.60.1",
32
+ "@sveltejs/package": "2.5.7",
33
+ "@sveltejs/vite-plugin-svelte": "^7.1.2",
34
+ "@types/node": "25.9.1",
35
+ "svelte": "5.55.9",
36
+ "svelte-check": "^4.4.8",
37
+ "typescript": "^5.9.3",
38
+ "vite": "^8.0.13"
39
+ },
40
+ "scripts": {
41
+ "build": "svelte-kit sync && svelte-package",
42
+ "prepublishOnly": "npm run build",
43
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
44
+ "dev": "svelte-package -w"
45
+ },
46
+ "dependencies": {
47
+ "@solar-icons/svelte": "^1.1.1"
48
+ }
49
+ }