ionbase-ui 0.18.1 → 0.20.0

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "package": "ionbase-ui",
3
- "version": "0.18.1",
3
+ "version": "0.20.0",
4
4
  "usage": "Pick a component here, then read dist/meta/<Name>.json for its full contract.",
5
5
  "hooks": [
6
6
  "useToast"
@@ -31,7 +31,8 @@
31
31
  "hasIntent": true
32
32
  },
33
33
  "Avatar": {
34
- "summary": "Avatar picks its content the way Figma's `Type` variant does, but by",
34
+ "summary": "A person or entity marker. Content is chosen by precedence — image, then initials, then icon — not by a type prop.",
35
+ "status": "stable",
35
36
  "variants": {
36
37
  "size": [
37
38
  "mini",
@@ -45,10 +46,11 @@
45
46
  ]
46
47
  },
47
48
  "detail": "dist/meta/Avatar.json",
48
- "hasIntent": false
49
+ "hasIntent": true
49
50
  },
50
51
  "AvatarGroup": {
51
- "summary": "AvatarGroup overlaps its children by a quarter of the avatar size, matching",
52
+ "summary": "Overlapping Avatars with a `+N` overflow, for showing several people in one row's width.",
53
+ "status": "stable",
52
54
  "variants": {
53
55
  "size": [
54
56
  "mini",
@@ -62,10 +64,11 @@
62
64
  ]
63
65
  },
64
66
  "detail": "dist/meta/AvatarGroup.json",
65
- "hasIntent": false
67
+ "hasIntent": true
66
68
  },
67
69
  "Badge": {
68
- "summary": "Badge is presentational — no role, no interaction. React Aria has nothing to",
70
+ "summary": "A small, non-interactive label that classifies the thing next to it. Presentational — no role, no live region.",
71
+ "status": "stable",
69
72
  "variants": {
70
73
  "intent": [
71
74
  "neutral",
@@ -77,7 +80,7 @@
77
80
  ]
78
81
  },
79
82
  "detail": "dist/meta/Badge.json",
80
- "hasIntent": false
83
+ "hasIntent": true
81
84
  },
82
85
  "Button": {
83
86
  "summary": "Triggers an action in place. Never navigates.",
@@ -103,7 +106,8 @@
103
106
  "hasIntent": true
104
107
  },
105
108
  "Checkbox": {
106
- "summary": "Checkbox wraps a native `<input type=\"checkbox\">` and hides it.",
109
+ "summary": "A native checkbox with the system's styling, supporting an indeterminate state.",
110
+ "status": "stable",
107
111
  "variants": {
108
112
  "size": [
109
113
  "sm",
@@ -117,10 +121,11 @@
117
121
  ]
118
122
  },
119
123
  "detail": "dist/meta/Checkbox.json",
120
- "hasIntent": false
124
+ "hasIntent": true
121
125
  },
122
126
  "Divider": {
123
- "summary": "A single `<hr>`, matching Figma's `Border` (70:22153).",
127
+ "summary": "A semantic thematic break, rendered as a real <hr>.",
128
+ "status": "stable",
124
129
  "variants": {
125
130
  "orientation": [
126
131
  "horizontal",
@@ -128,10 +133,11 @@
128
133
  ]
129
134
  },
130
135
  "detail": "dist/meta/Divider.json",
131
- "hasIntent": false
136
+ "hasIntent": true
132
137
  },
133
138
  "FullCard": {
134
- "summary": "Full Card — the full-bleed case study row from Figma `Full Card` (592:857).",
139
+ "summary": "A full-bleed row: a text column beside a framed media panel, mirrored by `alignment`.",
140
+ "status": "stable",
135
141
  "variants": {
136
142
  "alignment": [
137
143
  "right",
@@ -139,19 +145,21 @@
139
145
  ]
140
146
  },
141
147
  "detail": "dist/meta/FullCard.json",
142
- "hasIntent": false
148
+ "hasIntent": true
143
149
  },
