@signal9/era-ui 32.0.0 → 33.0.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 (145) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/dev/audit-overlay.svelte +2 -2
  3. package/dist/era-ui.css +1 -1
  4. package/dist/generated-docs/utilities.json +99 -99
  5. package/dist/os/pane.svelte +3 -13
  6. package/dist/styles/index.css +2 -956
  7. package/dist/styles/typography.css +1 -1
  8. package/dist/styles/utilities/geometry.css +188 -0
  9. package/dist/styles/utilities/interaction.css +334 -0
  10. package/dist/styles/utilities/materials.css +39 -0
  11. package/dist/styles/utilities/public.css +391 -0
  12. package/dist/styles/utilities.css +5 -0
  13. package/dist/ui/card/card.svelte +2 -52
  14. package/dist/ui/card/card.svelte.d.ts +0 -43
  15. package/dist/ui/card/variants.d.ts +44 -0
  16. package/dist/ui/card/variants.js +20 -0
  17. package/dist/ui/context-menu/context-menu-checkbox-item.svelte +2 -4
  18. package/dist/ui/context-menu/context-menu-group-heading.svelte +2 -5
  19. package/dist/ui/context-menu/context-menu-item.svelte +2 -8
  20. package/dist/ui/context-menu/context-menu-radio-item.svelte +2 -8
  21. package/dist/ui/context-menu/context-menu-separator.svelte +2 -5
  22. package/dist/ui/context-menu/context-menu-sub-trigger.svelte +2 -8
  23. package/dist/ui/dialog/dialog-header.svelte +1 -1
  24. package/dist/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +2 -4
  25. package/dist/ui/dropdown-menu/dropdown-menu-group-heading.svelte +2 -5
  26. package/dist/ui/dropdown-menu/dropdown-menu-item.svelte +2 -8
  27. package/dist/ui/dropdown-menu/dropdown-menu-radio-item.svelte +2 -8
  28. package/dist/ui/dropdown-menu/dropdown-menu-separator.svelte +2 -5
  29. package/dist/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +2 -8
  30. package/dist/ui/menu-recipes.d.ts +6 -0
  31. package/dist/ui/menu-recipes.js +6 -0
  32. package/dist/ui/menubar/menubar-checkbox-item.svelte +2 -9
  33. package/dist/ui/menubar/menubar-group-heading.svelte +2 -5
  34. package/dist/ui/menubar/menubar-item.svelte +2 -8
  35. package/dist/ui/menubar/menubar-radio-item.svelte +2 -8
  36. package/dist/ui/menubar/menubar-separator.svelte +2 -5
  37. package/dist/ui/menubar/menubar-sub-trigger.svelte +2 -8
  38. package/dist/ui/pane/pane-close.svelte +7 -26
  39. package/dist/ui/video-player/video-player.svelte +8 -8
  40. package/package.json +48 -12
  41. package/dist/docs/badge.md +0 -18
  42. package/dist/docs/bits-ui-audit.md +0 -58
  43. package/dist/docs/button.md +0 -19
  44. package/dist/docs/chip.md +0 -20
  45. package/dist/docs/component-docs-core.d.ts +0 -8
  46. package/dist/docs/component-docs-core.js +0 -73
  47. package/dist/docs/component-docs.d.ts +0 -2
  48. package/dist/docs/component-docs.js +0 -25
  49. package/dist/docs/component-source-scanners.d.ts +0 -18
  50. package/dist/docs/component-source-scanners.js +0 -46
  51. package/dist/docs/consumer-import.d.ts +0 -65
  52. package/dist/docs/consumer-import.js +0 -70
  53. package/dist/docs/css-utilities.d.ts +0 -58
  54. package/dist/docs/css-utilities.js +0 -317
  55. package/dist/docs/extract-props.d.ts +0 -13
  56. package/dist/docs/extract-props.js +0 -324
  57. package/dist/docs/generated-docs.d.ts +0 -6
  58. package/dist/docs/generated-docs.js +0 -30
  59. package/dist/docs/index.d.ts +0 -5
  60. package/dist/docs/index.js +0 -66
  61. package/dist/docs/notes.md +0 -83
  62. package/dist/docs/scroll-area.md +0 -7
  63. package/dist/docs/separator.md +0 -20
  64. package/dist/docs/table.md +0 -35
  65. package/dist/docs/utilities.d.ts +0 -4
  66. package/dist/docs/utilities.js +0 -15
  67. package/dist/generated-docs/accordion.md +0 -57
  68. package/dist/generated-docs/alert-dialog.md +0 -91
  69. package/dist/generated-docs/aspect-ratio.md +0 -17
  70. package/dist/generated-docs/avatar.md +0 -39
  71. package/dist/generated-docs/badge.md +0 -41
  72. package/dist/generated-docs/bar.md +0 -41
  73. package/dist/generated-docs/button-group.md +0 -19
  74. package/dist/generated-docs/button.md +0 -117
  75. package/dist/generated-docs/calendar.md +0 -126
  76. package/dist/generated-docs/card.md +0 -58
  77. package/dist/generated-docs/checkbox.md +0 -42
  78. package/dist/generated-docs/chip.md +0 -61
  79. package/dist/generated-docs/code-block.md +0 -20
  80. package/dist/generated-docs/collapsible.md +0 -30
  81. package/dist/generated-docs/combobox.md +0 -74
  82. package/dist/generated-docs/command-bar.md +0 -3
  83. package/dist/generated-docs/command.md +0 -126
  84. package/dist/generated-docs/context-menu.md +0 -104
  85. package/dist/generated-docs/copy-button.md +0 -29
  86. package/dist/generated-docs/cycle.md +0 -29
  87. package/dist/generated-docs/date-field.md +0 -49
  88. package/dist/generated-docs/date-picker.md +0 -180
  89. package/dist/generated-docs/date-range-field.md +0 -50
  90. package/dist/generated-docs/date-range-picker.md +0 -180
  91. package/dist/generated-docs/dialog.md +0 -94
  92. package/dist/generated-docs/draggable.md +0 -3
  93. package/dist/generated-docs/dropdown-menu.md +0 -104
  94. package/dist/generated-docs/file-upload.md +0 -18
  95. package/dist/generated-docs/getting-started.md +0 -3
  96. package/dist/generated-docs/input.md +0 -23
  97. package/dist/generated-docs/kv.md +0 -20
  98. package/dist/generated-docs/label.md +0 -17
  99. package/dist/generated-docs/link-preview.md +0 -40
  100. package/dist/generated-docs/llm-shell.md +0 -3
  101. package/dist/generated-docs/llms-full.txt +0 -5201
  102. package/dist/generated-docs/llms.txt +0 -138
  103. package/dist/generated-docs/logo.md +0 -24
  104. package/dist/generated-docs/manifest.json +0 -1685
  105. package/dist/generated-docs/measurements.md +0 -3
  106. package/dist/generated-docs/menu.md +0 -11
  107. package/dist/generated-docs/menubar.md +0 -104
  108. package/dist/generated-docs/meter.md +0 -101
  109. package/dist/generated-docs/mode.md +0 -24
  110. package/dist/generated-docs/nav.md +0 -73
  111. package/dist/generated-docs/navigation-menu.md +0 -11
  112. package/dist/generated-docs/notes.md +0 -87
  113. package/dist/generated-docs/os.md +0 -3
  114. package/dist/generated-docs/pagination.md +0 -55
  115. package/dist/generated-docs/pane.md +0 -34
  116. package/dist/generated-docs/pin-input.md +0 -31
  117. package/dist/generated-docs/popover.md +0 -43
  118. package/dist/generated-docs/progress.md +0 -17
  119. package/dist/generated-docs/radio-group.md +0 -31
  120. package/dist/generated-docs/range-calendar.md +0 -11
  121. package/dist/generated-docs/rating-group.md +0 -31
  122. package/dist/generated-docs/scroll-area.md +0 -65
  123. package/dist/generated-docs/select.md +0 -67
  124. package/dist/generated-docs/separator.md +0 -57
  125. package/dist/generated-docs/sheet.md +0 -11
  126. package/dist/generated-docs/skeleton.md +0 -18
  127. package/dist/generated-docs/slider.md +0 -71
  128. package/dist/generated-docs/spacing.md +0 -3
  129. package/dist/generated-docs/step.md +0 -51
  130. package/dist/generated-docs/surfaces.md +0 -3
  131. package/dist/generated-docs/switch.md +0 -18
  132. package/dist/generated-docs/table.md +0 -113
  133. package/dist/generated-docs/tabs.md +0 -48
  134. package/dist/generated-docs/text.md +0 -3
  135. package/dist/generated-docs/time-field.md +0 -49
  136. package/dist/generated-docs/time-range-field.md +0 -50
  137. package/dist/generated-docs/timeline.md +0 -32
  138. package/dist/generated-docs/todo.md +0 -3
  139. package/dist/generated-docs/toggle-group.md +0 -31
  140. package/dist/generated-docs/toggle.md +0 -20
  141. package/dist/generated-docs/toolbar.md +0 -11
  142. package/dist/generated-docs/tooltip.md +0 -40
  143. package/dist/generated-docs/tree.md +0 -36
  144. package/dist/generated-docs/utilities.md +0 -1236
  145. package/dist/generated-docs/video-player.md +0 -73
