staffa 0.6.0 → 0.7.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.
Files changed (85) hide show
  1. package/README.md +36 -16
  2. package/dist/components/autocomplete.js +12 -9
  3. package/dist/components/box.js +15 -10
  4. package/dist/components/button.d.ts +3 -1
  5. package/dist/components/button.js +21 -28
  6. package/dist/components/buttonChooser.js +1 -1
  7. package/dist/components/buttonGroup.d.ts +3 -3
  8. package/dist/components/buttonGroup.js +3 -3
  9. package/dist/components/dialog.d.ts +3 -1
  10. package/dist/components/dialog.js +20 -10
  11. package/dist/components/field.js +7 -4
  12. package/dist/components/main.js +52 -15
  13. package/dist/components/menu.d.ts +23 -2
  14. package/dist/components/menu.js +54 -29
  15. package/dist/components/select.js +1 -1
  16. package/dist/components/tabs.js +3 -3
  17. package/dist/components/toast.js +8 -8
  18. package/dist/components/tooltip.js +4 -3
  19. package/dist/core.d.ts +14 -2
  20. package/dist/core.js +23 -0
  21. package/dist/staffa.esm.js +1 -1
  22. package/dist/theme.js +138 -224
  23. package/package.json +3 -2
  24. package/skill/Attributes.md +10 -0
  25. package/skill/AutocompleteOptions.md +37 -0
  26. package/skill/BoxOptions.md +33 -0
  27. package/skill/ButtonChooserOptions.md +37 -0
  28. package/skill/ButtonGroupOptions.md +23 -0
  29. package/skill/ButtonOptions.md +58 -0
  30. package/skill/CheckboxOptions.md +27 -0
  31. package/skill/ContentOptions.md +16 -0
  32. package/skill/DialogOptions.md +70 -0
  33. package/skill/FieldOptions.md +63 -0
  34. package/skill/FloatingMenuOptions.md +21 -0
  35. package/skill/FormOptions.md +31 -0
  36. package/skill/MainOptions.md +91 -0
  37. package/skill/MenuItem.md +52 -0
  38. package/skill/MenuOptions.md +25 -0
  39. package/skill/SKILL.md +609 -0
  40. package/skill/SelectOptions.md +21 -0
  41. package/skill/Slot.md +13 -0
  42. package/skill/Tab.md +33 -0
  43. package/skill/TabsOptions.md +28 -0
  44. package/skill/TextareaOptions.md +51 -0
  45. package/skill/TextlineOptions.md +45 -0
  46. package/skill/TextlineType.md +18 -0
  47. package/skill/ToastOptions.md +40 -0
  48. package/skill/TooltipOptions.md +22 -0
  49. package/skill/addContextMenu.md +28 -0
  50. package/skill/addTooltip.md +29 -0
  51. package/skill/alert.md +17 -0
  52. package/skill/autocomplete.md +29 -0
  53. package/skill/box.md +26 -0
  54. package/skill/button.md +31 -0
  55. package/skill/buttonChooser.md +23 -0
  56. package/skill/buttonGroup.md +22 -0
  57. package/skill/checkbox.md +18 -0
  58. package/skill/confirm.md +17 -0
  59. package/skill/dialog.md +28 -0
  60. package/skill/form.md +29 -0
  61. package/skill/getDarkMode.md +12 -0
  62. package/skill/main.md +37 -0
  63. package/skill/menuButton.md +27 -0
  64. package/skill/prompt.md +19 -0
  65. package/skill/select.md +18 -0
  66. package/skill/showFloatingMenu.md +21 -0
  67. package/skill/tabs.md +19 -0
  68. package/skill/textarea.md +17 -0
  69. package/skill/textline.md +20 -0
  70. package/skill/toast.md +19 -0
  71. package/src/components/autocomplete.ts +12 -9
  72. package/src/components/box.ts +15 -10
  73. package/src/components/button.ts +23 -32
  74. package/src/components/buttonChooser.ts +1 -1
  75. package/src/components/buttonGroup.ts +3 -3
  76. package/src/components/dialog.ts +22 -11
  77. package/src/components/field.ts +7 -4
  78. package/src/components/main.ts +47 -16
  79. package/src/components/menu.ts +73 -40
  80. package/src/components/select.ts +1 -1
  81. package/src/components/tabs.ts +3 -3
  82. package/src/components/toast.ts +8 -8
  83. package/src/components/tooltip.ts +4 -3
  84. package/src/core.ts +30 -2
  85. package/src/theme.ts +152 -234