144
150
  "Header": {
145
- "summary": "Header renders Figma's four Device variants — Desktop, Tablet,",
151
+ "summary": "The page header bar. Renders Figma's Desktop, Tablet, Mobile-Closed and Mobile-Open from one DOM tree.",
152
+ "status": "stable",
146
153
  "variants": {},
147
154
  "detail": "dist/meta/Header.json",
148
- "hasIntent": false
155
+ "hasIntent": true
149
156
  },
150
157
  "Icon": {
151
- "summary": "Wrapper that applies the design system's icon sizing and accessibility",
158
+ "summary": "Applies the system's icon sizing and accessibility defaults to any SVG component you hand it. The package ships no icon set.",
159
+ "status": "stable",
152
160
  "variants": {},
153
161
  "detail": "dist/meta/Icon.json",
154
- "hasIntent": false
162
+ "hasIntent": true
155
163
  },
156
164
  "Input": {
157
165
  "summary": "A single-line text field, together with its label, helper text and error message.",
@@ -175,7 +183,8 @@
175
183
  "hasIntent": true
176
184
  },
177
185
  "Link": {
178
- "summary": "Link — Figma `Link` (774:1516).",
186
+ "summary": "Navigation to somewhere else. Renders an <a> when given `href`, a <button> otherwise.",
187
+ "status": "stable",
179
188
  "variants": {
180
189
  "variant": [
181
190
  "inline",
@@ -183,10 +192,11 @@
183
192
  ]
184
193
  },
185
194
  "detail": "dist/meta/Link.json",
186
- "hasIntent": false
195
+ "hasIntent": true
187
196
  },
188
197
  "Logo": {
189
- "summary": "The full lockup: mark + wordmark, matching Figma's `Logo-Ionbase`",
198
+ "summary": "The full IonBase lockup — mark plus wordmark.",
199
+ "status": "stable",
190
200
  "variants": {
191
201
  "size": [
192
202
  "sm",
@@ -198,10 +208,11 @@
198
208
  ]
199
209
  },
200
210
  "detail": "dist/meta/Logo.json",
201
- "hasIntent": false
211
+ "hasIntent": true
202
212
  },
203
213
  "LogoMark": {
204
- "summary": "The bare icon glyph, no wordmark — what `Header` actually uses.",
214
+ "summary": "The bare mark, no wordmark — what Header uses.",
215
+ "status": "stable",
205
216
  "variants": {
206
217
  "size": [
207
218
  "sm",
@@ -209,19 +220,21 @@
209
220
  ]
210
221
  },
211
222
  "detail": "dist/meta/LogoMark.json",
212
- "hasIntent": false
223
+ "hasIntent": true
213
224
  },
214
225
  "Menu": {
215
- "summary": "Menu is the list surface, not a popover.",
226
+ "summary": "The list surface only — no trigger, no anchor, no open state. Positioning it is the caller's job.",
227
+ "status": "stable",
216
228
  "variants": {},
217
229
  "detail": "dist/meta/Menu.json",
218
- "hasIntent": false
230
+ "hasIntent": true
219
231
  },
220
232
  "MenuItem": {
221
- "summary": null,
233
+ "summary": "One row in a Menu. A real <button> inside an <li>, with an optional leading icon and a trailing selected check.",
234
+ "status": "stable",
222
235
  "variants": {},
223
236
  "detail": "dist/meta/MenuItem.json",
224
- "hasIntent": false
237
+ "hasIntent": true
225
238
  },
226
239
  "Modal": {
227
240
  "summary": "A focus-trapping dialog. Renders nothing when closed and portals when open.",
@@ -242,13 +255,15 @@
242
255
  "hasIntent": true
243
256
  },
244
257
  "NavItem": {
245
- "summary": "Nav Item renders an `<a>` when given `href`, a `<button>` otherwise —",
258
+ "summary": "A primary navigation destination. Renders an <a> when given `href`, a <button> otherwise.",
259
+ "status": "stable",
246
260
  "variants": {},
247
261
  "detail": "dist/meta/NavItem.json",
248
- "hasIntent": false
262
+ "hasIntent": true
249
263
  },