@@ -1,5 +0,0 @@
1
- import { type ComponentEntry } from '../../routes/registry.js';
2
- export declare const docs: Record<string, string>;
3
- export declare function getDoc(slug: string): string | undefined;
4
- export declare function hasDoc(slug: string): boolean;
5
- export declare function listEntries(): ComponentEntry[];
@@ -1,66 +0,0 @@
1
- import { components, guides } from '../../routes/registry.js';
2
- import { buildComponentDoc } from './component-docs.js';
3
- import { utilitiesDoc } from './utilities.js';
4
- const rootUiIndexSources = import.meta.glob('../ui/index.ts', {
5
- query: '?raw',
6
- import: 'default',
7
- eager: true
8
- });
9
- const markdownModules = import.meta.glob('./*.md', {
10
- query: '?raw',
11
- import: 'default',
12
- eager: true
13
- });
14
- function slugFromPath(path) {
15
- return path.replace(/^\.\//, '').replace(/\.md$/, '');
16
- }
17
- const appendices = Object.fromEntries(Object.entries(markdownModules).map(([path, body]) => [slugFromPath(path), body]));
18
- // The utilities guide has no component source to synthesize from — its body is
19
- // parsed out of the `@utility` doc comments in src/lib/styles instead.
20
- appendices.utilities = [appendices.utilities, utilitiesDoc].filter(Boolean).join('\n\n');
21
- function titleFromSlug(slug) {
22
- return slug
23
- .split('-')
24
- .map((part) => part[0]?.toUpperCase() + part.slice(1))
25
- .join(' ');
26
- }
27
- function inferMissingEntriesFromRootUiIndex() {
28
- const src = Object.values(rootUiIndexSources)[0] ?? '';
29
- const mentioned = new Set();
30
- for (const m of src.matchAll(/from\s+['"]\.\/([^/'"]+)\/index\.js['"]/g)) {
31
- mentioned.add(m[1]);
32
- }
33
- // Provider exports theme tokens/types rather than a renderable component.
34
- mentioned.delete('provider');
35
- const existing = new Set([...guides, ...components].map((entry) => entry.slug));
36
- const fallbackIcon = components[0]?.icon ?? guides[0].icon;
37
- return [...mentioned]
38
- .filter((slug) => !existing.has(slug))
39
- .sort((a, b) => a.localeCompare(b))
40
- .map((slug) => ({
41
- name: titleFromSlug(slug),
42
- slug,
43
- description: `Component docs for ${titleFromSlug(slug)} (auto-discovered from src/lib/ui/index.ts exports).`,
44
- icon: fallbackIcon
45
- }));
46
- }
47
- const inferredEntries = inferMissingEntriesFromRootUiIndex();
48
- const allEntries = [...guides, ...components, ...inferredEntries];
49
- const entriesBySlug = Object.fromEntries(allEntries.map((e) => [e.slug, e]));
50
- // Synthesize every entry at module-init. Hand-authored markdown under
51
- // `src/lib/docs/<slug>.md` (if present) is appended verbatim as additional
52
- // notes — the header, import snippet, and props table always come from the
53
- // component source so the library stays in sync with itself.
54
- export const docs = Object.fromEntries(Object.values(entriesBySlug).map((entry) => [
55
- entry.slug,
56
- buildComponentDoc(entry, appendices[entry.slug])
57
- ]));
58
- export function getDoc(slug) {
59
- return docs[slug];
60
- }
61
- export function hasDoc(slug) {
62
- return slug in docs;
63
- }
64
- export function listEntries() {
65
- return allEntries;
66
- }
@@ -1,83 +0,0 @@
1
- ## Usage
2
-
3
- **Notes is not published.** It lives in `src/apps/` in the era-ui repository,
4
- outside the packaged `src/lib`, so there is no import path that reaches it — the
5
- `@signal9/era-ui/apps` subpath was removed in v13.
6
-
7
- A design system that also ships a note-taking application is two products in one
8
- package: Notes alone brings fifteen TipTap packages, and its release cadence and
9
- support expectations are nothing like a primitive's. It stays in the repo as a
10
- reference implementation and a demo — read it, copy it, or lift it into the
11
- product that renders it.
12
-
13
- What era DOES publish is the part that generalises: `@signal9/era-ui/styles/prose`
14
- is the document typography Notes uses, available to anyone building an editor.
15
-
16
- Read as a reference, the integration is: a sidebar with filter, pin, and delete; a TipTap
17
- document with a `/` command menu and a selection toolbar; and persistence to
18
- `localStorage` under `era-ui:notes`.
19
-
20
- ## Peer dependencies
21
-
22
- Install alongside the library (they are not bundled):
23
-
24
- ```
25
- @tiptap/core @tiptap/pm @tiptap/starter-kit @tiptap/suggestion
26
- @tiptap/extension-code-block-lowlight @tiptap/extension-details
27
- @tiptap/extension-highlight @tiptap/extension-image
28
- @tiptap/extension-placeholder @tiptap/extension-table
29
- @tiptap/extension-task-item @tiptap/extension-task-list
30
- @tiptap/extension-typography @tiptap/extension-unique-id
31
- lowlight tiptap-markdown
32
- ```
33
-
34
- ## Props
35
-
36
- | Prop | Type | Default | Notes |
37
- | ------------ | ---------------- | ------------------ | ----------------------------------------------------------------- |
38
- | `store` | `NotesStore` | created internally | Bring your own; when set, the host owns its lifecycle. |
39
- | `adapter` | `NotesAdapter` | `localStorage` | Persistence for the internally-created store. |
40
- | `storageKey` | `string` | `era-ui:notes` | Key for the default adapter. |
41
- | `noteId` | `string \| null` | `null` | `$bindable` — the open note, for deep-linking or session restore. |
42
- | `seed` | `NoteInit[]` | — | Created only when storage comes back empty (first-run sample). |
43
-
44
- ## Persistence
45
-
46
- Persistence is one small interface, so server-backed hosting is a drop-in swap —
47
- `load`/`save` may be sync or async:
48
-
49
- ```ts
50
- import { Notes, NotesStore } from '$apps/index.js'; // in-repo; not published
51
-
52
- const store = new NotesStore({
53
- adapter: {
54
- load: () => fetch('/api/notes').then((r) => r.json()),
55
- save: (notes) => fetch('/api/notes', { method: 'PUT', body: JSON.stringify(notes) })
56
- }
57
- });
58
- ```
59
-
60
- `NotesStore` is the reactive source of truth (`notes`, `ordered`, `loading`,
61
- `status`, `lastError`) with `create` / `update` / `remove` / `togglePin` /
62
- `setIcon` / `search` / `toMarkdown` / `flush`. Writes are debounced and
63
- coalesced, so a burst of keystrokes costs one `save`.
64
-
65
- ## The heading index
66
-
67
- Every document is also a tree. `buildGlobalTree()` walks heading structure,
68
- `treeToText()` renders it as a table of contents a model can read, and
69
- `extractSection(title, doc, headingId)` returns just the requested slice as
70
- structure-preserving markdown — reasoning-based retrieval rather than
71
- embeddings. Heading ids are stable (`@tiptap/extension-unique-id`), so a section
72
- address survives edits above it.
73
-
74
- ## Notes
75
-
76
- - Keyboard: `/` opens the command menu, `Mod-K` links a selection, `Mod-S`
77
- flushes pending writes immediately.
78
- - The slash menu and selection toolbar are real Svelte components mounted into
79
- the document root, so they follow every axis — density tiers, surface chrome,
80
- corners, motion, font — instead of carrying their own hardcoded styling.
81
- - `@tiptap/extension-mathematics` is deliberately absent: it needs KaTeX's
82
- stylesheet and fonts to render. Spread `noteExtensions` and add it yourself if
83
- you want math.
@@ -1,7 +0,0 @@
1
- ## Notes
2
-
3
- - For a region that should scroll but show no scrollbar at all — an overflowing
4
- tab strip, a chip rail, a small pane handle — you don't need ScrollArea: put
5
- the `scrollbar-none` CSS utility on the overflowing element. See
6
- [Utilities](/utilities.md). ScrollArea is for the case where the bar itself is
7
- part of the design.
@@ -1,20 +0,0 @@
1
- ## Usage
2
-
3
- ```svelte
4
- <script>
5
- import { Separator } from '@signal9/era-ui/separator';
6
- </script>
7
-
8
- <p>
9
- era
10
- <Separator variant="slant" decorative />
11
- ui
12
- <Separator variant="slant" decorative />
13
- separator
14
- </p>
15
- ```
16
-
17
- ## Notes
18
-
19
- - `variant="slant"` is for inline text separators only, such as breadcrumbs, compact metadata, and split titles.
20
- - Mark slant separators `decorative` unless they communicate a meaningful boundary to assistive technology.
@@ -1,35 +0,0 @@
1
- ## Usage
2
-
3
- ```svelte
4
- <script lang="ts">
5
- import { Table } from '@signal9/era-ui/table';
6
-
7
- const rows = [
8
- { id: 1, name: 'Ada', role: 'Engineer' },
9
- { id: 2, name: 'Grace', role: 'Designer' }
10
- ];
11
- </script>
12
-
13
- <Table.Root>
14
- <Table.Head>
15
- <Table.Row>
16
- <Table.HeadCell>Name</Table.HeadCell>
17
- <Table.HeadCell>Role</Table.HeadCell>
18
- </Table.Row>
19
- </Table.Head>
20
- <Table.Body>
21
- {#each rows as row (row.id)}
22
- <Table.Row>
23
- <Table.Cell>{row.name}</Table.Cell>
24
- <Table.Cell>{row.role}</Table.Cell>
25
- </Table.Row>
26
- {/each}
27
- </Table.Body>
28
- </Table.Root>
29
- ```
30
-
31
- ## Notes
32
-
33
- - Composition-first API (like `Table.Row`), not a single data-driven component — keeps layout decisions local to the call site.
34
- - All parts pass through `class` and standard HTML attrs.
35
- - Density tokens drive row height and cell padding.
@@ -1,4 +0,0 @@
1
- import { type CssUtility } from './css-utilities.js';
2
- export declare const utilities: CssUtility[];
3
- export declare const utilitiesDoc: string;
4
- export type { CssUtility };
@@ -1,15 +0,0 @@
1
- /*
2
- * Runtime side of the CSS-utility docs: globs the shipped stylesheets and parses
3
- * their `@utility` blocks. The node build script (scripts/build-llm-docs.ts)
4
- * feeds the same parser from the filesystem, so the site and the generated
5
- * markdown can never disagree about what era exposes.
6
- */
7
- import { buildUtilitiesDoc, parseUtilities } from './css-utilities.js';
8
- const cssSources = import.meta.glob('../styles/**/*.css', {
9
- query: '?raw',
10
- import: 'default',
11
- eager: true
12
- });
13
- const sources = Object.fromEntries(Object.entries(cssSources).map(([path, body]) => [path.replace(/^\.\.\/styles\//, ''), body]));
14
- export const utilities = parseUtilities(sources);
15
- export const utilitiesDoc = buildUtilitiesDoc(utilities);
@@ -1,57 +0,0 @@
1
- # Accordion
2
-
3
- Collapsible content sections.
4
-
5
- ## Import
6
-
7
- ```ts
8
- import * as Accordion from "@signal9/era-ui/accordion";
9
- ```
10
-
11
- Composed from sub-components — compose explicitly at the call site:
12
-
13
- - `Accordion.Root`
14
- - `Accordion.Item`
15
- - `Accordion.Header`
16
- - `Accordion.Trigger`
17
- - `Accordion.Content`
18
-
19
- ## Accordion.Root
20
-
21
- Inherits all props from `Accordion.RootProps`.
22
-
23
- | Prop | Type | Default | Notes |
24
- |------|------|---------|-------|
25
- | `ref?` | `(forwarded)` | `null` | bindable |
26
-
27
- ## Accordion.Item
28
-
29
- Inherits all props from `Accordion.ItemProps`.
30
-
31
- | Prop | Type | Default | Notes |
32
- |------|------|---------|-------|
33
- | `ref?` | `(forwarded)` | `null` | bindable |
34
-
35
- ## Accordion.Header
36
-
37
- Inherits all props from `Accordion.HeaderProps`.
38
-
39
- | Prop | Type | Default | Notes |
40
- |------|------|---------|-------|
41
- | `ref?` | `(forwarded)` | `null` | bindable |
42
-
43
- ## Accordion.Trigger
44
-
45
- Inherits all props from `OwnedPartProps<Accordion.TriggerProps>`.
46
-
47
- | Prop | Type | Default | Notes |
48
- |------|------|---------|-------|
49
- | `ref?` | `(forwarded)` | `null` | bindable |
50
-
51
- ## Accordion.Content
52
-
53
- Inherits all props from `Accordion.ContentProps`.
54
-
55
- | Prop | Type | Default | Notes |
56
- |------|------|---------|-------|
57
- | `ref?` | `(forwarded)` | `null` | bindable |
@@ -1,91 +0,0 @@
1
- # Alert Dialog
2
-
3
- A modal confirmation before destructive actions.
4
-
5
- ## Import
6
-
7
- ```ts
8
- import * as AlertDialog from "@signal9/era-ui/alert-dialog";
9
- ```
10
-
11
- Composed from sub-components — compose explicitly at the call site:
12
-
13
- - `AlertDialog.Root`
14
- - `AlertDialog.Trigger`
15
- - `AlertDialog.Content`
16
- - `AlertDialog.Overlay`
17
- - `AlertDialog.Title`
18
- - `AlertDialog.Description`
19
- - `AlertDialog.Cancel`
20
- - `AlertDialog.Action`
21
-
22
- ## AlertDialog.Root
23
-
24
- Inherits all props from `AlertDialog.RootProps`.
25
-
26
- | Prop | Type | Default | Notes |
27
- |------|------|---------|-------|
28
- | `children?` | `Snippet` | — | — |
29
- | `open?` | `(forwarded)` | `false` | bindable |
30
-
31
- ## AlertDialog.Trigger
32
-
33
- Inherits all props from `WithoutChildrenOrChild<AlertDialog.TriggerProps>`.
34
- Inherits all props from `ButtonVariants`.
35
-
36
- | Prop | Type | Default | Notes |
37
- |------|------|---------|-------|
38
- | `children?` | `Snippet` | — | — |
39
- | `ref?` | `(forwarded)` | `null` | bindable |
40
-
41
- ## AlertDialog.Content
42
-
43
- Inherits all props from `OwnedPartProps<AlertDialog.ContentProps>`.
44
-
45
- | Prop | Type | Default | Notes |
46
- |------|------|---------|-------|
47
- | `ref?` | `(forwarded)` | `null` | bindable |
48
-
49
- ## AlertDialog.Overlay
50
-
51
- Inherits all props from `AlertDialog.OverlayProps`.
52
-
53
- | Prop | Type | Default | Notes |
54
- |------|------|---------|-------|
55
- | `ref?` | `(forwarded)` | `null` | bindable |
56
-
57
- ## AlertDialog.Title
58
-
59
- Inherits all props from `AlertDialog.TitleProps`.
60
-
61
- | Prop | Type | Default | Notes |
62
- |------|------|---------|-------|
63
- | `ref?` | `(forwarded)` | `null` | bindable |
64
-
65
- ## AlertDialog.Description
66
-
67
- Inherits all props from `AlertDialog.DescriptionProps`.
68
-
69
- | Prop | Type | Default | Notes |
70
- |------|------|---------|-------|
71
- | `ref?` | `(forwarded)` | `null` | bindable |
72
-
73
- ## AlertDialog.Cancel
74
-
75
- Inherits all props from `WithoutChildrenOrChild<AlertDialog.CancelProps>`.
76
- Inherits all props from `Omit<ButtonVariants, 'active'>`.
77
-
78
- | Prop | Type | Default | Notes |
79
- |------|------|---------|-------|
80
- | `children?` | `Snippet` | — | — |
81
- | `ref?` | `(forwarded)` | `null` | bindable |
82
-
83
- ## AlertDialog.Action
84
-
85
- Inherits all props from `WithoutChildrenOrChild<AlertDialog.ActionProps>`.
86
- Inherits all props from `Omit<ButtonVariants, 'active'>`.
87
-
88
- | Prop | Type | Default | Notes |
89
- |------|------|---------|-------|
90
- | `children?` | `Snippet` | — | — |
91
- | `ref?` | `(forwarded)` | `null` | bindable |
@@ -1,17 +0,0 @@
1
- # Aspect Ratio
2
-
3
- Maintains a specified aspect ratio for content.
4
-
5
- ## Import
6
-
7
- ```ts
8
- import { AspectRatio } from "@signal9/era-ui/aspect-ratio";
9
- ```
10
-
11
- ## Props
12
-
13
- Inherits all props from `PartProps<AspectRatio.RootProps>`.
14
-
15
- | Prop | Type | Default | Notes |
16
- |------|------|---------|-------|
17
- | `ref?` | `(forwarded)` | `null` | bindable |
@@ -1,39 +0,0 @@
1
- # Avatar
2
-
3
- An image with optional initials/icon fallback.
4
-
5
- ## Import
6
-
7
- ```ts
8
- import * as Avatar from "@signal9/era-ui/avatar";
9
- ```
10
-
11
- Composed from sub-components — compose explicitly at the call site:
12
-
13
- - `Avatar.Root`
14
- - `Avatar.Image`
15
- - `Avatar.Fallback`
16
-
17
- ## Avatar.Root
18
-
19
- Inherits all props from `PartProps<Avatar.RootProps>`.
20
-
21
- | Prop | Type | Default | Notes |
22
- |------|------|---------|-------|
23
- | `ref?` | `(forwarded)` | `null` | bindable |
24
-
25
- ## Avatar.Image
26
-
27
- Inherits all props from `Avatar.ImageProps`.
28
-
29
- | Prop | Type | Default | Notes |
30
- |------|------|---------|-------|
31
- | `ref?` | `(forwarded)` | `null` | bindable |
32
-
33
- ## Avatar.Fallback
34
-
35
- Inherits all props from `PartProps<Avatar.FallbackProps>`.
36
-
37
- | Prop | Type | Default | Notes |
38
- |------|------|---------|-------|
39
- | `ref?` | `(forwarded)` | `null` | bindable |
@@ -1,41 +0,0 @@
1
- # Badge
2
-
3
- A small label for status or categorization.
4
-
5
- ## Import
6
-
7
- ```ts
8
- import { Badge } from "@signal9/era-ui/badge";
9
- ```
10
-
11
- ## Props
12
-
13
- Inherits all props from `HTMLAttributes<HTMLSpanElement>`.
14
-
15
- | Prop | Type | Default | Notes |
16
- |------|------|---------|-------|
17
- | `ref?` | `HTMLSpanElement \| null` | `null` | bindable |
18
- | `tone?` | `'default' \| 'accent' \| 'destructive' \| 'success' \| 'warning' \| 'info'` | `'default'` | — |
19
- | `lead?` | `Snippet` | — | Icon rendered BEFORE the label, outside it. Use this rather than putting
20
- an icon in `children`: the label then gets its own box, which is the only
21
- place era's ink centring can reach. |
22
- | `children?` | `Snippet` | — | — |
23
-
24
- ## Usage
25
-
26
- ```svelte
27
- <script>
28
- import { Badge } from '@signal9/era-ui/badge';
29
- </script>
30
-
31
- <Badge>draft</Badge>
32
- <Badge tone="accent">new</Badge>
33
- <Badge tone="success">passing</Badge>
34
- <Badge tone="destructive">failing</Badge>
35
- ```
36
-
37
- ## Notes
38
-
39
- - Non-interactive. For dismissible tokens use `Chip`. For labelled pairs use `KV`.
40
- - Uses the `xxs` tier tokens (height, radius, inset).
41
- - Inter-icon gap tightens to `--era-inset-pill` when an SVG is present.
@@ -1,41 +0,0 @@
1
- # Bar
2
-
3
- A flex container for toolbars and headers, in three heights.
4
-
5
- ## Import
6
-
7
- ```ts
8
- import { Bar } from "@signal9/era-ui/bar";
9
- ```
10
-
11
- ## Props
12
-
13
- Inherits all props from `HTMLAttributes<HTMLDivElement>`.
14
-
15
- | Prop | Type | Default | Notes |
16
- |------|------|---------|-------|
17
- | `ref?` | `HTMLDivElement \| null` | `null` | bindable |
18
- | `size?` | `'chip' \| 'control' \| 'bar'` | `'bar'` | Height tier (scales with density). Default `lg` — a full toolbar. |
19
- | `content?` | `BarContent` | — | Tier of the controls inside — drives the bar's padding and gap so they
20
- stay concentric to them. Omit this for the next canonical rung, or name
21
- the actual tier when the contents are smaller. |
22
- | `divider?` | `boolean` | `false` | The flush cap-a-panel chrome: an outset rule below, and a rounded
23
- BOTTOM only — the top defers to the panel's own radius.
24
- THE BOTTOM RADIUS IS LOAD-BEARING FOR THE RULE. The divider is an
25
- outset `box-shadow`, so it follows the box's corners: the rounded
26
- bottom is what curves the line up at the ends and makes the bar read
27
- as a long pill. Overriding the radius therefore changes the RULE, not
28
- just the corners. Measured against `cn`:
29
- - `rounded-none` drops both — a square bar with a dead-straight rule.
30
- That is the intended square mode (an in-app Notes bar passes it).
31
- - `rounded-b-*` or `rounded-b-none` replaces the curve — this is the
32
- one that surprises, because the rule changes shape when the caller
33
- thought they were only squaring a corner.
34
- - `rounded-t-*` is SAFE: it wins against `rounded-t-none` and leaves
35
- `rounded-b-control` standing, so the curve survives.
36
- A consumer lost the curve this way. The coupling was already written
37
- down — on the variant, inside `<script module>`, where someone
38
- hovering this prop never reaches it. Docs are only as good as the
39
- place the reader is standing. |
40
- | `topology?` | `'nested' \| 'docked'` | `'nested'` | `docked` removes one or more exposed curves; strict radius nesting does not apply. |
41
- | `children?` | `Snippet` | — | — |
@@ -1,19 +0,0 @@
1
- # Button Group
2
-
3
- Groups buttons with consistent spacing.
4
-
5
- ## Import
6
-
7
- ```ts
8
- import { ButtonGroup } from "@signal9/era-ui/button-group";
9
- ```
10
-
11
- ## Props
12
-
13
- Inherits all props from `HTMLAttributes<HTMLDivElement>`.
14
-
15
- | Prop | Type | Default | Notes |
16
- |------|------|---------|-------|
17
- | `ref?` | `HTMLDivElement \| null` | `null` | bindable |
18
- | `children?` | `Snippet` | — | — |
19
- | `orientation?` | `'horizontal' \| 'vertical'` | `'horizontal'` | — |
@@ -1,117 +0,0 @@
1
- # Button
2
-
3
- A flexible button or link element.
4
-
5
- ## Import
6
-
7
- ```ts
8
- import { Button } from "@signal9/era-ui/button";
9
- ```
10
-
11
- ## Props
12
-
13
- Inherits all props from `Button.RootProps`.
14
-
15
- | Prop | Type | Default | Notes |
16
- |------|------|---------|-------|
17
- | `tone?` | `'default' \| 'accent' \| 'destructive' \| 'success' \| 'warning' \| 'info'` | `'default'` | — |
18
- | `size?` | `'control' \| 'chip' \| 'pill' \| 'icon'` | `'control'` | — |
19
- | `variant?` | `'filled' \| 'link'` | `'filled'` | — |
20
- | `active?` | `boolean` | `false` | — |
21
- | `icon?` | `boolean` | `false` | — |
22
- | `loading?` | `boolean` | `false` | In flight: disables the button, sets `aria-busy`, and puts a spinner
23
- over the label.
24
- THE GEOMETRY DOES NOT MOVE. That is the requirement, not a detail. A
25
- button is loading because it was just CLICKED, so anything `loading`
26
- changes about the box moves the page under the pointer that is still
27
- on it — and a spinner PREPENDED to the label (what this used to do)
28
- costs an icon's width plus a gap, measured on a wrapping header row
29
- that reflowed everything beside it. A consumer hit exactly that and
30
- stopped using the prop, hand-rolling `disabled` + `aria-busy`
31
- instead, which is the report that produced this note.
32
- So the spinner is absolutely positioned and takes no part in the
33
- flex layout, and the label goes to `opacity-0` rather than being
34
- unmounted: the box that holds the width stays, and the text stays in
35
- the accessibility tree as the button's accessible name.
36
- The visible label is therefore HIDDEN in flight — the one thing this
37
- trades away, and the reason `loadingLabel` exists.
38
- IF YOU DO NOT WANT A SPINNER, use `busy`. Not showing one is a
39
- supported posture, not a legacy one — see that prop. |
40
- | `busy?` | `boolean` | `false` | In flight, WITHOUT a spinner: disables the button and sets `aria-busy`,
41
- and changes nothing else. The label stays visible and legible.
42
- This exists because "show a spinner" is a taste, not a requirement,
43
- and era had only one answer. A consumer whose house style is that
44
- spinners should not appear had to spell the posture out themselves —
45
- `disabled` plus a restated `aria-busy` — and rely on knowing that
46
- `restProps` spreads last, which is a real fact about this component
47
- that no reader should have to depend on. Two words for two postures
48
- is clearer than one word plus a workaround.
49
- `loading` implies this: it is `busy` plus the spinner and the hidden
50
- label. What you get from `busy` alone is a control that is visibly
51
- disabled (the era-interactive opacity) and announced as busy, with
52
- its geometry and its ink untouched — which is also why it needs no
53
- `loadingLabel`: nothing about the button changed except that you
54
- cannot press it.
55
- Reported by a consumer whose user asked for no spinners anywhere.
56
- They were right that a fix for the width shift did not answer it: a
57
- spinner that no longer moves its neighbours is still a spinner. |
58
- | `loadingLabel?` | `string` | — | Screen-reader-only label announced while `loading` is true. |
59
- | `lead?` | `Snippet` | — | Icon rendered BEFORE the label, outside it. Use this rather than putting
60
- an icon in `children`: the label then gets its own box, which is the only
61
- place era's ink centring can reach (see era-label-ink). |
62
- | `trail?` | `Snippet` | — | Icon rendered AFTER the label, outside it. Same reason as `lead`. |
63
- | `caps?` | `boolean` | `false` | Trim this label to the CAP band instead of the x-height band — for a
64
- label whose ink runs cap-to-baseline: "PDF", "CSV", "OK", "API".
65
- THE NAME SAYS CAPS AND THE MECHANISM IS DESCENDERS. Worth knowing before
66
- you reach for it, because it decides where it helps. A controlled A/B on
67
- one real button — same element, same classes, only the STRING changing —
68
- says case is not the variable at all:
69
- Save asc 9 desc 0 ink 1.28px high
70
- SAVE asc 9 desc 0 ink 1.28px high ← identical to "Save"
71
- Savg asc 9 desc 3 ink 0.22px low
72
- savg asc 7 desc 3 ink 1.22px low
73
- The ex band runs x-height to baseline, so ink above the x-height pulls
74
- the visual centre up and ink below the baseline pushes it back down;
75
- (xh − asc + desc)/2 predicts every row within 0.3px. A caps string is
76
- simply one that always has an ascender and never a descender, which is
77
- why the cap band boxes it exactly. "Save" has the same offset and this
78
- prop would fix it too. Measured by signalnine.org and reproduced here.
79
- WHAT IT COSTS, and why it is not the default. A fixed band gives every
80
- label the SAME baseline whatever it contains — measured spread across
81
- Save/Savg/save/savg/SAVE/PDF/Cancel/"Copy page" is 0.00px. Changing one
82
- label's band moves that label alone: in a Bar holding bold/italic/PDF/
83
- publish, the caps label sits 1.06px below the other three. So this trades
84
- a uniform offset the eye cannot see for a local misalignment it can, and
85
- it is the right trade only when the label has no neighbour to align with
86
- — a lone action, a label paired with an icon (the reported case, where
87
- the comparison is against an optically-centred glyph rather than against
88
- other text). Beside other labels in a bar, prefer leaving it off.
89
- A PROP because nothing can infer it: `text-transform: uppercase` is a
90
- different question (a label typed "PDF" carries no transform), and a
91
- snippet's text cannot be read before it renders.
92
- Only reaches the label when `lead`/`trail` give it its own box. Without
93
- one the label is an anonymous flex item that no selector can address,
94
- which is the whole reason those snippets exist. |
95
- | `topology?` | `'bounded' \| 'docked'` | `'bounded'` | `docked` joins this control to a neighbour and removes one or more curves. |
96
- | `children?` | `Snippet` | — | — |
97
- | `ref?` | `(forwarded)` | `null` | bindable |
98
-
99
- ## Usage
100
-
101
- ```svelte
102
- <script>
103
- import { Button } from '@signal9/era-ui/button';
104
- </script>
105
-
106
- <Button onclick={() => console.log('clicked')}>Save</Button>
107
- <Button tone="accent" size="chip">Confirm</Button>
108
- <Button tone="destructive" variant="link">Delete</Button>
109
- <Button icon size="icon" aria-label="Close"><X /></Button>
110
- ```
111
-
112
- ## Notes
113
-
114
- - Heights, radii, paddings, and gaps come from density tokens — never hard-code px.
115
- - `link` variant intentionally does not change color on hover (underline only) so it reads as static prose until confirmed interactive.
116
- - `variant="link"` is for a _control_ that should look like a link (a button that reveals a panel, a destructive action in a row). For a link in body copy or prose, use the `era-link` CSS utility on an `<a>` instead — see [Utilities](/utilities.md).
117
- - For a segmented row of buttons, use `ButtonGroup`.