@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.
Files changed (93) hide show
  1. package/LICENSE +21 -0
  2. package/dist/specs/atoms/actions/button.pidl.json +289 -0
  3. package/dist/specs/atoms/actions/icon-group.pidl.json +141 -0
  4. package/dist/specs/atoms/actions/segmented-control.pidl.json +137 -0
  5. package/dist/specs/atoms/content/action-tile.pidl.json +135 -0
  6. package/dist/specs/atoms/content/badge.pidl.json +189 -0
  7. package/dist/specs/atoms/content/callout.pidl.json +170 -0
  8. package/dist/specs/atoms/content/code-block.pidl.json +170 -0
  9. package/dist/specs/atoms/content/heading.pidl.json +175 -0
  10. package/dist/specs/atoms/content/icon.pidl.json +127 -0
  11. package/dist/specs/atoms/content/image.pidl.json +227 -0
  12. package/dist/specs/atoms/content/prose.pidl.json +183 -0
  13. package/dist/specs/atoms/content/stat.pidl.json +158 -0
  14. package/dist/specs/atoms/content/tabs.pidl.json +207 -0
  15. package/dist/specs/atoms/content/text.pidl.json +212 -0
  16. package/dist/specs/atoms/content/tile.pidl.json +156 -0
  17. package/dist/specs/atoms/data/donut.pidl.json +352 -0
  18. package/dist/specs/atoms/data/gauge.pidl.json +274 -0
  19. package/dist/specs/atoms/forms/checkbox-group.pidl.json +170 -0
  20. package/dist/specs/atoms/forms/checkbox.pidl.json +323 -0
  21. package/dist/specs/atoms/forms/file-picker.pidl.json +161 -0
  22. package/dist/specs/atoms/forms/form-field.pidl.json +106 -0
  23. package/dist/specs/atoms/forms/input.pidl.json +466 -0
  24. package/dist/specs/atoms/forms/radio-group.pidl.json +174 -0
  25. package/dist/specs/atoms/forms/radio.pidl.json +312 -0
  26. package/dist/specs/atoms/forms/search-input.pidl.json +265 -0
  27. package/dist/specs/atoms/forms/select.pidl.json +420 -0
  28. package/dist/specs/atoms/forms/textarea.pidl.json +422 -0
  29. package/dist/specs/atoms/forms/toggle.pidl.json +314 -0
  30. package/dist/specs/layout/grid-item.pidl.json +120 -0
  31. package/dist/specs/layout/grid.pidl.json +157 -0
  32. package/dist/specs/layout/page-section.pidl.json +105 -0
  33. package/dist/specs/layout/smart-container.pidl.json +148 -0
  34. package/dist/specs/layout/stack.pidl.json +144 -0
  35. package/dist/specs/organisms/content/accordion.pidl.json +196 -0
  36. package/dist/specs/organisms/content/card.pidl.json +283 -0
  37. package/dist/specs/organisms/feedback/alert-dialog.pidl.json +158 -0
  38. package/dist/specs/organisms/feedback/modal.pidl.json +133 -0
  39. package/dist/specs/organisms/feedback/toast.pidl.json +150 -0
  40. package/dist/specs/organisms/forms/dynamic-form.pidl.json +314 -0
  41. package/dist/specs/organisms/forms/form.pidl.json +135 -0
  42. package/dist/specs/organisms/forms/subscribe-form.pidl.json +188 -0
  43. package/dist/specs/organisms/navigation/command-palette.pidl.json +263 -0
  44. package/dist/specs/organisms/navigation/docs-sidebar.pidl.json +264 -0
  45. package/dist/specs/organisms/navigation/navbar.pidl.json +356 -0
  46. package/dist/specs/organisms/navigation/table-of-contents.pidl.json +197 -0
  47. package/dist/specs/sections/contact-section.pidl.json +183 -0
  48. package/dist/specs/sections/cta-section.pidl.json +168 -0
  49. package/dist/specs/sections/faq-section.pidl.json +202 -0
  50. package/dist/specs/sections/features-section.pidl.json +214 -0
  51. package/dist/specs/sections/footer-section.pidl.json +187 -0
  52. package/dist/specs/sections/hero-section.pidl.json +202 -0
  53. package/dist/src/borders-psychology.d.ts +17 -0
  54. package/dist/src/borders-psychology.d.ts.map +1 -0
  55. package/dist/src/borders-psychology.js +42 -0
  56. package/dist/src/borders-psychology.js.map +1 -0
  57. package/dist/src/color-psychology.d.ts +20 -0
  58. package/dist/src/color-psychology.d.ts.map +1 -0
  59. package/dist/src/color-psychology.js +57 -0
  60. package/dist/src/color-psychology.js.map +1 -0
  61. package/dist/src/design-intelligence.d.ts +13 -0
  62. package/dist/src/design-intelligence.d.ts.map +1 -0
  63. package/dist/src/design-intelligence.js +36 -0
  64. package/dist/src/design-intelligence.js.map +1 -0
  65. package/dist/src/index.d.ts +6238 -0
  66. package/dist/src/index.d.ts.map +1 -0
  67. package/dist/src/index.js +105 -0
  68. package/dist/src/index.js.map +1 -0
  69. package/dist/src/motion-psychology.d.ts +19 -0
  70. package/dist/src/motion-psychology.d.ts.map +1 -0
  71. package/dist/src/motion-psychology.js +47 -0
  72. package/dist/src/motion-psychology.js.map +1 -0
  73. package/dist/src/mutation-vocabulary.d.ts +13 -0
  74. package/dist/src/mutation-vocabulary.d.ts.map +1 -0
  75. package/dist/src/mutation-vocabulary.js +67 -0
  76. package/dist/src/mutation-vocabulary.js.map +1 -0
  77. package/dist/src/radius-psychology.d.ts +17 -0
  78. package/dist/src/radius-psychology.d.ts.map +1 -0
  79. package/dist/src/radius-psychology.js +42 -0
  80. package/dist/src/radius-psychology.js.map +1 -0
  81. package/dist/src/shadows-psychology.d.ts +17 -0
  82. package/dist/src/shadows-psychology.d.ts.map +1 -0
  83. package/dist/src/shadows-psychology.js +44 -0
  84. package/dist/src/shadows-psychology.js.map +1 -0
  85. package/dist/src/spacing-psychology.d.ts +22 -0
  86. package/dist/src/spacing-psychology.d.ts.map +1 -0
  87. package/dist/src/spacing-psychology.js +59 -0
  88. package/dist/src/spacing-psychology.js.map +1 -0
  89. package/dist/src/typography-psychology.d.ts +22 -0
  90. package/dist/src/typography-psychology.d.ts.map +1 -0
  91. package/dist/src/typography-psychology.js +68 -0
  92. package/dist/src/typography-psychology.js.map +1 -0
  93. package/package.json +64 -0