250
264
  "PhoneInput": {
251
- "summary": "PhoneInput — Figma `Input/Phone` (80:372).",
265
+ "summary": "A dial-code block butted against an Input, sharing one outline. It does not pick countries.",
266
+ "status": "stable",
252
267
  "variants": {
253
268
  "autoCapitalize": [
254
269
  "none",
@@ -265,10 +280,11 @@
265
280
  ]
266
281
  },
267
282
  "detail": "dist/meta/PhoneInput.json",
268
- "hasIntent": false
283
+ "hasIntent": true
269
284
  },
270
285
  "Popover": {
271
- "summary": "Popover — Figma `Popover` (825:1853).",
286
+ "summary": "An anchored panel that holds interactive content. Sits between Tooltip and Modal.",
287
+ "status": "stable",
272
288
  "variants": {
273
289
  "placement": [
274
290
  "right",
@@ -283,10 +299,11 @@
283
299
  ]
284
300
  },
285
301
  "detail": "dist/meta/Popover.json",
286
- "hasIntent": false
302
+ "hasIntent": true
287
303
  },
288
304
  "Radio": {
289
- "summary": null,
305
+ "summary": "One option inside a RadioGroup. Meaningless on its own — the group owns the name and the selected value.",
306
+ "status": "stable",
290
307
  "variants": {
291
308
  "size": [
292
309
  "sm",
@@ -300,10 +317,11 @@
300
317
  ]
301
318
  },
302
319
  "detail": "dist/meta/Radio.json",
303
- "hasIntent": false
320
+ "hasIntent": true
304
321
  },
305
322
  "RadioGroup": {
306
- "summary": "Renders a `<fieldset>` with a `<legend>` rather than a div with",
323
+ "summary": "A <fieldset>/<legend> group of mutually exclusive options. Owns the shared name and the selected value.",
324
+ "status": "stable",
307
325
  "variants": {
308
326
  "size": [
309
327
  "sm",
@@ -317,13 +335,14 @@
317
335
  ]
318
336
  },
319
337
  "detail": "dist/meta/RadioGroup.json",
320
- "hasIntent": false
338
+ "hasIntent": true
321
339
  },
322
340
  "ScrollProgress": {
323
- "summary": "The compact rail is the disclosure trigger. It is a real `<button>`, so a",
341
+ "summary": "A compact progress rail that expands into a section list. A disclosure, not a menu — and it computes nothing itself.",
342
+ "status": "stable",
324
343
  "variants": {},
325
344
  "detail": "dist/meta/ScrollProgress.json",
326
- "hasIntent": false
345
+ "hasIntent": true
327
346
  },
328
347
  "Select": {
329
348
  "summary": "A dropdown over a native <select>, with the same label and error wiring as Input.",
@@ -339,10 +358,11 @@
339
358
  "hasIntent": true
340
359
  },
341
360
  "TabItem": {
342
- "summary": null,
361
+ "summary": "One tab and its panel. Re-exported from react-stately's collection Item — `title` is the tab label, children are the panel.",
362
+ "status": "stable",
343
363
  "variants": {},
344
364
  "detail": "dist/meta/TabItem.json",
345
- "hasIntent": false
365
+ "hasIntent": true
346
366
  },
347
367
  "Table": {
348
368
  "summary": "A data table. Table owns the scroll container and density; rows and cells are composed.",
@@ -358,13 +378,15 @@
358
378
  "hasIntent": true
359
379
  },
360
380
  "TableBody": {
361
- "summary": null,
381
+ "summary": "The <tbody> section. Takes no props — it places the data rows and gives their cells body context.",
382
+ "status": "stable",
362
383
  "variants": {},
363
384
  "detail": "dist/meta/TableBody.json",
364
- "hasIntent": false
385
+ "hasIntent": true
365
386
  },
366
387
  "TableCell": {
367
- "summary": "One component covers Figma's `Table Cell` + `Cell Text`: the two are never",
388
+ "summary": "One cell, covering Figma's Table Cell and Cell Text together. `header` decides <th> versus <td>.",
389
+ "status": "stable",
368
390
  "variants": {
369
391
  "scope": [
370
392
  "row",
@@ -383,22 +405,25 @@
383
405
  ]
384
406
  },
385
407
  "detail": "dist/meta/TableCell.json",
386
- "hasIntent": false
408
+ "hasIntent": true
387
409
  },
