staffa 0.6.0 → 0.6.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 (48) hide show
  1. package/README.md +2 -0
  2. package/package.json +3 -2
  3. package/skill/Attributes.md +10 -0
  4. package/skill/AutocompleteOptions.md +37 -0
  5. package/skill/BoxOptions.md +33 -0
  6. package/skill/ButtonChooserOptions.md +37 -0
  7. package/skill/ButtonGroupOptions.md +23 -0
  8. package/skill/ButtonOptions.md +57 -0
  9. package/skill/CheckboxOptions.md +27 -0
  10. package/skill/ContentOptions.md +16 -0
  11. package/skill/DialogOptions.md +70 -0
  12. package/skill/FieldOptions.md +63 -0
  13. package/skill/FloatingMenuOptions.md +21 -0
  14. package/skill/FormOptions.md +31 -0
  15. package/skill/MainOptions.md +91 -0
  16. package/skill/MenuItem.md +52 -0
  17. package/skill/MenuOptions.md +25 -0
  18. package/skill/SKILL.md +548 -0
  19. package/skill/SelectOptions.md +21 -0
  20. package/skill/Slot.md +13 -0
  21. package/skill/Tab.md +33 -0
  22. package/skill/TabsOptions.md +28 -0
  23. package/skill/TextareaOptions.md +51 -0
  24. package/skill/TextlineOptions.md +45 -0
  25. package/skill/TextlineType.md +18 -0
  26. package/skill/ToastOptions.md +40 -0
  27. package/skill/TooltipOptions.md +22 -0
  28. package/skill/addTooltip.md +25 -0
  29. package/skill/alert.md +17 -0
  30. package/skill/autocomplete.md +22 -0
  31. package/skill/box.md +25 -0
  32. package/skill/button.md +29 -0
  33. package/skill/buttonChooser.md +23 -0
  34. package/skill/buttonGroup.md +20 -0
  35. package/skill/checkbox.md +17 -0
  36. package/skill/confirm.md +17 -0
  37. package/skill/dialog.md +28 -0
  38. package/skill/form.md +28 -0
  39. package/skill/getDarkMode.md +12 -0
  40. package/skill/main.md +33 -0
  41. package/skill/menuButton.md +27 -0
  42. package/skill/prompt.md +19 -0
  43. package/skill/select.md +17 -0
  44. package/skill/showFloatingMenu.md +22 -0
  45. package/skill/tabs.md +19 -0
  46. package/skill/textarea.md +16 -0
  47. package/skill/textline.md +19 -0
  48. package/skill/toast.md +20 -0