@@ -0,0 +1,183 @@
1
+ {
2
+ "kind": "component",
3
+ "id": "ui.contact-section",
4
+ "name": "ContactSection",
5
+ "displayName": "Contact Section",
6
+ "version": "0.1.0",
7
+ "level": "section",
8
+ "domain": "sections",
9
+ "bidi": true,
10
+ "description": "Contact information section with semantic address element, contact details, and form placeholder. Children projected into form area for V0.2 forms or external embeds.",
11
+ "props": [
12
+ {
13
+ "name": "heading",
14
+ "reactive": true,
15
+ "label": "Heading",
16
+ "type": "string | Signal<string>",
17
+ "default": "Contact Us",
18
+ "placeholder": "Get in touch",
19
+ "description": "Section heading text"
20
+ },
21
+ {
22
+ "name": "headingLevel",
23
+ "label": "Heading level",
24
+ "editor": { "tab": "settings" },
25
+ "type": "number",
26
+ "enum": [1, 2, 3, 4, 5, 6],
27
+ "default": 2,
28
+ "description": "Heading level for semantic correctness"
29
+ },
30
+ {
31
+ "name": "description",
32
+ "reactive": true,
33
+ "label": "Description",
34
+ "type": "string | Signal<string>",
35
+ "placeholder": "We'd love to hear from you. Reach out anytime.",
36
+ "description": "Section description below heading"
37
+ },
38
+ {
39
+ "name": "contacts",
40
+ "reactive": true,
41
+ "label": "Contacts",
42
+ "type": "ContactInfo[] | Signal<ContactInfo[]>",
43
+ "placeholder": [
44
+ {
45
+ "label": "Email",
46
+ "value": "hello@example.com",
47
+ "href": "mailto:hello@example.com",
48
+ "icon": "mail"
49
+ },
50
+ {
51
+ "label": "Phone",
52
+ "value": "+1 (555) 010-0000",
53
+ "href": "tel:+15550100000",
54
+ "icon": "phone"
55
+ },
56
+ {
57
+ "label": "Address",
58
+ "value": "123 Main St, Suite 100, San Francisco, CA 94103",
59
+ "icon": "map-pin"
60
+ }
61
+ ],
62
+ "description": "Array of contact items with label, value, optional icon and href",
63
+ "itemSchema": {
64
+ "label": {
65
+ "type": "string",
66
+ "required": true,
67
+ "description": "Contact method label (e.g. 'Email', 'Phone')"
68
+ },
69
+ "value": {
70
+ "type": "string",
71
+ "required": true,
72
+ "description": "Contact value (e.g. 'hello@example.com')"
73
+ },
74
+ "icon": {
75
+ "type": "string",
76
+ "editor": { "type": "icon" },
77
+ "description": "Optional icon name"
78
+ },
79
+ "href": {
80
+ "type": "string",
81
+ "description": "Optional link href (e.g. 'mailto:', 'tel:')"
82
+ }
83
+ }
84
+ },
85
+ {
86
+ "name": "spacing",
87
+ "label": "Spacing",
88
+ "editor": { "tab": "layout", "type": "token-space" },
89
+ "type": "enum",
90
+ "enum": ["0", "xs", "sm", "md", "lg", "xl"],
91
+ "default": "xl",
92
+ "description": "Vertical padding — maps to u-py-* utilities"
93
+ },
94
+ {
95
+ "name": "id",
96
+ "label": "Anchor ID",
97
+ "editor": { "tab": "settings" },
98
+ "type": "string",
99
+ "description": "Optional anchor id for in-page linking"
100
+ }
101
+ ],
102
+ "events": [],
103
+ "slots": [
104
+ {
105
+ "name": "form",
106
+ "displayName": "Form",
107
+ "description": "Contact form rendered beside the contact info.",
108
+ "accepts": ["ui.form"],
109
+ "max": 1
110
+ }
111
+ ],
112
+ "tokens": {
113
+ "spacing.vertical": "--space-{spacing} (via u-py-*)",
114
+ "spacing.container": "--space-md (gutter padding)"
115
+ },
116
+ "spacing": {
117
+ "heading-to-description": "--space-sm (close friends — heading and description)",
118
+ "description-to-contacts": "--space-lg (acquaintances — different content groups)",
119
+ "info-to-form": "--space-xl (strangers — contact info side and form side)",
120
+ "contact-items": "--space-sm (close friends — between contact list items)",
121
+ "icon-to-value": "--space-xs (lovers — icon and contact value)"
122
+ },
123
+ "designGuidance": {
124
+ "surface": "Contact section has no background — it relies on the page surface. The form/content side (projected children) should provide its own surface treatment (e.g. --color-surface-variant background with --radius-md).",
125
+ "depth": "No shadows on the section. Depth comes from the two-column layout and the contrast between the info side (text) and form side (contained card).",
126
+ "borders": "No section borders. Contact links use --color-text at rest with hover transition to --color-primary + underline.",
127
+ "interactivity": "Contact links are interactive — color transition on hover (motion-safe). Icons are decorative. The form side should contain interactive content (email button, form embed).",
128
+ "bestPractices": [
129
+ "Always provide href for actionable contacts — mailto: for email, tel: for phone",
130
+ "Form side should use a surface-variant background card, not a dashed wireframe placeholder",
131
+ "If no form is available, show a 'Send us a message' card with an email link — never show empty/wireframe states",
132
+ "Contact items use semantic <address> + <ul> — do not replace with divs",
133
+ "Two-column layout stacks on narrow viewports — design both orientations"
134
+ ]
135
+ },
136
+ "constraints": [
137
+ "Contact info rendered in semantic <address> element",
138
+ "href on contacts should use proper protocols (mailto:, tel:)",
139
+ "Children projected into form placeholder area (right side)",
140
+ "Layout uses flex-wrap with min-column tokens — stacks naturally when container is too narrow for two columns",
141
+ "Container uses fluid-center-parent (justify-content: center) and info side uses fluid-center-child (max-inline-size) — info block centers when wrapped to full width; form absorbs remaining space in two-column mode so centering has no effect"
142
+ ],
143
+ "a11y": [
144
+ "Renders semantic <section> element with aria-labelledby linked to heading",
145
+ "Uses <address> element for contact information",
146
+ "Contact links use proper href protocols for assistive tech",
147
+ "Icons are decorative (aria-hidden=true)",
148
+ "Contact list uses semantic <ul>/<li> markup",
149
+ "Contact list carries an explicit role=\"list\" because u-list-reset applies list-style: none !important, which strips list semantics in Safari/VoiceOver — the attribute is load-bearing, not redundant, and must not be removed",
150
+ "A contact's label reaches assistive tech by TWO different mechanisms, chosen by whether the value is a link. A linked value is an <a>, a nameable role, so it takes aria-label=\"Label: value\". A value with no usable href (an address, or an href rejected by isSafeHref) is a <span> — role=generic, where ARIA-in-HTML PROHIBITS naming and browsers discard aria-label — so its label is a visually hidden <span class=\"u-sr-only\"> instead. Do not unify these on aria-label: on the span it is inert, and the label is silently lost. axe does not flag it, because a prohibited name is discarded rather than reported"
151
+ ],
152
+ "ai": {
153
+ "synonyms": [
154
+ "contact",
155
+ "get in touch",
156
+ "reach us",
157
+ "contact form",
158
+ "contact info",
159
+ "contact details"
160
+ ],
161
+ "avoid": [
162
+ "div for contact info — use ContactSection with contacts array",
163
+ "links without proper protocol — use mailto: for email, tel: for phone"
164
+ ],
165
+ "patterns": [
166
+ "Basic contact: <ContactSection contacts=\"contactItems\"/>",
167
+ "With form placeholder: <ContactSection contacts=\"contactItems\"><p>Form coming in V0.2</p></ContactSection>",
168
+ "Custom heading: <ContactSection heading=\"'Get in Touch'\" description=\"'We'd love to hear from you'\" contacts=\"contactItems\"/>"
169
+ ]
170
+ },
171
+ "examples": [
172
+ {
173
+ "id": "basic-contact",
174
+ "title": "Contact section with details",
175
+ "pithy": "<ContactSection contacts=\"[{label:'Email',value:'hi@example.com',href:'mailto:hi@example.com',icon:'mail'}]\"/>",
176
+ "assertions": [
177
+ "renders <section>",
178
+ "<address> element present",
179
+ "contact link with mailto:"
180
+ ]
181
+ }
182
+ ]
183
+ }
@@ -0,0 +1,168 @@
1
+ {
2
+ "kind": "component",
3
+ "id": "ui.cta-section",
4
+ "name": "CTASection",
5
+ "displayName": "CTA Section",
6
+ "version": "0.1.0",
7
+ "level": "section",
8
+ "domain": "sections",
9
+ "bidi": true,
10
+ "description": "Call-to-action banner section with heading, description, and action buttons. Supports centered and inline layouts with semantic color theming.",
11
+ "props": [
12
+ {
13
+ "name": "eyebrow",
14
+ "reactive": true,
15
+ "label": "Eyebrow",
16
+ "type": "string | Signal<string>",
17
+ "placeholder": "GET STARTED",
18
+ "description": "Small uppercased label above the heading (e.g. 'LIMITED TIME', 'NEW')"
19
+ },
20
+ {
21
+ "name": "heading",
22
+ "reactive": true,
23
+ "label": "Heading",
24
+ "type": "string | Signal<string>",
25
+ "required": true,
26
+ "placeholder": "Ready to ship faster?",
27
+ "description": "CTA heading text"
28
+ },
29
+ {
30
+ "name": "headingLevel",
31
+ "label": "Heading level",
32
+ "editor": { "tab": "settings" },
33
+ "type": "number",
34
+ "enum": [1, 2, 3, 4, 5, 6],
35
+ "default": 2,
36
+ "description": "Heading level for semantic correctness"
37
+ },
38
+ {
39
+ "name": "description",
40
+ "reactive": true,
41
+ "label": "Description",
42
+ "type": "string | Signal<string>",
43
+ "placeholder": "Join thousands of developers building with our platform.",
44
+ "description": "Supporting description text below the heading"
45
+ },
46
+ {
47
+ "name": "color",
48
+ "label": "Color",
49
+ "editor": { "type": "token-color" },
50
+ "type": "enum",
51
+ "enum": [
52
+ "primary",
53
+ "secondary",
54
+ "tertiary",
55
+ "success",
56
+ "info",
57
+ "warning",
58
+ "danger"
59
+ ],
60
+ "default": "primary",
61
+ "description": "Semantic color scheme — sets data-color attribute for theming."
62
+ },
63
+ {
64
+ "name": "variant",
65
+ "label": "Variant",
66
+ "type": "enum",
67
+ "enum": ["centered", "inline"],
68
+ "default": "centered",
69
+ "description": "Layout variant — centered (stacked) or inline (text beside buttons)"
70
+ },
71
+ {
72
+ "name": "spacing",
73
+ "label": "Spacing",
74
+ "editor": { "tab": "layout", "type": "token-space" },
75
+ "type": "enum",
76
+ "enum": ["0", "xs", "sm", "md", "lg", "xl"],
77
+ "default": "lg",
78
+ "description": "Vertical padding — maps to u-py-* utilities"
79
+ },
80
+ {
81
+ "name": "id",
82
+ "label": "Anchor ID",
83
+ "editor": { "tab": "settings" },
84
+ "type": "string",
85
+ "description": "Optional anchor id for in-page linking"
86
+ }
87
+ ],
88
+ "events": [],
89
+ "slots": [
90
+ {
91
+ "name": "actions",
92
+ "displayName": "Actions",
93
+ "description": "Call-to-action buttons.",
94
+ "accepts": ["ui.button"]
95
+ }
96
+ ],
97
+ "tokens": {
98
+ "color.theme": "--color-{color} (via data-color attribute)",
99
+ "spacing.vertical": "--space-{spacing} (via u-py-*)",
100
+ "spacing.container": "--space-md (gutter padding)"
101
+ },
102
+ "spacing": {
103
+ "heading-to-description": "--space-sm (close friends — heading and supporting text)",
104
+ "content-to-actions": "--space-lg (acquaintances — text block and CTA buttons)",
105
+ "text-to-buttons-inline": "--space-lg (acquaintances — text side and buttons side in inline)"
106
+ },
107
+ "designGuidance": {
108
+ "surface": "CTA uses the standard --color-surface-variant background token to create a distinct visual band without being visually heavy. The background remains neutral; the color prop is expressed through themed accents and content rather than a tinted container.",
109
+ "depth": "Visual depth comes from the contrast between the surface-variant background and the surrounding page, plus the top and bottom borders. Avoid adding extra drop shadows so the section stays lightweight and consistent with other surfaces.",
110
+ "borders": "Top and bottom borders use the standard --color-border token to delineate the section. In forced-colors mode, rely on system border and background colors for sufficient contrast.",
111
+ "interactivity": "CTA itself is not interactive — buttons handle all interaction. Use eyebrow prop for urgency signals (e.g. 'LIMITED TIME').",
112
+ "bestPractices": [
113
+ "Use eyebrow for urgency or novelty signals — it draws the eye before the heading",
114
+ "Prefer ghost over outline for secondary CTA buttons",
115
+ "color prop controls accent theming (e.g. eyebrow color) while the background stays neutral — use 'warning' for urgency, 'success' for positive actions",
116
+ "Inline variant works best for newsletter/subscribe CTAs; centered for primary conversion CTAs",
117
+ "Description text is constrained to 60ch — keep it to 1-2 sentences"
118
+ ]
119
+ },
120
+ "constraints": [
121
+ "Children should contain CTA buttons — projected into the actions area",
122
+ "Color prop sets data-color for CSS theming — does not set inline background",
123
+ "Inline variant wraps to stacked layout on narrow containers"
124
+ ],
125
+ "a11y": [
126
+ "Renders semantic <section> element with aria-labelledby linked to heading",
127
+ "Heading uses correct <h1>-<h6> tag",
128
+ "CTA buttons maintain natural tab order"
129
+ ],
130
+ "ai": {
131
+ "synonyms": [
132
+ "cta",
133
+ "call to action",
134
+ "banner cta",
135
+ "signup banner",
136
+ "action section",
137
+ "conversion banner"
138
+ ],
139
+ "avoid": [
140
+ "div with styled background — use CTASection with color prop",
141
+ "multiple headings in CTA — use heading + description props"
142
+ ],
143
+ "patterns": [
144
+ "Centered CTA: <CTASection heading=\"'Ready to start?'\" description=\"'Join thousands'\"><Button>Sign Up</Button></CTASection>",
145
+ "Inline CTA: <CTASection variant=\"'inline'\" heading=\"'Get updates'\"><Button>Subscribe</Button></CTASection>",
146
+ "Colored CTA: <CTASection heading=\"'Limited offer'\" color=\"'warning'\"><Button>Claim Now</Button></CTASection>"
147
+ ]
148
+ },
149
+ "examples": [
150
+ {
151
+ "id": "centered-cta",
152
+ "title": "Centered CTA banner",
153
+ "pithy": "<CTASection heading=\"'Ready to get started?'\" description=\"'Join thousands of developers'\"><Button color=\"'primary'\">Sign Up Free</Button></CTASection>",
154
+ "assertions": [
155
+ "renders <section>",
156
+ "data-color='primary'",
157
+ "h2 with heading text",
158
+ "children in actions area"
159
+ ]
160
+ },
161
+ {
162
+ "id": "inline-cta",
163
+ "title": "Inline CTA",
164
+ "pithy": "<CTASection variant=\"'inline'\" heading=\"'Stay updated'\"><Button>Subscribe</Button></CTASection>",
165
+ "assertions": ["inline layout", "text beside buttons"]
166
+ }
167
+ ]
168
+ }
@@ -0,0 +1,202 @@
1
+ {
2
+ "kind": "component",
3
+ "id": "ui.faq-section",
4
+ "name": "FaqSection",
5
+ "displayName": "FAQ Section",
6
+ "version": "0.1.0",
7
+ "level": "section",
8
+ "domain": "sections",
9
+ "bidi": true,
10
+ "description": "Frequently-asked-questions section composed from the Accordion organism. Renders a centered header (optional eyebrow + heading + subheading) above a measure-constrained stack of native <details> disclosures, one per question.",
11
+ "props": [
12
+ {
13
+ "name": "heading",
14
+ "reactive": true,
15
+ "label": "Heading",
16
+ "type": "string | Signal<string>",
17
+ "default": "Frequently asked questions",
18
+ "placeholder": "Frequently asked questions",
19
+ "description": "Section heading text displayed above the questions"
20
+ },
21
+ {
22
+ "name": "headingLevel",
23
+ "label": "Heading level",
24
+ "editor": { "tab": "settings" },
25
+ "type": "number",
26
+ "enum": [1, 2, 3, 4, 5, 6],
27
+ "default": 2,
28
+ "description": "Heading level for semantic correctness"
29
+ },
30
+ {
31
+ "name": "subheading",
32
+ "reactive": true,
33
+ "label": "Subheading",
34
+ "type": "string | Signal<string>",
35
+ "placeholder": "Everything you need to know before getting started.",
36
+ "description": "Section description below the heading"
37
+ },
38
+ {
39
+ "name": "eyebrow",
40
+ "label": "Eyebrow",
41
+ "type": "string",
42
+ "placeholder": "FAQ",
43
+ "description": "Short uppercase kicker rendered above the heading"
44
+ },
45
+ {
46
+ "name": "items",
47
+ "reactive": true,
48
+ "label": "Questions",
49
+ "type": "FaqItem[] | Signal<FaqItem[]>",
50
+ "required": true,
51
+ "placeholder": [
52
+ {
53
+ "question": "What do I get out of the box?",
54
+ "answer": "Accessible, responsive components that follow the design system automatically — no custom CSS required to look consistent."
55
+ },
56
+ {
57
+ "question": "Can I use it without JavaScript?",
58
+ "answer": "Yes. The questions are native <details> elements, so they expand and collapse even before any JavaScript loads."
59
+ },
60
+ {
61
+ "question": "Does it work on mobile?",
62
+ "answer": "Every section is intrinsically fluid — layouts reflow to a single column on narrow screens with no breakpoints to configure."
63
+ },
64
+ {
65
+ "question": "How do I get help?",
66
+ "answer": "Reach out through the contact section, or open an issue in the repository. We usually respond within a day."
67
+ }
68
+ ],
69
+ "description": "Array of question/answer pairs. Questions and answers may be plain strings or reactive accessors.",
70
+ "itemSchema": {
71
+ "question": {
72
+ "type": "string",
73
+ "required": true,
74
+ "description": "The question, rendered as the disclosure trigger"
75
+ },
76
+ "answer": {
77
+ "type": "string",
78
+ "required": true,
79
+ "description": "The answer, revealed when the item is open"
80
+ },
81
+ "open": {
82
+ "type": "boolean",
83
+ "description": "Force this question open on first render"
84
+ }
85
+ }
86
+ },
87
+ {
88
+ "name": "mode",
89
+ "label": "Mode",
90
+ "type": "enum",
91
+ "enum": ["single", "multi"],
92
+ "default": "multi",
93
+ "description": "'single' closes sibling answers when one opens; 'multi' (default) lets answers stay open independently."
94
+ },
95
+ {
96
+ "name": "defaultOpen",
97
+ "label": "Default open",
98
+ "editor": { "tab": "settings" },
99
+ "type": "number | number[]",
100
+ "description": "Which question index(es) start open (index or array of indices)."
101
+ },
102
+ {
103
+ "name": "spacing",
104
+ "label": "Spacing",
105
+ "editor": { "tab": "layout", "type": "token-space" },
106
+ "type": "enum",
107
+ "enum": ["0", "xs", "sm", "md", "lg", "xl"],
108
+ "default": "xl",
109
+ "description": "Vertical padding — maps to u-py-* utilities"
110
+ },
111
+ {
112
+ "name": "id",
113
+ "label": "Anchor ID",
114
+ "editor": { "tab": "settings" },
115
+ "type": "string",
116
+ "description": "Optional anchor id for in-page linking"
117
+ }
118
+ ],
119
+ "events": [],
120
+ "slots": [
121
+ {
122
+ "name": "extras",
123
+ "displayName": "Extras",
124
+ "description": "Extra content below the questions, e.g. a \"Still have questions? Contact us\" link."
125
+ }
126
+ ],
127
+ "tokens": {
128
+ "spacing.vertical": "--space-{spacing} (via u-py-*)",
129
+ "spacing.container": "--space-md (gutter padding)",
130
+ "eyebrow.color": "--color-primary (via .ui-section-eyebrow)",
131
+ "heading.color": "--color-text (via Heading component)",
132
+ "subheading.color": "--color-text-muted (via Text component)",
133
+ "accordion.measure": "--measure-content max-inline-size, centered via margin-inline: auto"
134
+ },
135
+ "spacing": {
136
+ "eyebrow-to-heading": "--space-sm (close friends — kicker and heading)",
137
+ "heading-to-subheading": "--space-sm (close friends — heading and description)",
138
+ "header-to-accordion": "--space-lg (acquaintances — header block and question list)",
139
+ "questions-gap": "--space-sm (close friends — items in a list)"
140
+ },
141
+ "designGuidance": {
142
+ "surface": "The section itself has no background — it relies on the page surface. Each question is a bordered --color-surface card supplied by the Accordion organism, so the list reads as a contained stack against the page.",
143
+ "depth": "No shadows. Depth comes from the bordered question cards and the open/closed affordance, not elevation. The header is centered and the accordion is constrained to a readable measure so long FAQ lists stay scannable.",
144
+ "borders": "No section borders. Question borders (hairline, tinting to primary on hover) come from the Accordion.",
145
+ "interactivity": "Questions are native <details> disclosures — keyboard and screen-reader correct with no ARIA scaffolding. Choose 'single' mode for a focused reading experience or 'multi' for comparison.",
146
+ "bestPractices": [
147
+ "Provide real, useful answers in the items array — never ship an empty FAQ (the placeholder seeds four generic questions so the section is never blank on insert).",
148
+ "Use 'single' mode for long answers so only one occupies the viewport at a time.",
149
+ "Keep questions phrased the way a user would ask them — they double as scannable headings.",
150
+ "Add a contact link in the extras slot for questions the FAQ does not cover.",
151
+ "Set defaultOpen to the most common question to reduce clicks."
152
+ ]
153
+ },
154
+ "constraints": [
155
+ "Renders a semantic <section> with aria-labelledby linked to the heading",
156
+ "Composes the Accordion organism — questions are native <details>/<summary>, usable with zero JavaScript",
157
+ "items should be a non-empty array",
158
+ "Accordion is constrained to --measure-content and centered for readability",
159
+ "Layout is intrinsically fluid — no @media/@container breakpoints for stacking",
160
+ "Entrance animation observes the section root (motion-safe, SSR-safe)",
161
+ "destroy() disposes the composed Accordion, the heading/subheading atoms, the entrance observer, and empties the section"
162
+ ],
163
+ "a11y": [
164
+ "Renders semantic <section> element with aria-labelledby linked to heading",
165
+ "Questions use native <details>/<summary> — correct expanded/collapsed semantics with no added ARIA",
166
+ "Heading hierarchy: section heading at headingLevel",
167
+ "Question triggers are not wrapped in headings (avoids distorting the document outline)"
168
+ ],
169
+ "ai": {
170
+ "synonyms": [
171
+ "faq",
172
+ "frequently asked questions",
173
+ "questions",
174
+ "q&a",
175
+ "help",
176
+ "common questions",
177
+ "faqs"
178
+ ],
179
+ "avoid": [
180
+ "manual list of collapsibles — use FaqSection with an items array",
181
+ "div-based expanders with aria-expanded — FaqSection uses native <details> via Accordion"
182
+ ],
183
+ "patterns": [
184
+ "Basic FAQ: <FaqSection items=\"faqs\"/>",
185
+ "Single-open with eyebrow: <FaqSection eyebrow=\"'FAQ'\" heading=\"'Questions'\" mode=\"'single'\" items=\"faqs\"/>",
186
+ "First question open: <FaqSection items=\"faqs\" defaultOpen=\"0\"/>"
187
+ ]
188
+ },
189
+ "examples": [
190
+ {
191
+ "id": "basic-faq",
192
+ "title": "FAQ section with questions",
193
+ "pithy": "<FaqSection heading=\"'FAQ'\" items=\"faqs\"/>",
194
+ "assertions": [
195
+ "renders <section>",
196
+ "h2 section heading",
197
+ "aria-labelledby linked to heading",
198
+ "one <details> per question"
199
+ ]
200
+ }
201
+ ]
202
+ }