388
410
  "TableHead": {
389
- "summary": null,
411
+ "summary": "The <thead> section. Takes no props — it places the header row and gives its cells their head-or-body context.",
412
+ "status": "stable",
390
413
  "variants": {},
391
414
  "detail": "dist/meta/TableHead.json",
392
- "hasIntent": false
415
+ "hasIntent": true
393
416
  },
394
417
  "TableRow": {
395
- "summary": "A plain `<tr>`. Hover is CSS-only (`:hover` plus a `data-hovered` escape",
418
+ "summary": "A plain <tr>. Hover is CSS-only; a row is not itself interactive.",
419
+ "status": "stable",
396
420
  "variants": {},
397
421
  "detail": "dist/meta/TableRow.json",
398
- "hasIntent": false
422
+ "hasIntent": true
399
423
  },
400
424
  "Tabs": {
401
- "summary": null,
425
+ "summary": "A tab list and its panels, built on react-aria's tab collection. Children are TabItem.",
426
+ "status": "stable",
402
427
  "variants": {
403
428
  "type": [
404
429
  "pill",
@@ -415,10 +440,11 @@
415
440
  ]
416
441
  },
417
442
  "detail": "dist/meta/Tabs.json",
418
- "hasIntent": false
443
+ "hasIntent": true
419
444
  },
420
445
  "Toast": {
421
- "summary": "Toast — Figma `Toast` (820:1655).",
446
+ "summary": "A transient notification on neutral chrome. Intent is carried by the icon, not by a tinted panel.",
447
+ "status": "stable",
422
448
  "variants": {
423
449
  "intent": [
424
450
  "neutral",
@@ -430,10 +456,11 @@
430
456
  ]
431
457
  },
432
458
  "detail": "dist/meta/Toast.json",
433
- "hasIntent": false
459
+ "hasIntent": true
434
460
  },
435
461
  "ToastProvider": {
436
- "summary": "Renders the queue and supplies `useToast`.",
462
+ "summary": "Renders the toast queue and supplies the `useToast` hook. Mount once, near the app root.",
463
+ "status": "stable",
437
464
  "variants": {
438
465
  "placement": [
439
466
  "top-left",
@@ -443,10 +470,11 @@
443
470
  ]
444
471
  },
445
472
  "detail": "dist/meta/ToastProvider.json",
446
- "hasIntent": false
473
+ "hasIntent": true
447
474
  },
448
475
  "Toggle": {
449
- "summary": "Toggle is a checkbox with `role=\"switch\"`.",
476
+ "summary": "A switch — a checkbox with role=\"switch\", announced as on/off.",
477
+ "status": "stable",
450
478
  "variants": {
451
479
  "size": [
452
480
  "sm",
@@ -460,10 +488,11 @@
460
488
  ]
461
489
  },
462
490
  "detail": "dist/meta/Toggle.json",
463
- "hasIntent": false
491
+ "hasIntent": true
464
492
  },
465
493
  "Tooltip": {
466
- "summary": "Tooltip — Figma `Tooltip` (801:1568).",
494
+ "summary": "A text-only hint attached to a trigger. Opens on hover and on focus.",
495
+ "status": "stable",
467
496
  "variants": {
468
497
  "placement": [
469
498
  "right",
@@ -473,7 +502,7 @@
473
502
  ]
474
503
  },
475
504
  "detail": "dist/meta/Tooltip.json",
476
- "hasIntent": false
505
+ "hasIntent": true
477
506
  }
478
507
  }
479
508
  }