package/skill/SKILL.md ADDED
@@ -0,0 +1,548 @@
1
+ ---
2
+ name: staffa
3
+ description: Documentation for the Staffa component library for Aberdeen. Covers *surfaces*, CSS variables for colors etc, how to the various `s-` prefixed css classes, customizing, overriding style, adding own components. Access this if you're doing front-end work on an Aberdeen project that already uses Staffa, or may benefit from it.
4
+ ---
5
+
6
+ # Staffa
7
+
8
+ A small, opinionated TypeScript component library for the [Aberdeen](https://aberdeenjs.org) reactive UI library.
9
+
10
+ ```ts
11
+ import A from "aberdeen";
12
+ import * as S from "staffa";
13
+
14
+ const $user = A.proxy({ name: "", email: "" });
15
+
16
+ A.mount(document.body, () => {
17
+ S.main({
18
+ title: "Sign up",
19
+ maxWidth: "40rem",
20
+ content: () => {
21
+ S.form({
22
+ submit: () => console.log(A.unproxy($user)),
23
+ content: () => {
24
+ S.textline({ label: "Name", required: true, bind: A.ref($user, "name") });
25
+ S.textline({ label: "Email", type: "email", bind: A.ref($user, "email") });
26
+ },
27
+ actions: () => S.button({ text: "Create account", type: "submit" }),
28
+ });
29
+ },
30
+ });
31
+ });
32
+ ```
33
+
34
+ Staffa is made to look decent out of the box, but easily customizable at runtime.
35
+
36
+ ## Install
37
+
38
+ ```sh
39
+ npm install staffa aberdeen
40
+ ```
41
+
42
+ Aberdeen is a peer dependency. Staffa is published as ESM with TypeScript types.
43
+
44
+ ## How it works
45
+
46
+ ### Components are functions
47
+
48
+ Every component takes a single typed options object and draws DOM via Aberdeen. No classes, no web components. The `S` object collects all component functions:
49
+
50
+ ```ts
51
+ S.button({ text: "Save", disabled: false });
52
+ S.box({ header: "Settings", content: () => { ... } });
53
+ ```
54
+
55
+ ### Options objects are typed and can be reactive
56
+
57
+ All components get their options in a typed object. The object may be an Aberdeen proxy, if you want to update the component in-place.
58
+
59
+ ```ts
60
+ const $btn = A.proxy({ text: "Save", disabled: false });
61
+ S.button($btn);
62
+ // ...later:
63
+ $btn.disabled = true; // button updates instantly
64
+ ```
65
+
66
+ ### Rich text slots
67
+
68
+ Anywhere a component takes content, a `label`, `header`, button `text`, dialog body, etc, you can pass either a string or a `() => void` draw function. Strings render as **rich text**: `*italic*`, `**bold**`, `` `code` ``, `[link](/path)`. All text is safely escaped.
69
+
70
+ ```ts
71
+ S.button({ text: "Save **now**" });
72
+ S.box({ header: "See the [docs](/docs)", content: () => { ... } });
73
+ ```
74
+
75
+ ### Surfaces
76
+
77
+ Staffa builds on **surfaces**: elements marked with `.s-s` that have their own background and derived text/border tokens. Add modifier classes to colour them:
78
+
79
+ - **level**: `.base`, `.panel`, `.raised`
80
+ - **role**: `.primary`, `.secondary`, `.gradient`, `.neutral`, `.danger`, `.success`, `.warning`
81
+ - **variant**: `.filled`, `.tonal`, `.outlined`
82
+
83
+ Components are built from these (`S.button` is a `.s-s.primary.filled`, `S.box` a `.s-s.panel`, etc.). Because component options include an optional `attrs` string, which has Aberdeen `A()` string semantics, you can easily override it:
84
+
85
+ ```ts
86
+ S.button({ text: "Delete", attrs: ".danger" });
87
+ S.box({ attrs: ".raised.outlined", content: () => { ... } });
88
+ ```
89
+
90
+ Inside any surface, CSS variables are defined for suitable foreground colors (`$s-fg`, `$s-bg`, `$s-fg-muted`, `$s-border`, `$s-accent`, ...), with `color` defaulting to `$s-fg`. By using these, components has access to various foreground colors that will look regardless of the surface it is drawing on.
91
+
92
+ ### Dark and light modes
93
+
94
+ Dark/light mode is detected from OS preference by default. If you want to override this (based on user preferences), use:
95
+
96
+ ```ts
97
+ S.setDarkMode(true); // force dark
98
+ S.setDarkMode(false); // force light
99
+ S.setDarkMode(undefined); // follow OS
100
+ ```
101
+
102
+ *Hint:* A `buttonChooser` is probably the right component for a color scheme selector.
103
+
104
+ ### CSS reset
105
+
106
+ Staffa includes a lightweight CSS reset that makes bare semantic HTML look a bit better but unsurprising without additional styling.
107
+
108
+ ### Theming
109
+
110
+ The first step in theming is just setting some CSS variables, most commonly the primary and secondary color. This can be done through CSS directly, or using Aberdeen:
111
+
112
+ ```ts
113
+ A.cssVars["s-primary"] = "#fdda58";
114
+ A.cssVars["s-secondary"] = "#cc5624";
115
+ A.cssVars["s-danger"] = "#ee4422";
116
+ A.cssVars["s-radius"] = "4px";
117
+ ```
118
+
119
+ See `src/theme.ts` for what other CSS variables are being used.
120
+
121
+ If you need further customization, just add some CSS to override the default styling. For instance, to add your own surface type:
122
+
123
+ ```ts
124
+ // In filled mode, 's-a' is the foreground and 's-b' is the background. "outlined" and "tonal" use the colors in different ways.
125
+ A.insertGlobalCss({".s-s.my-surface": "--s-a:white --s-b:#ef6b00"});
126
+
127
+ S.button({
128
+ text: "You'll want to click me",
129
+ attrs: ".my-surface",
130
+ click: () => S.alert("Good work!", {attrs: ".my-surface"})
131
+ });
132
+ ```
133
+
134
+ Note that when changing CSS like this, things *may* break if you upgrade Staffa. The recommended update strategy is therefore: don't!
135
+
136
+ If you want to make changes that are dependent upon the current light/dark mode setting, rely on Aberdeen reactivity:
137
+
138
+ ```ts
139
+ A(() => {
140
+ if (S.getDarkMode()) {
141
+ A.cssVars["s-primary"] = "#aa9944";
142
+ A.insertGlobalCss({".s-s.my-surface": "--s-a:white --s-b:#444444"});
143
+ } else {
144
+ A.cssVars["s-primary"] = "#fdda58";
145
+ A.insertGlobalCss({".s-s.my-surface": "--s-a:black --s-b:#cccccc"});
146
+ }
147
+ });
148
+ ```
149
+
150
+ ## Components
151
+
152
+ Components share naming conventions for options: `attrs` (outermost element), `contentAttrs` (children-holding element), `inputAttrs` (form control element), and `<region>Attrs` (sub-regions like `headerAttrs`/`footerAttrs`). Form components consistently support `label`, `help`, `error`, `disabled`, `required`, `name` through the `drawField()` helper.
153
+
154
+ ### Layout & containers
155
+
156
+ - **`S.main(opts)`**: app shell, a sticky header with `icon`, `title`, `subtitle`, `menu`; scrollable content area; footer. Set `maxWidth` to center the content.
157
+ - **`S.box(opts | content)`**: surface with optional `header`/`footer` and padded body. Pass a function for shorthand `{ content }`.
158
+ - **`S.tabs(opts)`**: tablist with live panels and keyboard navigation.
159
+ - **`S.form(opts | content)`**: form aligning fields in a column or responsive grid, with an `actions` bar. Prevents the default page reload.
160
+
161
+ ### Form fields
162
+
163
+ - **`S.textline(opts)`**: single-line input (`text`, `password`, `email`, `number`, `tel`, `url`, `search`, dates, ...).
164
+ - **`S.textarea(opts)`**: multi-line input.
165
+ - **`S.checkbox(opts)`**: labelled checkbox.
166
+ - **`S.select(opts)`**: single-select dropdown backed by native `<select>` (styled control, OS dropdown).
167
+ - **`S.autocomplete(opts)`**: type-ahead combobox with `multi` (chips), `allowCustom` (free text), `required`, and dynamic `options`.
168
+
169
+ ### Dialogs
170
+
171
+ - **`S.dialog(opts)`**: modal dialog with backdrop and fade transition. The `content` slot receives a `close()` function. Lifecycle is tied to the calling scope (disappears when cleaned up). Nesting stacks correctly.
172
+ - **`S.alert(msg)` / `S.confirm(msg)` / `S.prompt(msg, initial?)`**: promise-returning shortcuts.
173
+
174
+ ### Actions
175
+
176
+ - **`S.button(opts | text)`**: button surface; restyle via `attrs` (e.g. `.danger`, `.outlined`), plus `size`, `disabled`, `icon`, `href` (renders `<a role=button>`). Defaults to filled `.primary`.
177
+ - **`S.buttonGroup(opts)`**: groups buttons, `attached` (segmented) or `spaced`.
178
+ - **`S.buttonChooser(opts)`**: single-select segmented control bound to a value.
179
+
180
+
181
+ ### Icons
182
+
183
+ Staffa ships the full [Lucide icon set](https://lucide.dev/icons/) as named exports. Import only the ones you use, so a bundler tree-shakes the rest (the whole set is ~82 kB gzipped):
184
+
185
+ ```ts
186
+ import { sparkles, bell } from "staffa/icons.js";
187
+ ```
188
+
189
+ Each icon is a draw function usable anywhere a slot is accepted (e.g. a button `icon`), or called directly. Customize per call, or globally via `setDefaults()`:
190
+
191
+ ```ts
192
+ S.button({ text: "Save", icon: bell });
193
+ sparkles({ size: "1.5em", color: "var(--s-primary)", strokeWidth: 1.5 });
194
+ ```
195
+
196
+ Options: `size`, `color` (defaults to `currentColor`), `strokeWidth`, `cap`, `join`, `attrs`.
197
+
198
+ ### Other
199
+
200
+ - **`S.menuButton(opts)` / `S.showFloatingMenu(opts)`**: menu actions and floating menus, with keyboard navigation and submenus.
201
+ - **`S.toast(opts)`**: transient notification at the bottom of the viewport.
202
+ - **`S.addTooltip(el, opts)`**: tooltip on hover, attached to an existing element.
203
+
204
+ Two-way binding uses Aberdeen proxies: pass `bind: A.ref($obj, "key")` to form fields.
205
+
206
+ ## Browser (no bundler)
207
+
208
+ `staffa/all.js` is a pre-built ESM bundle. Use an [import map](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/script/type/importmap):
209
+
210
+ ```html
211
+ <script type="importmap">
212
+ {
213
+ "imports": {
214
+ "aberdeen": "https://cdn.jsdelivr.net/npm/aberdeen/dist/src/aberdeen.js",
215
+ "staffa/all.js": "https://cdn.jsdelivr.net/npm/staffa/dist/staffa.esm.js"
216
+ }
217
+ }
218
+ </script>
219
+ <script type="module">
220
+ import A from "aberdeen";
221
+ import * as S from "staffa/all.js";
222
+ // ...
223
+ </script>
224
+ ```
225
+
226
+ It includes all components, but not the icons.
227
+
228
+ ## Extending Staffa
229
+
230
+ Staffa is designed for extension. A component is simply a plain function taking a typed options object and drawing Aberdeen DOM. This section explains the philosophy so extensions follow the same patterns.
231
+
232
+ ### Design principles
233
+
234
+ 1. **Components are functions**. They take one typed options object, emit Aberdeen DOM, and *usually* return nothing.
235
+
236
+ 2. **Reuse option types.** Define options by extending `ContentOptions` (for layout components) or `FieldOptions` (for form controls) from `src/core.ts` and `src/components/field.ts`. Don't reinvent fields like `attrs`, `label`, `help`, etc.
237
+
238
+ 3. **Reach for reactivity deliberately.** Pass option strings straight to `A` as positional args (the caller's scope). Only wrap a dedicated `A(() => ...)` scope where it matters: input elements (recreation loses focus), or large subtrees you don't want to redraw. Use `A.peek(() => ...)` when you need a value but must not subscribe.
239
+
240
+ 4. **Build on surfaces.** Mark elements `.s-s` and add level/role/variant modifiers. Inside them, use the contextual foreground color CSS variables (`$s-fg`, `$s-bg`, `$s-border`, ...) so components adapt to wherever they're nested. Hard-coding colors in components shouldn't be needed, but if you must, make sure you set *both* foreground and background.
241
+
242
+ 5. **No outer margins.** Components don't margin themselves; spacing is the parent's job. Content components set default `padding` on the content element; `contentAttrs` overrides it.
243
+
244
+ 6. **Make everything styleable.** Provide `attrs`, `contentAttrs`, `inputAttrs`, and `<region>Attrs` hooks so callers can customize. Apply `attrs` last so it can override component classes.
245
+
246
+ 7. **Use semantic HTML and ARIA.** Prefer native elements (`<button>`, `<label>`, `<form>`, `<section>`) and native behaviour. Add ARIA only where semantics fall short (e.g. tabs, combobox).
247
+
248
+ 8. **Use CSS.** Use `A.insertGlobalCss({...})` at module top level to provide (nested) CSS styling for your component. Give your top-level element the `s-<component-name>` class. Avoid inventing further classes; lean on nesting (`&` for the element, bare key for descendants) and element/structural selectors.
249
+
250
+ 9. **Reuse form controls.** Use `drawField()` and call `applyControlAttrs()`.
251
+
252
+ 10. **Function over form.** Provide enough contrast. Stick to UI conventions to help users; buttons have a rounded border, links are underlined, text input background is white, etc.
253
+
254
+ ### Adding a component to Staffa
255
+
256
+ The previous section is good advice for any project-specific custom, but should definitely be followed for any new components to be included in Staffa. In addition, you'd want to:
257
+
258
+ 1. Create `src/components/<name>.ts`.
259
+ 2. Define `<Name>Options` extending `ContentOptions`, `FieldOptions`, or a plain interface. Add TSDoc on every option.
260
+ 3. Add a TSDoc `@example` on the function.
261
+ 4. Register in `src/index.ts` (the `S` object + type re-export).
262
+ 5. Extend `smoke.mjs` to render it. Run `npm run smoke` and `npm run build`.
263
+
264
+ See `src/components/button.ts` and `src/components/dialog.ts` for examples.
265
+
266
+ ## Commands
267
+
268
+ ```sh
269
+ npm run build # compile TypeScript to dist/
270
+ npm run typecheck # check types
271
+ npm run smoke # render every component in jsdom
272
+ npx http-server # allows demo to be viewed at http://localhost:8080/demo
273
+ npx shotest test # visual tests: click through the demo, screenshotting every step
274
+ npx shotest review # review/accept the visual changes against the baseline
275
+ ```
276
+
277
+ The visual tests (`tests/*.spec.ts`) need a build first (`npm run build`); they serve the repo root themselves and click through every demo page. Accepted baselines live in `test-accepted/`.
278
+
279
+ # API Reference
280
+
281
+ ## setDarkMode · function
282
+
283
+ Force dark mode (`true`), light mode (`false`), or follow the OS preference
284
+ (`undefined`). Takes effect immediately and is persisted to localStorage.
285
+
286
+ **Signature:** `(value: boolean) => void`
287
+
288
+ **Parameters:**
289
+
290
+ - `value: boolean | undefined`
291
+
292
+ ## [getDarkMode](getDarkMode.md) · function
293
+
294
+ Whether dark mode is currently active. Reactive — read it inside a scope to
295
+ re-run on changes.
296
+
297
+ ## [autocomplete](autocomplete.md) · function
298
+
299
+ A combobox with type-ahead filtering. Supports single or multi-select (chips),
300
+ optional free-text entry, and full keyboard control (arrows, enter, escape,
301
+ backspace-to-remove). Implements the ARIA combobox/listbox pattern.
302
+
303
+ ## [AutocompleteOptions](AutocompleteOptions.md) · interface
304
+
305
+ Options for `autocomplete`.
306
+
307
+ ## AutocompleteOptionInput · type
308
+
309
+ A selectable option: a bare string, or a `{ value, label }` pair.
310
+
311
+ **Type:** `string | { value: string; label?: string }`
312
+
313
+ ## [box](box.md) · function
314
+
315
+ A surface container — the workhorse layout primitive. Has an optional styled
316
+ header and footer, and a padded body that holds `ContentOptions.content`.
317
+
318
+ ## [BoxOptions](BoxOptions.md) · interface
319
+
320
+ Options for `box`.
321
+
322
+ ## [button](button.md) · function
323
+
324
+ A button. Always carries at least a visible border so its affordance is
325
+ obvious at a glance.
326
+
327
+ ## [ButtonOptions](ButtonOptions.md) · interface
328
+
329
+ Options for `button`.
330
+
331
+ ## [buttonChooser](buttonChooser.md) · function
332
+
333
+ A single-selection segmented control: an attached button group where exactly
334
+ one button is active at a time. Optionally allows deselecting back to `undefined`.
335
+
336
+ ## [ButtonChooserOptions](ButtonChooserOptions.md) · interface
337
+
338
+ Options for `buttonChooser`.
339
+
340
+ ## [buttonGroup](buttonGroup.md) · function
341
+
342
+ Groups related buttons, either as a joined segmented control (`attached`) or
343
+ spaced out. A `role=group` is applied for assistive tech.
344
+
345
+ ## [ButtonGroupOptions](ButtonGroupOptions.md) · interface
346
+
347
+ Options for `buttonGroup`.
348
+
349
+ ## [checkbox](checkbox.md) · function
350
+
351
+ A checkbox with an associated, clickable label. Uses the native `<input
352
+ type=checkbox>` (styled with `accent-color`) for full keyboard and screen
353
+ reader support.
354
+
355
+ ## [CheckboxOptions](CheckboxOptions.md) · interface
356
+
357
+ Options for `checkbox`.
358
+
359
+ ## [form](form.md) · function
360
+
361
+ An opinionated `<form>` wrapper that lays its fields out consistently — a clean
362
+ single column by default, or a responsive grid — and provides a standard
363
+ action bar.
364
+
365
+ ## [FormOptions](FormOptions.md) · interface
366
+
367
+ Options for `form`.
368
+
369
+ ## [main](main.md) · function
370
+
371
+ An application shell that wires up the things almost every app needs: a sticky
372
+ top bar (icon, title, subtitle, action menu), a scrollable content area, and a
373
+ footer. With `MainOptions.maxWidth` the content area is centred and its
374
+ width capped. Add a `nav` to get a responsive sidebar (auto-collapses to a
375
+ menu button below 640 px, or always a button with `navPosition: "button"`).
376
+
377
+ ## [MainOptions](MainOptions.md) · interface
378
+
379
+ Options for `main`.
380
+
381
+ ## [menuButton](menuButton.md) · function
382
+
383
+ A button that opens a | floating dropdown menu on
384
+ click. Keyboard navigation: Arrow Up/Down, Home, End; Escape/Tab to close;
385
+ Enter/Space activate the focused item natively.
386
+
387
+ ## [showFloatingMenu](showFloatingMenu.md) · function
388
+
389
+ Open a floating dropdown menu anchored to an element. Portals to
390
+ `document.body` (never clipped), positions itself (flipping up when there's
391
+ no room below), and closes on Escape, Tab, item selection, or any click
392
+ outside the panel and anchor. Returns a `close()` function.
393
+
394
+ ## [MenuOptions](MenuOptions.md) · interface
395
+
396
+ Options for `menuButton` and `MainOptions.nav`.
397
+
398
+ ## MenuEntry · type
399
+
400
+ An entry in a menu or sidebar nav list. Three forms:
401
+ - `MenuItem` — a clickable/linkable row with label and optional icon.
402
+ - `MenuSeparator` — a visual divider (`{ separator: true }`).
403
+ - A slot (string or draw function) — renders custom content (section header,
404
+ avatar, search box, …). Skipped by keyboard navigation.
405
+
406
+ **Type:** `MenuItem | MenuSeparator | Slot`
407
+
408
+ ## [MenuItem](MenuItem.md) · interface
409
+
410
+ A clickable item in a menu or sidebar nav.
411
+
412
+ ## MenuSeparator · interface
413
+
414
+ A visual divider between groups of items.
415
+
416
+ ### menuSeparator.separator · member
417
+
418
+ **Type:** `true`
419
+
420
+ ## [FloatingMenuOptions](FloatingMenuOptions.md) · interface
421
+
422
+ Options for `showFloatingMenu`.
423
+
424
+ ## [dialog](dialog.md) · function
425
+
426
+ A dialog rendered into `document.body` via `A.mount`, with a dimming backdrop
427
+ that fades in and out. Returns a `Promise<void>` that resolves when the dialog
428
+ closes. Lifecycle is also tied to the parent reactive scope — when that scope
429
+ is cleaned up the dialog disappears and the promise resolves.
430
+
431
+ ## [alert](alert.md) · function
432
+
433
+ Shows a message dialog with a single OK button. Returns a `Promise<void>`
434
+ that resolves when the user dismisses it.
435
+
436
+ ## [confirm](confirm.md) · function
437
+
438
+ Shows a confirmation dialog with Cancel and OK buttons. Returns a
439
+ `Promise<boolean>` — `true` if the user clicked OK, `false` otherwise.
440
+
441
+ ## [prompt](prompt.md) · function
442
+
443
+ Shows a prompt dialog with a text input. Returns a `Promise<string | null>` —
444
+ the entered string if the user confirmed, or `null` if cancelled.
445
+
446
+ ## [DialogOptions](DialogOptions.md) · interface
447
+
448
+ Options for `dialog`.
449
+
450
+ ## [select](select.md) · function
451
+
452
+ A single-select dropdown backed by a native `<select>` element. Looks like the
453
+ other Staffa inputs but delegates all focus management, keyboard navigation, and
454
+ mobile-native picker behaviour to the browser.
455
+
456
+ ## [SelectOptions](SelectOptions.md) · interface
457
+
458
+ Options for `select`.
459
+
460
+ ## SelectOptionInput · type
461
+
462
+ A selectable option: a bare string, or a `{ value, label }` pair.
463
+
464
+ **Type:** `string | { value: string; label?: string }`
465
+
466
+ ## [tabs](tabs.md) · function
467
+
468
+ A tabbed view. Renders an ARIA `tablist` of buttons and a single live panel
469
+ for the selected tab. Supports keyboard navigation (left/right/home/end).
470
+
471
+ ## [Tab](Tab.md) · interface
472
+
473
+ A single tab definition.
474
+
475
+ ## [TabsOptions](TabsOptions.md) · interface
476
+
477
+ Options for `tabs`.
478
+
479
+ ## [textarea](textarea.md) · function
480
+
481
+ A multi-line text input. Shares the field chrome and styling of
482
+ `textline`, adding `rows` and `resize` controls.
483
+
484
+ ## [TextareaOptions](TextareaOptions.md) · interface
485
+
486
+ Options for `textarea`.
487
+
488
+ ## [textline](textline.md) · function
489
+
490
+ A single-line text input — covering text, passwords, numbers, email, dates and
491
+ the other line-oriented `<input>` types.
492
+
493
+ ## [TextlineOptions](TextlineOptions.md) · interface
494
+
495
+ Options for `textline`.
496
+
497
+ ## [TextlineType](TextlineType.md) · type
498
+
499
+ The `<input>` types `textline` supports. Deliberately excludes types
500
+ that need their own widget (`checkbox`, `radio`, `color`, `range`, `file`,
501
+ `button`, ...) — use the dedicated components for those.
502
+
503
+ ## [toast](toast.md) · function
504
+
505
+ Show a toast notification. Returns a `dismiss()` function to remove it
506
+ programmatically. Auto-dismisses after `duration` ms (default 4 000).
507
+
508
+ ## [ToastOptions](ToastOptions.md) · interface
509
+
510
+ Options for `toast`.
511
+
512
+ ## [addTooltip](addTooltip.md) · function
513
+
514
+ Attaches a tooltip to the current element: adds hover/focus handlers via
515
+ `A` so the tip appears when the element is hovered or keyboard-focused.
516
+ The tip panel is rendered into `document.body` via a portal, so it is never
517
+ clipped by `overflow:hidden` ancestors. Position is computed from the
518
+ element's bounding rect and automatically flips when near the viewport edge.
519
+
520
+ ## [TooltipOptions](TooltipOptions.md) · interface
521
+
522
+ Options for `addTooltip`.
523
+
524
+ ## [FieldOptions](FieldOptions.md) · interface
525
+
526
+ Options shared by all *form field* components (textline, textarea, checkbox,
527
+ autocomplete, ...).
528
+
529
+ ## [ContentOptions](ContentOptions.md) · interface
530
+
531
+ Options for components that wrap a single block of caller-provided content,
532
+ with an `attrs` escape hatch on the outermost element.
533
+
534
+ ## Bindable · type
535
+
536
+ A reactive "value box", such as the result of `A.proxy(x)` or `A.ref(obj, key)`.
537
+
538
+ **Type:** `{ value: T }`
539
+
540
+ ## [Slot](Slot.md) · type
541
+
542
+ Something that renders a small piece of content: either a plain string or a
543
+ draw function (for icons, badges, custom markup, ...).
544
+
545
+ ## [Attributes](Attributes.md) · type
546
+
547
+ Shared building blocks for the Staffa component library.
548
+
@@ -0,0 +1,21 @@
1
+ ## SelectOptions · interface
2
+
3
+ Options for `select`.
4
+
5
+ ### selectOptions.options · member
6
+
7
+ The list of selectable options.
8
+
9
+ **Type:** `SelectOptionInput[] | (() => SelectOptionInput[])`
10
+
11
+ ### selectOptions.bind · member
12
+
13
+ Two-way binding for the selected value string (`""` when nothing is selected).
14
+
15
+ **Type:** `Bindable<string>`
16
+
17
+ ### selectOptions.placeholder · member
18
+
19
+ Placeholder option shown when nothing is selected yet.
20
+
21
+ **Type:** `string`
package/skill/Slot.md ADDED
@@ -0,0 +1,13 @@
1
+ ## Slot · type
2
+
3
+ Something that renders a small piece of content: either a plain string or a
4
+ draw function (for icons, badges, custom markup, ...).
5
+
6
+ A string is drawn as **rich text** (see `drawSlot`): Aberdeen's `rich`
7
+ markup is applied, so `*italic*`, `**bold**`, `` `code` `` and
8
+ `[links](/path)` render as inline elements (text is safely escaped).
9
+
10
+ The optional `Args` type parameter lets a slot's draw-function receive
11
+ arguments — e.g. a dialog body is a `Slot<[close: () => void]>`.
12
+
13
+ **Type:** `string | ((...args: Args) => void)`
package/skill/Tab.md ADDED
@@ -0,0 +1,33 @@
1
+ ## Tab · interface
2
+
3
+ A single tab definition.
4
+
5
+ ### tab.id · member
6
+
7
+ Stable id used as the selection value. Falls back to the array index.
8
+
9
+ **Type:** `string`
10
+
11
+ ### tab.label · member
12
+
13
+ Tab label shown in the tab strip.
14
+
15
+ **Type:** `Slot`
16
+
17
+ ### tab.icon · member
18
+
19
+ Optional leading icon.
20
+
21
+ **Type:** `Slot`
22
+
23
+ ### tab.content · member
24
+
25
+ Content rendered in the panel when this tab is active. A string is rendered as rich text.
26
+
27
+ **Type:** `Slot`
28
+
29
+ ### tab.disabled · member
30
+
31
+ Disables selecting this tab.
32
+
33
+ **Type:** `boolean`
@@ -0,0 +1,28 @@
1
+ ## TabsOptions · interface
2
+
3
+ Options for `tabs`.
4
+
5
+ ### tabsOptions.attrs · member
6
+
7
+ Aberdeen attr/style string applied to the outermost element.
8
+
9
+ **Type:** `string`
10
+
11
+ ### tabsOptions.tabs · member
12
+
13
+ The tabs to display.
14
+
15
+ **Type:** `Tab[]`
16
+
17
+ ### tabsOptions.bind · member
18
+
19
+ Two-way binding for the selected tab's id. When omitted, the component keeps
20
+ its own internal selection, starting at the first tab.
21
+
22
+ **Type:** `Bindable<string>`
23
+
24
+ ### tabsOptions.contentAttrs · member
25
+
26
+ Aberdeen attr/style string applied to the active panel.
27
+
28
+ **Type:** `string`
@@ -0,0 +1,51 @@
1
+ ## TextareaOptions · interface
2
+
3
+ Options for `textarea`.
4
+
5
+ ### textareaOptions.placeholder · member
6
+
7
+ Placeholder text.
8
+
9
+ **Type:** `string`
10
+
11
+ ### textareaOptions.bind · member
12
+
13
+ Two-way binding target.
14
+
15
+ **Type:** `Bindable<string>`
16
+
17
+ ### textareaOptions.value · member
18
+
19
+ Static initial value.
20
+
21
+ **Type:** `string`
22
+
23
+ ### textareaOptions.rows · member
24
+
25
+ Visible number of text rows. Defaults to `4`. Ignored when `autoGrow` is enabled.
26
+
27
+ **Type:** `number`
28
+
29
+ ### textareaOptions.resize · member
30
+
31
+ Whether the textarea may be resized by the user. Defaults to `"vertical"`. Ignored when `autoGrow` is enabled.
32
+
33
+ **Type:** `"none" | "vertical" | "horizontal" | "both"`
34
+
35
+ ### textareaOptions.autoGrow · member
36
+
37
+ Auto-grow the textarea to fit its content. Defaults to `true`.
38
+
39
+ **Type:** `boolean`
40
+
41
+ ### textareaOptions.input · member
42
+
43
+ Fired on every `input` event.
44
+
45
+ **Type:** `(event: Event) => void`
46
+
47
+ ### textareaOptions.change · member
48
+
49
+ Fired on `change` (commit).
50
+
51
+ **Type:** `(event: Event) => void`