@@ -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`
@@ -0,0 +1,45 @@
1
+ ## TextlineOptions · interface
2
+
3
+ Options for `textline`.
4
+
5
+ ### textlineOptions.type · member
6
+
7
+ Input type. Defaults to `"text"`.
8
+
9
+ **Type:** `TextlineType`
10
+
11
+ ### textlineOptions.placeholder · member
12
+
13
+ Placeholder text.
14
+
15
+ **Type:** `string`
16
+
17
+ ### textlineOptions.bind · member
18
+
19
+ Two-way binding target (e.g. `A.ref($user, "name")`).
20
+
21
+ **Type:** `Bindable<string | number>`
22
+
23
+ ### textlineOptions.value · member
24
+
25
+ Static initial value (use | bind for reactivity).
26
+
27
+ **Type:** `string | number`
28
+
29
+ ### textlineOptions.autocomplete · member
30
+
31
+ Autocomplete hint passed to the native `autocomplete` attribute.
32
+
33
+ **Type:** `string`
34
+
35
+ ### textlineOptions.input · member
36
+
37
+ Fired on every `input` event with the native event.
38
+
39
+ **Type:** `(event: Event) => void`
40
+
41
+ ### textlineOptions.change · member
42
+
43
+ Fired on `change` (commit) with the native event.
44
+
45
+ **Type:** `(event: Event) => void`
@@ -0,0 +1,18 @@
1
+ ## TextlineType · type
2
+
3
+ The `<input>` types `textline` supports. Deliberately excludes types
4
+ that need their own widget (`checkbox`, `radio`, `color`, `range`, `file`,
5
+ `button`, ...) — use the dedicated components for those.
6
+
7
+ **Type:** `| "text"
8
+ | "password"
9
+ | "email"
10
+ | "number"
11
+ | "tel"
12
+ | "url"
13
+ | "search"
14
+ | "date"
15
+ | "time"
16
+ | "datetime-local"
17
+ | "month"
18
+ | "week"`
@@ -0,0 +1,40 @@
1
+ ## ToastOptions · interface
2
+
3
+ Options for `toast`.
4
+
5
+ ### toastOptions.message · member
6
+
7
+ Primary message. A string is rendered as rich text.
8
+
9
+ **Type:** `Slot`
10
+
11
+ ### toastOptions.title · member
12
+
13
+ Optional bold title above the message.
14
+
15
+ **Type:** `Slot`
16
+
17
+ ### toastOptions.type · member
18
+
19
+ Colour role. Defaults to `"neutral"`.
20
+
21
+ **Type:** `"success" | "danger" | "warning" | "neutral"`
22
+
23
+ ### toastOptions.duration · member
24
+
25
+ Auto-dismiss delay in milliseconds. Defaults to `6000`.
26
+ Pass `0` to make the toast persistent until dismissed manually.
27
+
28
+ **Type:** `number`
29
+
30
+ ### toastOptions.dismissible · member
31
+
32
+ Show a close button. Defaults to `true`.
33
+
34
+ **Type:** `boolean`
35
+
36
+ ### toastOptions.attrs · member
37
+
38
+ Aberdeen attr/style string applied to the toast element.
39
+
40
+ **Type:** `string`
@@ -0,0 +1,22 @@
1
+ ## TooltipOptions · interface
2
+
3
+ Options for `addTooltip`.
4
+
5
+ ### tooltipOptions.tip · member
6
+
7
+ The tooltip text or draw function. A string is rendered as rich text.
8
+
9
+ **Type:** `Slot`
10
+
11
+ ### tooltipOptions.placement · member
12
+
13
+ Which side the tooltip appears on. Defaults to `"top"`.
14
+ Automatically flips to the opposite side when there isn't enough room.
15
+
16
+ **Type:** `"left" | "right" | "top" | "bottom"`
17
+
18
+ ### tooltipOptions.attrs · member
19
+
20
+ Aberdeen attr/style string applied to the tip panel.
21
+
22
+ **Type:** `string`
@@ -0,0 +1,28 @@
1
+ ## addContextMenu · function
2
+
3
+ Attaches a context menu to the current element: adds a `contextmenu` handler
4
+ via `A` so a | floating menu opens (instead of
5
+ the browser's own menu) on right-click or long-press. The menu is anchored to
6
+ the element and closes on Escape, Tab, item selection, or any click outside.
7
+
8
+ **Signature:** `(opts: ContextMenuOptions) => void`
9
+
10
+ **Parameters:**
11
+
12
+ - `opts: ContextMenuOptions`
13
+
14
+ **Examples:**
15
+
16
+ ```ts
17
+ import * as icons from "staffa/icons";
18
+
19
+ S.box(() => {
20
+ A("#Right-click / long-tap me!");
21
+ S.addContextMenu({
22
+ items: [
23
+ { label: "AI something", icon: icons.sparkles, click: () => ai() },
24
+ { label: "Launch missiles", icon: icons.rocket, click: () => launch() },
25
+ ],
26
+ });
27
+ });
28
+ ```
@@ -0,0 +1,29 @@
1
+ ## addTooltip · function
2
+
3
+ Attaches a tooltip to the current element: adds hover/focus handlers via
4
+ `A` so the tip appears when the element is hovered or keyboard-focused.
5
+ The tip panel is rendered into `document.body` via a portal, so it is never
6
+ clipped by `overflow:hidden` ancestors. Position is computed from the
7
+ element's bounding rect and automatically flips when near the viewport edge.
8
+
9
+ **Signature:** `(opts: TooltipOptions) => void`
10
+
11
+ **Parameters:**
12
+
13
+ - `opts: TooltipOptions`
14
+
15
+ **Examples:**
16
+
17
+ ```ts
18
+ S.button(() => {
19
+ A("#Save");
20
+ S.addTooltip({ tip: "Saves your work to the cloud" });
21
+ });
22
+
23
+ A(" ");
24
+
25
+ S.button(() => {
26
+ A(".danger #Delete");
27
+ S.addTooltip({ tip: "Dangerous — cannot be undone", placement: "bottom" });
28
+ });
29
+ ```
package/skill/alert.md ADDED
@@ -0,0 +1,17 @@
1
+ ## alert · function
2
+
3
+ Shows a message dialog with a single OK button. Returns a `Promise<void>`
4
+ that resolves when the user dismisses it.
5
+
6
+ **Signature:** `(message: string, opts?: Partial<DialogOptions>) => Promise<void>`
7
+
8
+ **Parameters:**
9
+
10
+ - `message: string`
11
+ - `opts: Partial<DialogOptions>` (optional)
12
+
13
+ **Examples:**
14
+
15
+ ```ts
16
+ await S.alert("File saved successfully.");
17
+ ```
@@ -0,0 +1,29 @@
1
+ ## autocomplete · function
2
+
3
+ A combobox with type-ahead filtering. Supports single or multi-select (chips),
4
+ optional free-text entry, and full keyboard control (arrows, enter, escape,
5
+ backspace-to-remove). Implements the ARIA combobox/listbox pattern.
6
+
7
+ **Signature:** `(opts: AutocompleteOptions) => void`
8
+
9
+ **Parameters:**
10
+
11
+ - `opts: AutocompleteOptions`
12
+
13
+ **Examples:**
14
+
15
+ ```ts
16
+ // Single select from a fixed list
17
+ const $sel = A.proxy("Netherlands");
18
+ S.autocomplete({ label: "Country", options: ["Belgium", "Netherlands"], bind: $sel });
19
+
20
+ // Multi-select, disallowing custom items
21
+ const $tags = A.proxy({value: [] as string[]});
22
+ S.autocomplete({
23
+ label: "Tags",
24
+ multi: true,
25
+ allowCustom: false,
26
+ options: ["Rust", "JS", "C++", "Klingon", "Go"],
27
+ bind: A.ref($tags)
28
+ });
29
+ ```
package/skill/box.md ADDED
@@ -0,0 +1,26 @@
1
+ ## box · function
2
+
3
+ A surface container — the workhorse layout primitive. Has an optional styled
4
+ header and footer, and a padded body that holds `ContentOptions.content`.
5
+
6
+ The body gets default `padding` and matching `gap`; add `display:flex` via
7
+ | contentAttrs if you want its children laid
8
+ out as a flex container.
9
+
10
+ Shortcut: pass a function to use it directly as the body content.
11
+
12
+ **Signature:** `(opts?: BoxOptions | Slot) => void`
13
+
14
+ **Parameters:**
15
+
16
+ - `opts: BoxOptions | Slot` (optional)
17
+
18
+ **Examples:**
19
+
20
+ ```ts
21
+ const $user = A.proxy({name: "Kvothe"});
22
+ S.box({ header: "Profile", contentAttrs: "display:flex flex-direction:column", content: () => {
23
+ S.textline({ label: "Name", bind: A.ref($user, "name") });
24
+ }});
25
+ S.box(() => A("p#Just some content")); // shorthand
26
+ ```
@@ -0,0 +1,31 @@
1
+ ## button · function
2
+
3
+ A button. Tonal and outlined variants show a border; filled variants rely on
4
+ their solid background for affordance.
5
+
6
+ Shortcut: pass a string to use it as the label, or a function for custom
7
+ content.
8
+
9
+ **Tip:** pair `href` with Aberdeen's `interceptLinks()` (called once at app
10
+ startup) for SPA-style navigation without manual click handlers:
11
+ ```ts
12
+ import {interceptLinks} from from "aberdeen/route";
13
+ interceptLinks(); // once at root
14
+ S.button({ href: "/dashboard", content: "Dashboard" }); // navigates via router
15
+ ```
16
+
17
+ **Signature:** `(opts?: Slot | ButtonOptions) => void`
18
+
19
+ **Parameters:**
20
+
21
+ - `opts: ButtonOptions | Slot` (optional)
22
+
23
+ **Examples:**
24
+
25
+ ```ts
26
+ S.button({ content: "Save", click: S.alert("Saved.") });
27
+ S.button({ content: "Cancel", attrs: ".nest", click: cancel }); // neutral button
28
+ S.button({ content: "Delete", attrs: ".danger .outlined", click: del });
29
+ S.button("Cancel"); // shorthand for { content: "Cancel" }
30
+ S.button({ href: "/docs", content: "Docs" }); // renders an <a role=button>
31
+ ```
@@ -0,0 +1,23 @@
1
+ ## buttonChooser · function
2
+
3
+ A single-selection segmented control: an attached button group where exactly
4
+ one button is active at a time. Optionally allows deselecting back to `undefined`.
5
+
6
+ Renders a hidden `<input>` alongside (when `name` is set) so the selected
7
+ value is included in native form submission.
8
+
9
+ **Signature:** `(opts: ButtonChooserOptions) => void`
10
+
11
+ **Parameters:**
12
+
13
+ - `opts: ButtonChooserOptions`
14
+
15
+ **Examples:**
16
+
17
+ ```ts
18
+ const $view = A.proxy({ value: "day" as string | undefined });
19
+ S.buttonChooser({
20
+ options: { day: "Day", week: "Week", month: "Month" },
21
+ bind: $view,
22
+ });
23
+ ```
@@ -0,0 +1,22 @@
1
+ ## buttonGroup · function
2
+
3
+ Groups related buttons, either as a joined segmented control (`attached`) or
4
+ spaced out. A `role=group` is applied for assistive tech.
5
+
6
+ If you want a single button to be *selected*, use `buttonChooser`.
7
+
8
+ **Signature:** `(opts?: ButtonGroupOptions) => void`
9
+
10
+ **Parameters:**
11
+
12
+ - `opts: ButtonGroupOptions` (optional)
13
+
14
+ **Examples:**
15
+
16
+ ```ts
17
+ S.buttonGroup({ buttons: [
18
+ { content: "Day", attrs: ".nest" },
19
+ { content: "Week", attrs: ".nest" },
20
+ { content: "Month", attrs: ".nest" },
21
+ ]});
22
+ ```
@@ -0,0 +1,18 @@
1
+ ## checkbox · function
2
+
3
+ A checkbox with an associated, clickable label. Uses the native `<input
4
+ type=checkbox>` (styled with `accent-color`) for full keyboard and screen
5
+ reader support.
6
+
7
+ **Signature:** `(opts?: CheckboxOptions) => void`
8
+
9
+ **Parameters:**
10
+
11
+ - `opts: CheckboxOptions` (optional)
12
+
13
+ **Examples:**
14
+
15
+ ```ts
16
+ const $prefs = A.proxy({newsletter: true});
17
+ S.checkbox({ label: "Subscribe to newsletter", bind: A.ref($prefs, "newsletter") });
18
+ ```
@@ -0,0 +1,17 @@
1
+ ## confirm · function
2
+
3
+ Shows a confirmation dialog with Cancel and OK buttons. Returns a
4
+ `Promise<boolean>` — `true` if the user clicked OK, `false` otherwise.
5
+
6
+ **Signature:** `(message: string, opts?: Partial<DialogOptions>) => Promise<boolean>`
7
+
8
+ **Parameters:**
9
+
10
+ - `message: string`
11
+ - `opts: Partial<DialogOptions>` (optional)
12
+
13
+ **Examples:**
14
+
15
+ ```ts
16
+ if (await S.confirm("Delete this item?")) S.alert("Gone!");
17
+ ```
@@ -0,0 +1,28 @@
1
+ ## dialog · function
2
+
3
+ A dialog rendered into `document.body` via `A.mount`, with a dimming backdrop
4
+ that fades in and out. Returns a `Promise<void>` that resolves when the dialog
5
+ closes. Lifecycle is also tied to the parent reactive scope — when that scope
6
+ is cleaned up the dialog disappears and the promise resolves.
7
+
8
+ Multiple dialogs stack correctly: each new pair (backdrop + dialog) has a
9
+ higher z-index, while older dialogs are pushed behind their covering backdrop.
10
+
11
+ **Signature:** `(opts: DialogOptions) => Promise<void>`
12
+
13
+ **Parameters:**
14
+
15
+ - `opts: DialogOptions`
16
+
17
+ **Examples:**
18
+
19
+ ```ts
20
+ S.dialog({
21
+ header: "Confirm",
22
+ content: (close) => {
23
+ A("p #Are you sure?");
24
+ S.button({ content: "Yes", click: () => { S.alert("Nice!"); close(); } });
25
+ S.button({ content: "Cancel", attrs: ".nest", click: close });
26
+ },
27
+ });
28
+ ```
package/skill/form.md ADDED
@@ -0,0 +1,29 @@
1
+ ## form · function
2
+
3
+ An opinionated `<form>` wrapper that lays its fields out consistently — a clean
4
+ single column by default, or a responsive grid — and provides a standard
5
+ action bar.
6
+
7
+ Field components (("./textline").textline et al.) drop straight
8
+ in as `ContentOptions.content`. Submission is wired so the browser's
9
+ native validation runs, but the page never reloads.
10
+
11
+ **Signature:** `(opts?: Slot | FormOptions) => void`
12
+
13
+ **Parameters:**
14
+
15
+ - `opts: FormOptions | Slot` (optional)
16
+
17
+ **Examples:**
18
+
19
+ ```ts
20
+ const $user = A.proxy({name: "Darth", email: "d.vader@example.com"});
21
+ S.form({
22
+ submit: () => save(),
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({ content: "Save", type: "submit" }),
28
+ });
29
+ ```
@@ -0,0 +1,12 @@
1
+ ## getDarkMode · function
2
+
3
+ Whether dark mode is currently active. Reactive — read it inside a scope to
4
+ re-run on changes.
5
+
6
+ **Signature:** `(allowAuto?: boolean) => boolean`
7
+
8
+ **Parameters:**
9
+
10
+ - `allowAuto: any` (optional) - - When `true`, returns `undefined` (rather than a boolean) if
11
+ the user is following the OS preference, so a dark/light/auto control can
12
+ tell the three states apart.
package/skill/main.md ADDED
@@ -0,0 +1,37 @@
1
+ ## main · function
2
+
3
+ An application shell that wires up the things almost every app needs: a sticky
4
+ top bar (icon, title, subtitle, action menu), a scrollable content area, and a
5
+ footer. With `MainOptions.maxWidth` the content area is centred and its
6
+ width capped. Add a `nav` to get a responsive sidebar (auto-collapses to a
7
+ menu button below 640 px, or always a button with `navPosition: "button"`).
8
+
9
+ **Signature:** `(opts?: MainOptions) => void`
10
+
11
+ **Parameters:**
12
+
13
+ - `opts: MainOptions` (optional)
14
+
15
+ **Examples:**
16
+
17
+ ```ts
18
+ S.main({
19
+ icon: "✦",
20
+ title: "Staffa Demo",
21
+ maxWidth: "56rem",
22
+ nav: {
23
+ items: [
24
+ { label: "Home", icon: () => A("#🏠"), href: "/" },
25
+ { label: "Settings", href: "/settings" },
26
+ ],
27
+ },
28
+ navPosition: "left",
29
+ menu: () => S.button({ content: "New", attrs: ".small" }),
30
+ content: drawPage,
31
+ footer: "© 2026",
32
+ });
33
+
34
+ function drawPage() {
35
+ S.box({title: "Hello world", content: "Here's you app.."});
36
+ }
37
+ ```
@@ -0,0 +1,27 @@
1
+ ## menuButton · function
2
+
3
+ A button that opens a | floating dropdown menu on
4
+ click. Keyboard navigation: Arrow Up/Down, Home, End; Escape/Tab to close;
5
+ Enter/Space activate the focused item natively.
6
+
7
+ **Tip:** set `href` on items and call `interceptLinks()` once at app startup
8
+ for SPA navigation — active items are highlighted automatically.
9
+
10
+ **Signature:** `(opts: MenuOptions) => void`
11
+
12
+ **Parameters:**
13
+
14
+ - `opts: MenuOptions`
15
+
16
+ **Examples:**
17
+
18
+ ```ts
19
+ S.menuButton({
20
+ button: { content: "Actions", attrs: ".nest" },
21
+ items: [
22
+ { label: "Edit", icon: () => A("#✎"), click: () => edit() },
23
+ { separator: true },
24
+ { label: "Delete", attrs: "fg:$s-danger", click: () => del() },
25
+ ],
26
+ });
27
+ ```
@@ -0,0 +1,19 @@
1
+ ## prompt · function
2
+
3
+ Shows a prompt dialog with a text input. Returns a `Promise<string | null>` —
4
+ the entered string if the user confirmed, or `null` if cancelled.
5
+
6
+ **Signature:** `(message: string, defaultValue?: string, opts?: Partial<DialogOptions>) => Promise<string>`
7
+
8
+ **Parameters:**
9
+
10
+ - `message: string`
11
+ - `defaultValue: any` (optional)
12
+ - `opts: Partial<DialogOptions>` (optional)
13
+
14
+ **Examples:**
15
+
16
+ ```ts
17
+ const name = await S.prompt("Enter your name:", "Alice");
18
+ if (name !== null) S.alert(`Hi ${name}!`);
19
+ ```
@@ -0,0 +1,18 @@
1
+ ## select · function
2
+
3
+ A single-select dropdown backed by a native `<select>` element. Looks like the
4
+ other Staffa inputs but delegates all focus management, keyboard navigation, and
5
+ mobile-native picker behaviour to the browser.
6
+
7
+ **Signature:** `(opts: SelectOptions) => void`
8
+
9
+ **Parameters:**
10
+
11
+ - `opts: SelectOptions`
12
+
13
+ **Examples:**
14
+
15
+ ```ts
16
+ const $sel = A.proxy("Netherlands");
17
+ S.select({ label: "Country", options: ["Belgium", "Netherlands"], bind: $sel });
18
+ ```
@@ -0,0 +1,21 @@
1
+ ## showFloatingMenu · function
2
+
3
+ Open a floating dropdown menu anchored to an element. Portals to
4
+ `document.body` (never clipped), positions itself (flipping up when there's
5
+ no room below), and closes on Escape, Tab, item selection, or any click
6
+ outside the panel and anchor. Returns a `close()` function.
7
+
8
+ Menus are usually opened through `menuButton` or
9
+ `addContextMenu`; reach for this primitive when you need to trigger a
10
+ menu from some other event, anchored to an arbitrary element.
11
+
12
+ **Signature:** `(opts: FloatingMenuOptions) => () => void`
13
+
14
+ **Parameters:**
15
+
16
+ - `opts: FloatingMenuOptions`
17
+
18
+ **Examples:**
19
+
20
+ ```ts
21
+ // An
package/skill/tabs.md ADDED
@@ -0,0 +1,19 @@
1
+ ## tabs · function
2
+
3
+ A tabbed view. Renders an ARIA `tablist` of buttons and a single live panel
4
+ for the selected tab. Supports keyboard navigation (left/right/home/end).
5
+
6
+ **Signature:** `(opts: TabsOptions) => void`
7
+
8
+ **Parameters:**
9
+
10
+ - `opts: TabsOptions`
11
+
12
+ **Examples:**
13
+
14
+ ```ts
15
+ S.tabs({ tabs: [
16
+ { label: "Overview", content: () => A("p#Let me give you an overview..") },
17
+ { label: "Settings", content: () => S.checkbox({label: "I agree to anything", checked: true}) },
18
+ ]});
19
+ ```