package/llms.txt ADDED
@@ -0,0 +1,27 @@
1
+ # ionbase-ui
2
+
3
+ > IonBase is a React design system for enterprise SaaS, built to be consumed by an agent rather than read by a developer. Every component ships a machine-readable contract carrying the judgement a type signature cannot: when to use it, what to use instead, the anti-patterns, and what it guarantees for accessibility versus what it requires of you.
4
+
5
+ Version 0.20.0. 35 components.
6
+
7
+ ## Read these, in this order
8
+
9
+ 1. `dist/meta/index.json` — every component with its summary and variant axes. Pick one from here.
10
+ 2. `dist/meta/<Name>.json` — the full contract for that one component: props with their origins and defaults, variant guidance, slots, accessibility guarantees and requirements, anti-patterns, tokens.
11
+
12
+ Both are importable: `ionbase-ui/meta/index` and `ionbase-ui/meta/<Name>.json`. Do NOT load `ionbase-ui/meta` (`components.json`) — it is all 35 contracts in one file, for tooling that wants a single fetch, and it will bury the component you need.
13
+
14
+ ## Components
15
+
16
+ `Alert`, `Avatar`, `AvatarGroup`, `Badge`, `Button`, `Checkbox`, `Divider`, `FullCard`, `Header`, `Icon`, `Input`, `Link`, `Logo`, `LogoMark`, `Menu`, `MenuItem`, `Modal`, `NavItem`, `PhoneInput`, `Popover`, `Radio`, `RadioGroup`, `ScrollProgress`, `Select`, `TabItem`, `Table`, `TableBody`, `TableCell`, `TableHead`, `TableRow`, `Tabs`, `Toast`, `ToastProvider`, `Toggle`, `Tooltip`
17
+
18
+ ## Rules that ship with this package
19
+
20
+ - `ionbase-ui/eslint-plugin` — five rules driven from the contracts: deprecated props, missing accessible names, raw style values, measured contrast failures, competing primary actions.
21
+ - `ionbase-ui/stylelint-config` — bans raw colour and spacing values in favour of tokens.
22
+
23
+ Turn both on. They encode the same judgement as the contracts, enforced.
24
+
25
+ ## Hosted
26
+
27
+ https://raza-ahmed.github.io/ionbase-design-system/llms.txt — the same index with per-component markdown pages.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ionbase-ui",
3
- "version": "0.18.1",
3
+ "version": "0.20.0",
4
4
  "description": "IonBase Design System — accessible React components, styles and design tokens in one package",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -22,6 +22,7 @@
22
22
  "types": "./dist/tokens-js.d.ts",
23
23
  "default": "./dist/tokens-js.js"
24
24
  },
25
+ "./llms.txt": "./llms.txt",
25
26
  "./stylelint-config": "./stylelint-config.js",
26
27
  "./eslint-plugin": "./eslint-plugin/index.js"
27
28
  },
@@ -38,7 +39,8 @@
38
39
  "files": [
39
40
  "dist",
40
41
  "eslint-plugin",
41
- "stylelint-config.js"
42
+ "stylelint-config.js",
43
+ "llms.txt"
42
44
  ],
43
45
  "sideEffects": [
44
46
  "**/*.css"
@@ -57,7 +59,7 @@
57
59
  },
58
60
  "scripts": {
59
61
  "dev": "tsc --watch",
60
- "build": "node scripts/sync-tokens.mjs && tsc --build --force && node scripts/copy-css.mjs && node scripts/verify-client-boundaries.mjs && node scripts/verify-contrast.mjs && node scripts/build-meta.mjs && node scripts/verify-meta.mjs",
62
+ "build": "node scripts/sync-tokens.mjs && tsc --build --force && node scripts/copy-css.mjs && node scripts/verify-client-boundaries.mjs && node scripts/verify-contrast.mjs && node scripts/build-meta.mjs && node scripts/verify-meta.mjs && node scripts/build-llms.mjs",
61
63
  "typecheck": "tsc --noEmit",
62
64
  "lint": "eslint . && stylelint \"src/styles/*.css\"",
63
65
  "format": "prettier --check .",
@@ -65,7 +67,8 @@
65
67
  "meta:build": "node scripts/build-meta.mjs",
66
68
  "meta:verify": "node scripts/build-meta.mjs && node scripts/verify-meta.mjs",
67
69
  "contrast": "node scripts/verify-contrast.mjs",
68
- "contrast:list": "node scripts/verify-contrast.mjs --list"
70
+ "contrast:list": "node scripts/verify-contrast.mjs --list",
71
+ "llms": "node scripts/build-llms.mjs"
69
72
  },
70
73
  "peerDependencies": {
71
74
  "react": "^18.0.0 || ^19.0.0",