@pithyjs/pidl-catalog 0.1.0-beta.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.
- package/LICENSE +21 -0
- package/dist/specs/atoms/actions/button.pidl.json +289 -0
- package/dist/specs/atoms/actions/icon-group.pidl.json +141 -0
- package/dist/specs/atoms/actions/segmented-control.pidl.json +137 -0
- package/dist/specs/atoms/content/action-tile.pidl.json +135 -0
- package/dist/specs/atoms/content/badge.pidl.json +189 -0
- package/dist/specs/atoms/content/callout.pidl.json +170 -0
- package/dist/specs/atoms/content/code-block.pidl.json +170 -0
- package/dist/specs/atoms/content/heading.pidl.json +175 -0
- package/dist/specs/atoms/content/icon.pidl.json +127 -0
- package/dist/specs/atoms/content/image.pidl.json +227 -0
- package/dist/specs/atoms/content/prose.pidl.json +183 -0
- package/dist/specs/atoms/content/stat.pidl.json +158 -0
- package/dist/specs/atoms/content/tabs.pidl.json +207 -0
- package/dist/specs/atoms/content/text.pidl.json +212 -0
- package/dist/specs/atoms/content/tile.pidl.json +156 -0
- package/dist/specs/atoms/data/donut.pidl.json +352 -0
- package/dist/specs/atoms/data/gauge.pidl.json +274 -0
- package/dist/specs/atoms/forms/checkbox-group.pidl.json +170 -0
- package/dist/specs/atoms/forms/checkbox.pidl.json +323 -0
- package/dist/specs/atoms/forms/file-picker.pidl.json +161 -0
- package/dist/specs/atoms/forms/form-field.pidl.json +106 -0
- package/dist/specs/atoms/forms/input.pidl.json +466 -0
- package/dist/specs/atoms/forms/radio-group.pidl.json +174 -0
- package/dist/specs/atoms/forms/radio.pidl.json +312 -0
- package/dist/specs/atoms/forms/search-input.pidl.json +265 -0
- package/dist/specs/atoms/forms/select.pidl.json +420 -0
- package/dist/specs/atoms/forms/textarea.pidl.json +422 -0
- package/dist/specs/atoms/forms/toggle.pidl.json +314 -0
- package/dist/specs/layout/grid-item.pidl.json +120 -0
- package/dist/specs/layout/grid.pidl.json +157 -0
- package/dist/specs/layout/page-section.pidl.json +105 -0
- package/dist/specs/layout/smart-container.pidl.json +148 -0
- package/dist/specs/layout/stack.pidl.json +144 -0
- package/dist/specs/organisms/content/accordion.pidl.json +196 -0
- package/dist/specs/organisms/content/card.pidl.json +283 -0
- package/dist/specs/organisms/feedback/alert-dialog.pidl.json +158 -0
- package/dist/specs/organisms/feedback/modal.pidl.json +133 -0
- package/dist/specs/organisms/feedback/toast.pidl.json +150 -0
- package/dist/specs/organisms/forms/dynamic-form.pidl.json +314 -0
- package/dist/specs/organisms/forms/form.pidl.json +135 -0
- package/dist/specs/organisms/forms/subscribe-form.pidl.json +188 -0
- package/dist/specs/organisms/navigation/command-palette.pidl.json +263 -0
- package/dist/specs/organisms/navigation/docs-sidebar.pidl.json +264 -0
- package/dist/specs/organisms/navigation/navbar.pidl.json +356 -0
- package/dist/specs/organisms/navigation/table-of-contents.pidl.json +197 -0
- package/dist/specs/sections/contact-section.pidl.json +183 -0
- package/dist/specs/sections/cta-section.pidl.json +168 -0
- package/dist/specs/sections/faq-section.pidl.json +202 -0
- package/dist/specs/sections/features-section.pidl.json +214 -0
- package/dist/specs/sections/footer-section.pidl.json +187 -0
- package/dist/specs/sections/hero-section.pidl.json +202 -0
- package/dist/src/borders-psychology.d.ts +17 -0
- package/dist/src/borders-psychology.d.ts.map +1 -0
- package/dist/src/borders-psychology.js +42 -0
- package/dist/src/borders-psychology.js.map +1 -0
- package/dist/src/color-psychology.d.ts +20 -0
- package/dist/src/color-psychology.d.ts.map +1 -0
- package/dist/src/color-psychology.js +57 -0
- package/dist/src/color-psychology.js.map +1 -0
- package/dist/src/design-intelligence.d.ts +13 -0
- package/dist/src/design-intelligence.d.ts.map +1 -0
- package/dist/src/design-intelligence.js +36 -0
- package/dist/src/design-intelligence.js.map +1 -0
- package/dist/src/index.d.ts +6238 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +105 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/motion-psychology.d.ts +19 -0
- package/dist/src/motion-psychology.d.ts.map +1 -0
- package/dist/src/motion-psychology.js +47 -0
- package/dist/src/motion-psychology.js.map +1 -0
- package/dist/src/mutation-vocabulary.d.ts +13 -0
- package/dist/src/mutation-vocabulary.d.ts.map +1 -0
- package/dist/src/mutation-vocabulary.js +67 -0
- package/dist/src/mutation-vocabulary.js.map +1 -0
- package/dist/src/radius-psychology.d.ts +17 -0
- package/dist/src/radius-psychology.d.ts.map +1 -0
- package/dist/src/radius-psychology.js +42 -0
- package/dist/src/radius-psychology.js.map +1 -0
- package/dist/src/shadows-psychology.d.ts +17 -0
- package/dist/src/shadows-psychology.d.ts.map +1 -0
- package/dist/src/shadows-psychology.js +44 -0
- package/dist/src/shadows-psychology.js.map +1 -0
- package/dist/src/spacing-psychology.d.ts +22 -0
- package/dist/src/spacing-psychology.d.ts.map +1 -0
- package/dist/src/spacing-psychology.js +59 -0
- package/dist/src/spacing-psychology.js.map +1 -0
- package/dist/src/typography-psychology.d.ts +22 -0
- package/dist/src/typography-psychology.d.ts.map +1 -0
- package/dist/src/typography-psychology.js +68 -0
- package/dist/src/typography-psychology.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "component",
|
|
3
|
+
"id": "ui.action-tile",
|
|
4
|
+
"name": "ActionTile",
|
|
5
|
+
"displayName": "Action Tile",
|
|
6
|
+
"version": "0.1.0",
|
|
7
|
+
"level": "atom",
|
|
8
|
+
"domain": "content",
|
|
9
|
+
"bidi": true,
|
|
10
|
+
"description": "Full-width actionable row with a leading icon/glyph slot beside a bold title and a muted description. Renders a <button>. Used for choice lists — publish tiers, export options, setup steps.",
|
|
11
|
+
"props": [
|
|
12
|
+
{
|
|
13
|
+
"name": "title",
|
|
14
|
+
"label": "Title",
|
|
15
|
+
"type": "string",
|
|
16
|
+
"required": true,
|
|
17
|
+
"placeholder": "Share Preview",
|
|
18
|
+
"description": "Bold primary line. Combined with the description to form the default accessible name."
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "description",
|
|
22
|
+
"label": "Description",
|
|
23
|
+
"type": "string",
|
|
24
|
+
"required": false,
|
|
25
|
+
"placeholder": "One self-contained HTML file",
|
|
26
|
+
"description": "Muted secondary line describing the action."
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "loading",
|
|
30
|
+
"label": "Loading",
|
|
31
|
+
"type": "boolean | () => boolean",
|
|
32
|
+
"reactive": true,
|
|
33
|
+
"default": false,
|
|
34
|
+
"description": "Loading state — sets aria-busy, shows a spinner in the media slot, and blocks clicks. Accepts a static boolean or a () => boolean accessor."
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "disabled",
|
|
38
|
+
"label": "Disabled",
|
|
39
|
+
"type": "boolean | () => boolean",
|
|
40
|
+
"reactive": true,
|
|
41
|
+
"default": false,
|
|
42
|
+
"description": "Disabled state — sets aria-disabled (keeping the control focusable, like Button) and dims the chrome via the design-system disabled mixin. Accepts a static boolean or a () => boolean accessor."
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"name": "ariaLabel",
|
|
46
|
+
"label": "ARIA label",
|
|
47
|
+
"editor": { "tab": "settings" },
|
|
48
|
+
"type": "string",
|
|
49
|
+
"required": false,
|
|
50
|
+
"description": "Accessible label override. Defaults to the title and description text."
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"events": [
|
|
54
|
+
{
|
|
55
|
+
"name": "onClick",
|
|
56
|
+
"description": "Fired on click. Guarded against the disabled and loading states — the handler is not invoked while either is truthy."
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
"slots": [{ "name": "default", "displayName": "Icon" }],
|
|
60
|
+
"tokens": {
|
|
61
|
+
"color": "--color-primary (via --_action-tile-color), --color-on-primary, --color-surface, --color-text, --color-text-muted, --color-border",
|
|
62
|
+
"spacing": "--space-md (inline padding), --space-sm (block padding, media gap), --space-xs (title ↔ description)",
|
|
63
|
+
"radius": "--radius-md (tile), --radius-sm (media), --radius-pill (spinner)",
|
|
64
|
+
"size": "--font-size-sm (title, description), --icon-size-lg (media), --icon-size-sm (spinner)",
|
|
65
|
+
"border": "--border-width-hairline (idle), --border-width-thin (forced-colors, spinner)",
|
|
66
|
+
"motion": "--motion-transition-background, --motion-transition-color, --motion-duration-normal, --motion-duration-slow, --motion-easing-standard"
|
|
67
|
+
},
|
|
68
|
+
"spacing": {
|
|
69
|
+
"media-to-body": "--space-sm (close friends — glyph next to its label block)",
|
|
70
|
+
"title-to-description": "--space-xs (lovers — two lines of one action)"
|
|
71
|
+
},
|
|
72
|
+
"constraints": [
|
|
73
|
+
"title is required and must be non-empty — DEV warning when missing",
|
|
74
|
+
"Blocked (disabled or loading) tiles skip onClick invocation entirely (preventDefault + stopImmediatePropagation)",
|
|
75
|
+
"Default slot is treated as decorative (aria-hidden) — semantic content belongs in title / description / ariaLabel",
|
|
76
|
+
"Reactive loading / disabled accessors wire an internal effect; static booleans apply state once"
|
|
77
|
+
],
|
|
78
|
+
"a11y": [
|
|
79
|
+
"Renders a real <button type='button'> — keyboard activation, focus ring, and form-control semantics for free",
|
|
80
|
+
"Accessible name defaults to the title + description text; explicit ariaLabel takes precedence",
|
|
81
|
+
"loading sets aria-busy='true' so assistive tech announces the in-progress action",
|
|
82
|
+
"Forced-colors: explicit border, GrayText when disabled"
|
|
83
|
+
],
|
|
84
|
+
"ai": {
|
|
85
|
+
"synonyms": [
|
|
86
|
+
"action tile",
|
|
87
|
+
"action row",
|
|
88
|
+
"option row",
|
|
89
|
+
"choice",
|
|
90
|
+
"menu item",
|
|
91
|
+
"launcher"
|
|
92
|
+
],
|
|
93
|
+
"avoid": [
|
|
94
|
+
"a <Button> stretched full-width with custom CSS to fit a title + description — use <ActionTile>, which owns the two-line layout and busy/disabled a11y",
|
|
95
|
+
"div with onClick — use <ActionTile> so keyboard activation and focus ring come for free",
|
|
96
|
+
"<Tile> for horizontal icon-beside-text rows — Tile is the vertical icon-over-label variant"
|
|
97
|
+
],
|
|
98
|
+
"patterns": [
|
|
99
|
+
"Publish tier: <ActionTile title=\"'Share Preview'\" description=\"'One self-contained HTML file'\" @click=\"share\"><Icon name=\"'share'\" decorative=\"true\" size=\"'sm'\" /></ActionTile>",
|
|
100
|
+
"Busy tier: <ActionTile title=\"'Download Files'\" description=\"'A .zip of the static site'\" loading=\"isExporting\" @click=\"download\"><Icon name=\"'download'\" decorative=\"true\" size=\"'sm'\" /></ActionTile>",
|
|
101
|
+
"Disabled tier: <ActionTile title=\"'Go Live'\" description=\"'Coming soon'\" disabled=\"true\"><Icon name=\"'send'\" /></ActionTile>"
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
"designGuidance": {
|
|
105
|
+
"surface": "Surface uses --color-surface with a hairline border. Hover blends the primary tint via the design-system state-background mixin.",
|
|
106
|
+
"depth": "Flat by default; no shadow — depth is reserved for the containing surface (e.g. a Modal).",
|
|
107
|
+
"borders": "Hairline border in idle; hover tints the border toward primary.",
|
|
108
|
+
"interactivity": "Hover, focus-visible, loading, and disabled states derive from design-system tokens — no bespoke colors. The media glyph inverts to primary on hover/focus.",
|
|
109
|
+
"darkMode": "Adapts automatically via --color-* tokens; the --_action-tile-color split keeps the media glyph contrast correct in either mode."
|
|
110
|
+
},
|
|
111
|
+
"examples": [
|
|
112
|
+
{
|
|
113
|
+
"id": "default",
|
|
114
|
+
"title": "Default action tile",
|
|
115
|
+
"pithy": "<ActionTile title=\"'Share Preview'\" description=\"'One self-contained HTML file'\"><Icon name=\"'share'\" decorative=\"true\" size=\"'sm'\" /></ActionTile>",
|
|
116
|
+
"assertions": [
|
|
117
|
+
"renders a <button class='ui-action-tile'>",
|
|
118
|
+
"title text content matches",
|
|
119
|
+
"description text content matches"
|
|
120
|
+
]
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"id": "loading",
|
|
124
|
+
"title": "Loading action tile",
|
|
125
|
+
"pithy": "<ActionTile title=\"'Download Files'\" loading=\"true\"><Icon name=\"'download'\" decorative=\"true\" size=\"'sm'\" /></ActionTile>",
|
|
126
|
+
"assertions": ["data-loading='true'", "aria-busy='true'"]
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"id": "disabled",
|
|
130
|
+
"title": "Disabled action tile",
|
|
131
|
+
"pithy": "<ActionTile title=\"'Go Live'\" description=\"'Coming soon'\" disabled=\"true\"><Icon name=\"'send'\" /></ActionTile>",
|
|
132
|
+
"assertions": ["aria-disabled='true'", "data-disabled='true'"]
|
|
133
|
+
}
|
|
134
|
+
]
|
|
135
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "component",
|
|
3
|
+
"id": "ui.badge",
|
|
4
|
+
"name": "Badge",
|
|
5
|
+
"displayName": "Badge",
|
|
6
|
+
"version": "0.1.0",
|
|
7
|
+
"level": "atom",
|
|
8
|
+
"domain": "content",
|
|
9
|
+
"bidi": true,
|
|
10
|
+
"description": "Inline status badge for counts, labels, and dot indicators. Renders a <span> with semantic color, size, and variant styling. In dot mode renders a compact colored circle with role='status'.",
|
|
11
|
+
"props": [
|
|
12
|
+
{
|
|
13
|
+
"name": "text",
|
|
14
|
+
"reactive": true,
|
|
15
|
+
"label": "Text",
|
|
16
|
+
"type": "string | Signal<string>",
|
|
17
|
+
"placeholder": "New",
|
|
18
|
+
"description": "Visible badge text. Rendered as a text node inside the badge. Ignored in dot mode. When omitted, the component falls back to slot content."
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "iconStart",
|
|
22
|
+
"reactive": true,
|
|
23
|
+
"label": "Leading icon",
|
|
24
|
+
"type": "icon",
|
|
25
|
+
"description": "Icon shown before the badge text. Ignored in dot mode."
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "color",
|
|
29
|
+
"label": "Color",
|
|
30
|
+
"editor": { "type": "token-color" },
|
|
31
|
+
"type": "enum",
|
|
32
|
+
"enum": [
|
|
33
|
+
"primary",
|
|
34
|
+
"secondary",
|
|
35
|
+
"tertiary",
|
|
36
|
+
"success",
|
|
37
|
+
"info",
|
|
38
|
+
"warning",
|
|
39
|
+
"danger"
|
|
40
|
+
],
|
|
41
|
+
"default": "primary",
|
|
42
|
+
"description": "Semantic color — maps to --color-* design tokens via --_badge-* custom properties."
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"name": "size",
|
|
46
|
+
"label": "Size",
|
|
47
|
+
"type": "enum",
|
|
48
|
+
"enum": ["sm", "md", "lg"],
|
|
49
|
+
"default": "md",
|
|
50
|
+
"description": "Badge size — controls font-size and padding"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"name": "variant",
|
|
54
|
+
"label": "Variant",
|
|
55
|
+
"type": "enum",
|
|
56
|
+
"enum": ["filled", "outline", "subtle"],
|
|
57
|
+
"default": "filled",
|
|
58
|
+
"description": "Display variant — filled (solid bg), outline (border only), subtle (tinted bg)"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"name": "dot",
|
|
62
|
+
"label": "Dot",
|
|
63
|
+
"type": "boolean",
|
|
64
|
+
"default": false,
|
|
65
|
+
"description": "Dot-only mode — renders a small colored circle with no text. Requires label for accessibility."
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"name": "pulse",
|
|
69
|
+
"label": "Pulse",
|
|
70
|
+
"type": "boolean",
|
|
71
|
+
"default": false,
|
|
72
|
+
"description": "Pulsing animation for dot mode — live indicator (respects prefers-reduced-motion)"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"name": "label",
|
|
76
|
+
"label": "Label",
|
|
77
|
+
"type": "string",
|
|
78
|
+
"required": false,
|
|
79
|
+
"description": "Accessible label. Required when dot is true. Optional for text badges (visible content is the accessible name)."
|
|
80
|
+
}
|
|
81
|
+
],
|
|
82
|
+
"events": [],
|
|
83
|
+
"tokens": {
|
|
84
|
+
"color": "--color-{color}, --color-on-{color} (via --_badge-color, --_badge-on-color)",
|
|
85
|
+
"size": "--font-size-{xs|sm|body}, --space-{xs|sm|md}",
|
|
86
|
+
"radius": "--radius-pill (pill shape)",
|
|
87
|
+
"border": "--border-width-thin (outline variant, 40% opacity)",
|
|
88
|
+
"shadow": "--shadow-xs (filled variant depth)",
|
|
89
|
+
"motion": "--motion-duration-deliberate, --motion-easing-standard (pulse animation)"
|
|
90
|
+
},
|
|
91
|
+
"spacing": {
|
|
92
|
+
"badge-to-text": "--space-xs (lovers — badge inline with label)",
|
|
93
|
+
"badges-in-group": "--space-xs (lovers — related badges side by side)"
|
|
94
|
+
},
|
|
95
|
+
"constraints": [
|
|
96
|
+
"label is required when dot is true — DEV warning when missing",
|
|
97
|
+
"Dot mode ignores children, variant, and size — always renders as a solid colored circle sized by --space-sm token",
|
|
98
|
+
"Text badges use visible content as accessible name unless label overrides it",
|
|
99
|
+
"Colors are semantic only (primary/secondary/tertiary/success/info/warning/danger) — no text colors",
|
|
100
|
+
"Text truncates with ellipsis at max-inline-size 12rem (~20 chars at body font-size)",
|
|
101
|
+
"size has no effect in dot mode — DEV warning when set to a non-default size",
|
|
102
|
+
"Pulse animation respects prefers-reduced-motion (static opacity fallback)",
|
|
103
|
+
"pulse without dot has no effect — DEV warning when set on text badges",
|
|
104
|
+
"user-select: none — badges are labels, not selectable content"
|
|
105
|
+
],
|
|
106
|
+
"a11y": [
|
|
107
|
+
"Dot mode: role='status' + aria-label for live-region semantics",
|
|
108
|
+
"Text badges: visible text content serves as accessible name",
|
|
109
|
+
"Explicit label prop overrides visible text via aria-label",
|
|
110
|
+
"Forced-colors: border fallback ensures visibility in high-contrast mode"
|
|
111
|
+
],
|
|
112
|
+
"ai": {
|
|
113
|
+
"synonyms": [
|
|
114
|
+
"badge",
|
|
115
|
+
"tag",
|
|
116
|
+
"chip",
|
|
117
|
+
"label",
|
|
118
|
+
"pill",
|
|
119
|
+
"status indicator",
|
|
120
|
+
"count"
|
|
121
|
+
],
|
|
122
|
+
"avoid": [
|
|
123
|
+
"div for badges — use <Badge> component",
|
|
124
|
+
"raw background colors — use color prop",
|
|
125
|
+
"hardcoded pill radius — component handles it",
|
|
126
|
+
"span with manual styling — use variant prop"
|
|
127
|
+
],
|
|
128
|
+
"patterns": [
|
|
129
|
+
"Status badge: <Badge color=\"'success'\">Active</Badge>",
|
|
130
|
+
"Count badge: <Badge color=\"'danger'\" size=\"'sm'\">3</Badge>",
|
|
131
|
+
"Outline badge: <Badge variant=\"'outline'\" color=\"'info'\">Beta</Badge>",
|
|
132
|
+
"Subtle badge: <Badge variant=\"'subtle'\" color=\"'warning'\">Pending</Badge>",
|
|
133
|
+
"Dot indicator: <Badge dot=\"true\" color=\"'danger'\" label=\"'3 unread'\" />",
|
|
134
|
+
"Pulsing live dot: <Badge dot=\"true\" pulse=\"true\" color=\"'success'\" label=\"'Online'\" />"
|
|
135
|
+
]
|
|
136
|
+
},
|
|
137
|
+
"designGuidance": {
|
|
138
|
+
"surface": "Filled uses solid semantic color bg with on-color text + inner glass highlight. Outline uses 40% opacity border. Subtle uses 18% tinted bg.",
|
|
139
|
+
"depth": "Filled has shadow-xs + inner highlight for subtle depth. Outline/subtle are flat.",
|
|
140
|
+
"borders": "Outline variant uses thin inset box-shadow at 40% opacity. Filled has inner glass highlight.",
|
|
141
|
+
"interactivity": "Badges are non-interactive (no hover/focus states). Use Button with badge styling for clickable tags.",
|
|
142
|
+
"darkMode": "Colors adapt automatically via --color-* custom properties. Dark-mode semantic tokens use higher lightness with dark on-colors for WCAG AA contrast.",
|
|
143
|
+
"inlineUsage": "Badges use vertical-align: super for notification-count positioning inline with text. min-inline-size guarantees circles for single-char content (counts). margin-inline-start provides optical spacing from preceding text."
|
|
144
|
+
},
|
|
145
|
+
"examples": [
|
|
146
|
+
{
|
|
147
|
+
"id": "filled",
|
|
148
|
+
"title": "Filled status badge",
|
|
149
|
+
"pithy": "<Badge color=\"'success'\">Active</Badge>",
|
|
150
|
+
"assertions": [
|
|
151
|
+
"has ui-badge class",
|
|
152
|
+
"data-variant='filled'",
|
|
153
|
+
"data-color='success'"
|
|
154
|
+
]
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"id": "outline",
|
|
158
|
+
"title": "Outline badge",
|
|
159
|
+
"pithy": "<Badge variant=\"'outline'\" color=\"'info'\">Beta</Badge>",
|
|
160
|
+
"assertions": ["data-variant='outline'", "data-color='info'"]
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"id": "subtle",
|
|
164
|
+
"title": "Subtle badge",
|
|
165
|
+
"pithy": "<Badge variant=\"'subtle'\" color=\"'warning'\">Pending</Badge>",
|
|
166
|
+
"assertions": ["data-variant='subtle'", "data-color='warning'"]
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"id": "dot",
|
|
170
|
+
"title": "Dot indicator",
|
|
171
|
+
"pithy": "<Badge dot=\"true\" color=\"'danger'\" label=\"'Unread messages'\" />",
|
|
172
|
+
"assertions": [
|
|
173
|
+
"has ui-badge-dot class",
|
|
174
|
+
"role='status'",
|
|
175
|
+
"aria-label='Unread messages'"
|
|
176
|
+
]
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"id": "pulsing-dot",
|
|
180
|
+
"title": "Pulsing live indicator",
|
|
181
|
+
"pithy": "<Badge dot=\"true\" pulse=\"true\" color=\"'success'\" label=\"'Online'\" />",
|
|
182
|
+
"assertions": [
|
|
183
|
+
"has ui-badge-pulse class",
|
|
184
|
+
"role='status'",
|
|
185
|
+
"aria-label='Online'"
|
|
186
|
+
]
|
|
187
|
+
}
|
|
188
|
+
]
|
|
189
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "component",
|
|
3
|
+
"id": "ui.callout",
|
|
4
|
+
"name": "Callout",
|
|
5
|
+
"displayName": "Callout",
|
|
6
|
+
"version": "0.1.0",
|
|
7
|
+
"level": "atom",
|
|
8
|
+
"domain": "content",
|
|
9
|
+
"bidi": true,
|
|
10
|
+
"description": "Static, tone-driven admonition/callout container for docs pages. Renders a role=note region with a decorative leading tone icon, a visually-hidden tone label (so tone is never conveyed by color alone), an optional bold title, and the body content. Tone (info | tip | warning | danger) drives the accent bar, tinted surface, and default icon.",
|
|
11
|
+
"props": [
|
|
12
|
+
{
|
|
13
|
+
"name": "content",
|
|
14
|
+
"label": "Content",
|
|
15
|
+
"type": "string",
|
|
16
|
+
"required": true,
|
|
17
|
+
"placeholder": "This behaviour is experimental and may change.",
|
|
18
|
+
"description": "The callout body, authored as text in the site builder. The component's TypeScript API additionally accepts a Node or a { el, destroy } ui-kit component. Strings are inserted as text (never HTML) — avoids injection and stray {{ }} interpolation."
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "tone",
|
|
22
|
+
"label": "Tone",
|
|
23
|
+
"type": "enum",
|
|
24
|
+
"enum": ["info", "tip", "warning", "danger"],
|
|
25
|
+
"default": "info",
|
|
26
|
+
"description": "Semantic tone driving the accent color, tinted surface, default icon, and visually-hidden label. Each tone has a distinct icon shape so tone is never conveyed by color alone: info→circle-info, tip→lightbulb, warning→triangle alert, danger→octagon alert. The legacy spelling 'warn' is still accepted as a deprecated alias for 'warning'."
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "title",
|
|
30
|
+
"label": "Title",
|
|
31
|
+
"type": "string",
|
|
32
|
+
"required": false,
|
|
33
|
+
"description": "Optional bold heading line above the body. Rendered as literal text (never HTML) via a bold <Text> line — not a document heading, so it does not affect heading hierarchy."
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "icon",
|
|
37
|
+
"label": "Icon",
|
|
38
|
+
"type": "icon",
|
|
39
|
+
"required": false,
|
|
40
|
+
"description": "Override the default tone icon with a named icon (resolved via the built-in icon fallback)."
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "size",
|
|
44
|
+
"label": "Size",
|
|
45
|
+
"type": "enum",
|
|
46
|
+
"enum": ["md", "sm"],
|
|
47
|
+
"default": "md",
|
|
48
|
+
"description": "Density. 'md' (default) is the full docs callout; 'sm' is a compact variant for inline hints beside form fields — tighter padding, gap, and radius, with a smaller icon."
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"name": "dismissible",
|
|
52
|
+
"label": "Dismissible",
|
|
53
|
+
"type": "boolean",
|
|
54
|
+
"default": false,
|
|
55
|
+
"description": "Show a trailing dismiss (×) button that tears down and removes the callout when clicked. The TypeScript API also accepts an onDismiss callback, fired just before removal."
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"name": "ariaLabel",
|
|
59
|
+
"label": "ARIA label",
|
|
60
|
+
"editor": { "tab": "settings" },
|
|
61
|
+
"type": "string",
|
|
62
|
+
"required": false,
|
|
63
|
+
"description": "Accessible name for the callout container. Useful when several callouts share a page and need to be distinguished by assistive tech."
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
"tokens": {
|
|
67
|
+
"color": "--color-info/success/warning/danger (per-tone accent, theme-aware), --color-surface (tint base), --color-text (body). Fill = color-mix(accent 12%, surface); border = color-mix(accent 30%, transparent); icon chip = color-mix(accent 20%, transparent); title = the tone accent (meets text contrast in both themes).",
|
|
68
|
+
"spacing": "--space-xs (icon chip padding), --space-sm (title↔body), --space-md (container padding + chip↔content gap)",
|
|
69
|
+
"radius": "--radius-lg (container), --radius-md (compact container, data-size='sm'), --radius-sm (icon chip + focus-ring rounding on body links)",
|
|
70
|
+
"border": "--border-width-hairline (full tone border), --border-width-medium (flush inset accent bar), --border-width-thin (forced-colors border)",
|
|
71
|
+
"typography": "--font-size-lg + weight semibold (title, via the <Text> component)"
|
|
72
|
+
},
|
|
73
|
+
"spacing": {
|
|
74
|
+
"chip-content-gap": "--space-md (friends — the icon chip beside the message column)",
|
|
75
|
+
"chip-padding": "--space-xs (the tinted chip's inset around the md icon → a 28px chip)",
|
|
76
|
+
"title-body-gap": "--space-sm (close friends — title above its body)",
|
|
77
|
+
"container-padding": "--space-md (comfortable reading padding; inline-start adds the accent-bar width so content clears the flush bar)"
|
|
78
|
+
},
|
|
79
|
+
"constraints": [
|
|
80
|
+
"content is required — it is the callout body",
|
|
81
|
+
"Inline container — no interactivity of its own except the optional dismiss (×) button when dismissible=true; body content may also contain its own links/controls",
|
|
82
|
+
"String content is inserted as text (textContent), never HTML — avoids injection and stray {{ }} interpolation",
|
|
83
|
+
"title is rendered as literal text via a bold <Text as='strong'> line — never a Heading atom, so it does not inject document hierarchy",
|
|
84
|
+
"Tone is conveyed by a visually-hidden text label (Information:/Tip:/Warning:/Danger:), never by color alone (WCAG 1.4.1)",
|
|
85
|
+
"The leading tone icon is decorative (aria-hidden) and resolves via the built-in icon fallback — no app sprite setup required",
|
|
86
|
+
"icon overrides the tone default glyph when provided"
|
|
87
|
+
],
|
|
88
|
+
"a11y": [
|
|
89
|
+
"role=note names the container as an admonition region",
|
|
90
|
+
"Tone is announced via a visually-hidden label placed before the title/body — tone is never conveyed by color alone",
|
|
91
|
+
"Tone glyphs resolve through the normal icon pipeline, so an app sprite registering the same generic names (info/tip/alert/octagon-alert) overrides them. The visually-hidden tone label keeps the non-color-alone guarantee intact regardless, but an app that overrides these names should keep the shapes visually distinct",
|
|
92
|
+
"The leading tone icon is decorative (aria-hidden=true) so it is not double-announced",
|
|
93
|
+
"ariaLabel, when provided, sets the container's accessible name",
|
|
94
|
+
"Forced-colors: the accent tint is replaced by a solid CanvasText border so the container stays perceivable"
|
|
95
|
+
],
|
|
96
|
+
"ai": {
|
|
97
|
+
"synonyms": [
|
|
98
|
+
"callout",
|
|
99
|
+
"admonition",
|
|
100
|
+
"note",
|
|
101
|
+
"notice",
|
|
102
|
+
"info box",
|
|
103
|
+
"warning box",
|
|
104
|
+
"alert box",
|
|
105
|
+
"tip",
|
|
106
|
+
"aside",
|
|
107
|
+
"banner note"
|
|
108
|
+
],
|
|
109
|
+
"avoid": [
|
|
110
|
+
"using <Callout> as a transient or floating notification — it is an inline docs container (it can be dismissible, but it does not stack, auto-dismiss, or portal); use a feedback component (Toast/AlertDialog) for those",
|
|
111
|
+
"using <Badge> for a sentence-length message — Badge clips long text; <Callout> is for multi-word admonitions"
|
|
112
|
+
],
|
|
113
|
+
"patterns": [
|
|
114
|
+
"Basic: <Callout content=\"'Heads up — this is experimental.'\" />",
|
|
115
|
+
"Toned with title: <Callout tone=\"'warning'\" title=\"'Deprecated'\" content=\"'Use the new API instead.'\" />",
|
|
116
|
+
"Danger: <Callout tone=\"'danger'\" content=\"'This action cannot be undone.'\" />",
|
|
117
|
+
"Custom icon: <Callout tone=\"'tip'\" icon=\"'eye'\" content=\"'Preview before publishing.'\" />"
|
|
118
|
+
]
|
|
119
|
+
},
|
|
120
|
+
"designGuidance": {
|
|
121
|
+
"surface": "A tone-tinted fill (accent mixed ~12% into --color-surface) inside a full translucent tone border, with a flush inset accent bar on the inline-start edge and a tinted icon chip anchoring the tone. Every tone reads at a glance in both light and dark themes.",
|
|
122
|
+
"depth": "Flat — no shadow. Visual weight comes from the tinted fill, the tone border, the flush accent bar, and the icon chip.",
|
|
123
|
+
"borders": "A full --border-width-hairline tone border (color-mix of the accent at 30% alpha) around the whole card, plus a flush --border-width-medium accent bar rendered as an inset box-shadow (so it follows the rounded corners; RTL-flipped via :dir(rtl)). Forced-colors falls back to a solid CanvasText border.",
|
|
124
|
+
"interactivity": "The container itself is inert except for the optional trailing dismiss (×) button (dismissible=true), a ghost <Button> that removes the callout. Any other interactivity comes from body content (e.g. links), which surfaces the design-system focus ring.",
|
|
125
|
+
"motion": "Static by default — the exit transition is scoped to the dismissing state, so ordinary layout/theme changes are never animated. When dismissible, dismissing plays a motion-safe exit (fade + collapse to zero footprint, absorbing one gap along the flex container's main axis so siblings slide up); reduced-motion removes it instantly. Focus moves to the nearest survivor before removal.",
|
|
126
|
+
"bestPractices": "Use for tone-driven asides in docs and long-form content: info for context, tip for suggestions, warn for caveats, danger for irreversible/destructive warnings. Keep the title short and the body scannable. Prefer one callout per idea rather than stacking many."
|
|
127
|
+
},
|
|
128
|
+
"examples": [
|
|
129
|
+
{
|
|
130
|
+
"id": "default",
|
|
131
|
+
"title": "Info callout",
|
|
132
|
+
"pithy": "<Callout content=\"'PithyJS updates only signal-bound DOM nodes.'\" />",
|
|
133
|
+
"assertions": [
|
|
134
|
+
"renders <div class='ui-callout'>",
|
|
135
|
+
"role='note'",
|
|
136
|
+
"data-tone='info'",
|
|
137
|
+
"leading icon has data-icon='info'"
|
|
138
|
+
]
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"id": "tones",
|
|
142
|
+
"title": "All tones",
|
|
143
|
+
"pithy": "<Callout tone=\"'danger'\" content=\"'This cannot be undone.'\" />",
|
|
144
|
+
"assertions": [
|
|
145
|
+
"data-tone reflects the tone prop",
|
|
146
|
+
"each tone uses a distinct icon shape: info→info, tip→tip, warning→alert, danger→octagon-alert",
|
|
147
|
+
"a visually-hidden label announces the tone"
|
|
148
|
+
]
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"id": "titled",
|
|
152
|
+
"title": "With title",
|
|
153
|
+
"pithy": "<Callout tone=\"'warning'\" title=\"'Deprecated'\" content=\"'Use the new API.'\" />",
|
|
154
|
+
"assertions": [
|
|
155
|
+
"renders a bold .ui-callout-title line",
|
|
156
|
+
"title text stays literal (no HTML/interpolation)"
|
|
157
|
+
]
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"id": "component-body",
|
|
161
|
+
"title": "Component body",
|
|
162
|
+
"pithy": "<Callout content=\"body\" />",
|
|
163
|
+
"assertions": [
|
|
164
|
+
"content binds a context variable holding a { el, destroy } handle (e.g. const body = CodeBlock({ code }))",
|
|
165
|
+
"the component mounts in the callout body",
|
|
166
|
+
"its destroy is chained to the callout's destroy"
|
|
167
|
+
]
|
|
168
|
+
}
|
|
169
|
+
]
|
|
170
|
+
}
|