astryx-dracula 0.5.0 → 0.6.2

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 (129) hide show
  1. package/BRAND.md +3 -3
  2. package/README.md +7 -4
  3. package/USAGE.md +49 -49
  4. package/astryx-dracula.d.ts +2 -2
  5. package/astryx-dracula.js +25 -9
  6. package/astryx-dracula.variants.d.ts +2 -2
  7. package/astryx.integration.mjs +1 -1
  8. package/icons.mjs +21 -17
  9. package/icons.tsx +69 -62
  10. package/package.json +125 -120
  11. package/shared/auth-chrome-config.ts +6 -6
  12. package/shared/auth-chrome.tsx +143 -144
  13. package/shared/auth-copy.ts +14 -14
  14. package/shared/chaptered-doc-config.ts +48 -51
  15. package/shared/chaptered-doc.tsx +267 -289
  16. package/shared/chart-hues.ts +25 -10
  17. package/shared/chart-labels.tsx +31 -30
  18. package/shared/chart-legend.tsx +55 -56
  19. package/shared/chart-panel-style.ts +3 -3
  20. package/shared/data-bar.tsx +97 -102
  21. package/shared/format-money.ts +1 -1
  22. package/shared/gallery-image.ts +6 -6
  23. package/shared/login-demo.ts +1 -1
  24. package/shared/metric-card.tsx +101 -105
  25. package/shared/metric-delta.tsx +28 -27
  26. package/shared/order-desk.tsx +205 -216
  27. package/shared/revenue-chart.tsx +145 -165
  28. package/shared/scene-castle.tsx +206 -291
  29. package/shared/scene-frame.tsx +33 -32
  30. package/shared/scene-hues.ts +17 -17
  31. package/shared/scene-tile.tsx +88 -92
  32. package/shared/settings-data.ts +119 -125
  33. package/shared/settings-rows.tsx +122 -159
  34. package/shared/sparkline.tsx +75 -88
  35. package/shared/sso-icons.tsx +10 -22
  36. package/shared/stars.tsx +16 -25
  37. package/templates/ai-chat-landing.template.mjs +5 -4
  38. package/templates/ai-chat-landing.tsx +473 -460
  39. package/templates/ai-chat.template.mjs +5 -4
  40. package/templates/ai-chat.tsx +543 -612
  41. package/templates/blank.template.mjs +5 -4
  42. package/templates/blank.tsx +18 -14
  43. package/templates/centered-hero.template.mjs +5 -4
  44. package/templates/centered-hero.tsx +55 -68
  45. package/templates/classic-gallery.template.mjs +5 -4
  46. package/templates/classic-gallery.tsx +97 -104
  47. package/templates/contact-form.template.mjs +5 -4
  48. package/templates/contact-form.tsx +247 -282
  49. package/templates/dashboard-portfolio.template.mjs +5 -4
  50. package/templates/dashboard-portfolio.tsx +717 -548
  51. package/templates/dashboard.template.mjs +5 -4
  52. package/templates/dashboard.tsx +596 -567
  53. package/templates/detail-page.template.mjs +5 -4
  54. package/templates/detail-page.tsx +546 -603
  55. package/templates/documentation-design.template.mjs +5 -4
  56. package/templates/documentation-design.tsx +231 -243
  57. package/templates/documentation-technical.template.mjs +5 -4
  58. package/templates/documentation-technical.tsx +236 -239
  59. package/templates/documentation.template.mjs +5 -4
  60. package/templates/documentation.tsx +267 -279
  61. package/templates/editor.template.mjs +5 -4
  62. package/templates/editor.tsx +844 -877
  63. package/templates/file-explorer.template.mjs +5 -4
  64. package/templates/file-explorer.tsx +566 -590
  65. package/templates/form-two-column.template.mjs +5 -4
  66. package/templates/form-two-column.tsx +195 -210
  67. package/templates/gallery-hero.template.mjs +5 -4
  68. package/templates/gallery-hero.tsx +93 -114
  69. package/templates/ide.template.mjs +5 -4
  70. package/templates/ide.tsx +407 -453
  71. package/templates/incident-console.template.mjs +5 -4
  72. package/templates/incident-console.tsx +593 -575
  73. package/templates/kanban-board.template.mjs +5 -4
  74. package/templates/kanban-board.tsx +665 -683
  75. package/templates/library.template.mjs +5 -4
  76. package/templates/library.tsx +409 -430
  77. package/templates/login-card.template.mjs +5 -4
  78. package/templates/login-card.tsx +63 -72
  79. package/templates/login-split.template.mjs +5 -4
  80. package/templates/login-split.tsx +192 -193
  81. package/templates/login-sso.template.mjs +5 -4
  82. package/templates/login-sso.tsx +257 -258
  83. package/templates/login.template.mjs +5 -4
  84. package/templates/login.tsx +53 -49
  85. package/templates/messaging-shell.template.mjs +5 -4
  86. package/templates/messaging-shell.tsx +556 -574
  87. package/templates/mixed-gallery.template.mjs +5 -4
  88. package/templates/mixed-gallery.tsx +60 -58
  89. package/templates/payment-form.template.mjs +5 -4
  90. package/templates/payment-form.tsx +882 -991
  91. package/templates/product-detail.template.mjs +5 -4
  92. package/templates/product-detail.tsx +261 -272
  93. package/templates/product-gallery.template.mjs +5 -4
  94. package/templates/product-gallery.tsx +126 -137
  95. package/templates/product-tour.template.mjs +5 -4
  96. package/templates/product-tour.tsx +741 -773
  97. package/templates/settings-dialog.template.mjs +5 -4
  98. package/templates/settings-dialog.tsx +688 -717
  99. package/templates/settings-sidebar.template.mjs +5 -4
  100. package/templates/settings-sidebar.tsx +762 -807
  101. package/templates/settings.template.mjs +5 -4
  102. package/templates/settings.tsx +289 -304
  103. package/templates/shell-nav.template.mjs +5 -4
  104. package/templates/shell-nav.tsx +212 -219
  105. package/templates/shell-side-nav.template.mjs +5 -4
  106. package/templates/shell-side-nav.tsx +135 -157
  107. package/templates/shell-top-nav.template.mjs +5 -4
  108. package/templates/shell-top-nav.tsx +182 -203
  109. package/templates/side-gallery.template.mjs +5 -4
  110. package/templates/side-gallery.tsx +85 -90
  111. package/templates/table-grouped.template.mjs +5 -4
  112. package/templates/table-grouped.tsx +1000 -1053
  113. package/templates/table-page-chart.template.mjs +5 -4
  114. package/templates/table-page-chart.tsx +400 -398
  115. package/templates/table-page-heatmap-status.template.mjs +5 -4
  116. package/templates/table-page-heatmap-status.tsx +483 -512
  117. package/templates/table-page-shoe-store-heatmap.template.mjs +5 -4
  118. package/templates/table-page-shoe-store-heatmap.tsx +748 -746
  119. package/templates/table-page.template.mjs +5 -4
  120. package/templates/table-page.tsx +396 -405
  121. package/templates/table.template.mjs +5 -4
  122. package/templates/table.tsx +92 -93
  123. package/templates/tech-report.template.mjs +5 -4
  124. package/templates/tech-report.tsx +1316 -1304
  125. package/templates/theme-showcase.template.mjs +5 -4
  126. package/templates/theme-showcase.tsx +871 -951
  127. package/theme.css +35 -77
  128. package/theme.css.d.ts +9 -0
  129. package/tokens.css +373 -380
@@ -1,45 +1,47 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
- // XLE (canonical structure, validated with `bunx astryx layout check`):
2
+ // XLE (canonical structure of the tree below; the CLI had no XLE validator
3
+ // after `astryx layout` was removed in 0.7.0, so this is a reading aid and a
4
+ // human drift check — update it with the file, never alone):
3
5
  // Counts: 31 total, Core 18 / Layout 4 / Navigation 4 / Form 5. Derived at
4
6
  // render from COMPONENT_CATEGORIES, so these numerals must move together with
5
7
  // the array -- the gate in scripts/check.ts reads the rendered count, not this
6
8
  // comment.
7
- // L > LC > V[g=10] > (C[p=10] > (H[g=8 a=center] > (V[g=4] > Hd"The coven grimoire"[level=1 t=display-1] + Tx.lg"Every incantation in the Astryx spellbook"[t=large] + (H > B.primary"Enter the grimoire")))) + (V[g=4] > (H[j=between a=center] > Hd"Core"[level=2] + Tx"18 spells"[t=body]) + (H[j=between a=center] > Hd"Layout"[level=2] + Tx"4 spells"[t=body]) + (H[j=between a=center] > Hd"Navigation"[level=2] + Tx"4 spells"[t=body]) + (H[j=between a=center] > Hd"Form"[level=2] + Tx"5 spells"[t=body]) + (G[c={min:260} g=4] > (CC[p=4] > V[g=3] > C[p=0] + (V[g=1] > Tx"Avatar"[t=body] + Tx"Avatars represent"[t=body]))*4))
9
+ // L[h=fill mw=1200] > LC[p=8] > V[g=10] > (C.transparent[p=10] > (H[g=8 a=center] > (SI[fill] > V[g=4] > Hd"The coven grimoire"[level=1 t=display-1] + Tx.lg"Every incantation in the Astryx spellbook"[t=large] + (H > B.primary"Enter the grimoire")))) + (V[g=4] > (H[j=between a=center] > Hd"Core"[level=2] + Tx"18 spells"[t=body]) + (G[c={min:260} g=4] > (CC.transparent[p=4] > V[g=3] > (C.muted[p=0 h=160] > Scene{SceneTile}) + (V[g=1] > Tx"AppShell"[t=body] + Tx"AppShell provides"[t=body]))*18)) + (V[g=4] > (H[j=between a=center] > Hd"Layout"[level=2] + Tx"4 spells"[t=body]) + (G[c={min:260} g=4] > (CC.transparent[p=4] > V[g=3] > (C.muted[p=0 h=160] > Scene{SceneTile}) + (V[g=1] > Tx"Card"[t=body] + Tx"Cards group"[t=body]))*4)) + (V[g=4] > (H[j=between a=center] > Hd"Navigation"[level=2] + Tx"4 spells"[t=body]) + (G[c={min:260} g=4] > (CC.transparent[p=4] > V[g=3] > (C.muted[p=0 h=160] > Scene{SceneTile}) + (V[g=1] > Tx"Breadcrumbs"[t=body] + Tx"Breadcrumbs show"[t=body]))*4)) + (V[g=4] > (H[j=between a=center] > Hd"Form"[level=2] + Tx"5 spells"[t=body]) + (G[c={min:260} g=4] > (CC.transparent[p=4] > V[g=3] > (C.muted[p=0 h=160] > Scene{SceneTile}) + (V[g=1] > Tx"CheckboxInput"[t=body] + Tx"CheckboxInput renders"[t=body]))*5))
8
10
 
9
11
  /**
10
12
  * Documentation catalog — every component shelf in the grimoire. Frame-first layout (see `bunx astryx docs layout`): (Frame/responsive/container: see XLE header above.)
11
13
  */
12
14
 
13
- import type {CSSProperties} from 'react';
14
- import {Heading, Text} from '@astryxdesign/core/Text';
15
- import {Button} from '@astryxdesign/core/Button';
16
- import {Card} from '@astryxdesign/core/Card';
17
- import {ClickableCard} from '@astryxdesign/core/ClickableCard';
18
- import {HStack, VStack, StackItem} from '@astryxdesign/core/Stack';
19
- import {Layout, LayoutContent} from '@astryxdesign/core/Layout';
20
- import {Grid} from '@astryxdesign/core/Grid';
21
- import {SceneTile} from 'astryx-dracula/shared/scene-tile';
22
- import {galleryImageClip} from 'astryx-dracula/shared/gallery-image';
23
- import type {SceneHue} from 'astryx-dracula/shared/scene-hues';
15
+ import { Button } from "@astryxdesign/core/Button";
16
+ import { Card } from "@astryxdesign/core/Card";
17
+ import { ClickableCard } from "@astryxdesign/core/ClickableCard";
18
+ import { Grid } from "@astryxdesign/core/Grid";
19
+ import { Layout, LayoutContent } from "@astryxdesign/core/Layout";
20
+ import { HStack, StackItem, VStack } from "@astryxdesign/core/Stack";
21
+ import { Heading, Text } from "@astryxdesign/core/Text";
22
+ import { galleryImageClip } from "astryx-dracula/shared/gallery-image";
23
+ import type { SceneHue } from "astryx-dracula/shared/scene-hues";
24
+ import { SceneTile } from "astryx-dracula/shared/scene-tile";
25
+ import type { CSSProperties } from "react";
24
26
 
25
27
  // Negative margin offsets each card's 8px padding so the grid content stays
26
28
  // visually aligned while giving every card a padded hover/click target.
27
29
  const cardGrid: CSSProperties = {
28
- margin: 'calc(var(--spacing-2) * -1)',
30
+ margin: "calc(var(--spacing-2) * -1)",
29
31
  };
30
32
 
31
33
  // Same-route hash: demo links stay focusable anchors without escaping the
32
34
  // template through the hash router (bare "#" would drop back to the home page).
33
- const SELF_HASH = '#/templates/documentation';
35
+ const SELF_HASH = "#/templates/documentation";
34
36
 
35
37
  // Decorative accent per grimoire shelf. None of them is purple: the sigils
36
38
  // are not interactive, and purple belongs to the things that are. Art lives
37
39
  // in shared/scene-tile (lg fork: centered glyph on a flat field).
38
40
  const SHELF_HUES: Record<string, SceneHue> = {
39
- Core: 'var(--dracula-pink)',
40
- Layout: 'var(--dracula-cyan)',
41
- Navigation: 'var(--dracula-green)',
42
- Form: 'var(--dracula-yellow)',
41
+ Core: "var(--dracula-pink)",
42
+ Layout: "var(--dracula-cyan)",
43
+ Navigation: "var(--dracula-green)",
44
+ Form: "var(--dracula-yellow)",
43
45
  };
44
46
 
45
47
  // ---------------------------------------------------------------------------
@@ -47,181 +49,181 @@ const SHELF_HUES: Record<string, SceneHue> = {
47
49
  // ---------------------------------------------------------------------------
48
50
 
49
51
  const COMPONENT_CATEGORIES = [
50
- {
51
- label: 'Core',
52
- items: [
53
- {
54
- key: 'appshell',
55
- name: 'AppShell',
56
- desc: 'AppShell provides a foundational page layout with header, sidebar, and content regions. Use it to establish consistent structure across your application.',
57
- },
58
- {
59
- key: 'avatar',
60
- name: 'Avatar',
61
- desc: 'Avatars represent a person or entity with an image, initials, or icon. They are commonly used in user profiles, comments, and contact lists.',
62
- },
63
- {
64
- key: 'badge',
65
- name: 'Badge',
66
- desc: 'Badges display small counts or status labels. They can be attached to icons, buttons, or list items to surface key information at a glance.',
67
- },
68
- {
69
- key: 'banner',
70
- name: 'Banner',
71
- desc: 'Banners show important, non-modal messages at the top of a page or section. They communicate status, warnings, or promotional information.',
72
- },
73
- {
74
- key: 'button',
75
- name: 'Button',
76
- desc: 'Buttons let people take action. They can be used in forms, dialogs, and toolbars, or as standalone links.',
77
- },
78
- {
79
- key: 'calendar',
80
- name: 'Calendar',
81
- desc: 'Calendar provides a date-picking grid for selecting single dates or date ranges. It integrates with form fields for date input.',
82
- },
83
- {
84
- key: 'dialog',
85
- name: 'Dialog',
86
- desc: 'Dialogs are modal overlays that require user attention or action before continuing. They are used for confirmations, forms, and critical decisions.',
87
- },
88
- {
89
- key: 'dropdownmenu',
90
- name: 'DropdownMenu',
91
- desc: 'DropdownMenu presents a list of actions or options in a floating overlay. It is triggered by a button and supports nested submenus.',
92
- },
93
- {
94
- key: 'empty-state',
95
- name: 'EmptyState',
96
- desc: 'EmptyState provides a placeholder when there is no content to display. It guides users with a message, illustration, and optional call-to-action.',
97
- },
98
- {
99
- key: 'hovercard',
100
- name: 'HoverCard',
101
- desc: 'HoverCard shows a rich preview of content when users hover over a trigger element. It is ideal for previewing profiles, links, or details.',
102
- },
103
- {
104
- key: 'icon',
105
- name: 'Icon',
106
- desc: 'Icons are small visual symbols that represent actions, objects, or concepts. They improve scannability and reinforce meaning alongside text.',
107
- },
108
- {
109
- key: 'kbd',
110
- name: 'Kbd',
111
- desc: 'Kbd renders keyboard shortcut hints in a styled inline element. Use it to show users which key combinations perform specific actions.',
112
- },
113
- {
114
- key: 'link',
115
- name: 'Link',
116
- desc: 'Links provide navigation between pages or to external resources. They follow accessible anchor semantics with visual affordance.',
117
- },
118
- {
119
- key: 'list',
120
- name: 'List',
121
- desc: 'List displays a vertical set of related items. It supports selection, icons, and metadata for building menus, nav lists, and more.',
122
- },
123
- {
124
- key: 'popover',
125
- name: 'Popover',
126
- desc: 'Popover displays rich content in a floating panel anchored to a trigger element. It is used for forms, filters, and contextual tools.',
127
- },
128
- {
129
- key: 'table',
130
- name: 'Table',
131
- desc: 'Table displays structured data in rows and columns with support for sorting, selection, and custom cell rendering.',
132
- },
133
- {
134
- key: 'token',
135
- name: 'Token',
136
- desc: 'Tokens display compact metadata labels such as tags, categories, or filters. They can be dismissible and support selection state.',
137
- },
138
- {
139
- key: 'tooltip',
140
- name: 'Tooltip',
141
- desc: 'Tooltips show concise helper text when users hover over or focus an element. They clarify icons, truncated labels, and controls.',
142
- },
143
- ],
144
- },
145
- {
146
- label: 'Layout',
147
- items: [
148
- {
149
- key: 'card',
150
- name: 'Card',
151
- desc: 'Cards group related content and actions in a contained surface. They can include headers, media, body text, and action bars.',
152
- },
153
- {
154
- key: 'divider',
155
- name: 'Divider',
156
- desc: 'Dividers separate content into distinct sections with a subtle or strong horizontal line. They can optionally include a label.',
157
- },
158
- {
159
- key: 'grid',
160
- name: 'Grid',
161
- desc: 'Grid provides a CSS grid-based layout container with configurable columns, rows, and gap. It simplifies responsive multi-column designs.',
162
- },
163
- {
164
- key: 'stack',
165
- name: 'Stack',
166
- desc: 'Stack arranges child elements in a row or column with consistent gap spacing. It is the primary tool for one-dimensional layout composition.',
167
- },
168
- ],
169
- },
170
- {
171
- label: 'Navigation',
172
- items: [
173
- {
174
- key: 'breadcrumbs',
175
- name: 'Breadcrumbs',
176
- desc: "Breadcrumbs show the user's current location within a navigation hierarchy. They provide quick links back to parent pages.",
177
- },
178
- {
179
- key: 'sidenav',
180
- name: 'SideNav',
181
- desc: 'SideNav renders a vertical navigation panel with links, sections, and collapsible groups. It is used as the primary nav in dashboard layouts.',
182
- },
183
- {
184
- key: 'tablist',
185
- name: 'TabList',
186
- desc: 'TabList switches between content views using a horizontal row of tabs. Only one tab is active at a time, and content changes without a page reload.',
187
- },
188
- {
189
- key: 'topnav',
190
- name: 'TopNav',
191
- desc: 'TopNav provides an app-level navigation bar across the top of the page. It holds branding, primary links, search, and user actions.',
192
- },
193
- ],
194
- },
195
- {
196
- label: 'Form',
197
- items: [
198
- {
199
- key: 'checkboxinput',
200
- name: 'CheckboxInput',
201
- desc: 'CheckboxInput renders a single checkbox with a label. It is used for boolean opt-in choices like terms acceptance or feature toggles.',
202
- },
203
- {
204
- key: 'selector',
205
- name: 'Selector',
206
- desc: 'Selector lets users pick a single item from a dropdown list. It supports search, grouping, and custom option rendering.',
207
- },
208
- {
209
- key: 'switch',
210
- name: 'Switch',
211
- desc: 'Switch toggles a setting between on and off states with immediate effect. It is used for preferences, feature flags, and real-time controls.',
212
- },
213
- {
214
- key: 'textinput',
215
- name: 'TextInput',
216
- desc: 'TextInput is a single-line text field for short user input like names, emails, and search queries. It supports icons, prefixes, and validation.',
217
- },
218
- {
219
- key: 'typeahead',
220
- name: 'Typeahead',
221
- desc: 'Typeahead provides an autocomplete search input that suggests results as the user types. It supports async data sources and custom rendering.',
222
- },
223
- ],
224
- },
52
+ {
53
+ label: "Core",
54
+ items: [
55
+ {
56
+ key: "appshell",
57
+ name: "AppShell",
58
+ desc: "AppShell provides a foundational page layout with header, sidebar, and content regions. Use it to establish consistent structure across your application.",
59
+ },
60
+ {
61
+ key: "avatar",
62
+ name: "Avatar",
63
+ desc: "Avatars represent a person or entity with an image, initials, or icon. They are commonly used in user profiles, comments, and contact lists.",
64
+ },
65
+ {
66
+ key: "badge",
67
+ name: "Badge",
68
+ desc: "Badges display small counts or status labels. They can be attached to icons, buttons, or list items to surface key information at a glance.",
69
+ },
70
+ {
71
+ key: "banner",
72
+ name: "Banner",
73
+ desc: "Banners show important, non-modal messages at the top of a page or section. They communicate status, warnings, or promotional information.",
74
+ },
75
+ {
76
+ key: "button",
77
+ name: "Button",
78
+ desc: "Buttons let people take action. They can be used in forms, dialogs, and toolbars, or as standalone links.",
79
+ },
80
+ {
81
+ key: "calendar",
82
+ name: "Calendar",
83
+ desc: "Calendar provides a date-picking grid for selecting single dates or date ranges. It integrates with form fields for date input.",
84
+ },
85
+ {
86
+ key: "dialog",
87
+ name: "Dialog",
88
+ desc: "Dialogs are modal overlays that require user attention or action before continuing. They are used for confirmations, forms, and critical decisions.",
89
+ },
90
+ {
91
+ key: "dropdownmenu",
92
+ name: "DropdownMenu",
93
+ desc: "DropdownMenu presents a list of actions or options in a floating overlay. It is triggered by a button and supports nested submenus.",
94
+ },
95
+ {
96
+ key: "empty-state",
97
+ name: "EmptyState",
98
+ desc: "EmptyState provides a placeholder when there is no content to display. It guides users with a message, illustration, and optional call-to-action.",
99
+ },
100
+ {
101
+ key: "hovercard",
102
+ name: "HoverCard",
103
+ desc: "HoverCard shows a rich preview of content when users hover over a trigger element. It is ideal for previewing profiles, links, or details.",
104
+ },
105
+ {
106
+ key: "icon",
107
+ name: "Icon",
108
+ desc: "Icons are small visual symbols that represent actions, objects, or concepts. They improve scannability and reinforce meaning alongside text.",
109
+ },
110
+ {
111
+ key: "kbd",
112
+ name: "Kbd",
113
+ desc: "Kbd renders keyboard shortcut hints in a styled inline element. Use it to show users which key combinations perform specific actions.",
114
+ },
115
+ {
116
+ key: "link",
117
+ name: "Link",
118
+ desc: "Links provide navigation between pages or to external resources. They follow accessible anchor semantics with visual affordance.",
119
+ },
120
+ {
121
+ key: "list",
122
+ name: "List",
123
+ desc: "List displays a vertical set of related items. It supports selection, icons, and metadata for building menus, nav lists, and more.",
124
+ },
125
+ {
126
+ key: "popover",
127
+ name: "Popover",
128
+ desc: "Popover displays rich content in a floating panel anchored to a trigger element. It is used for forms, filters, and contextual tools.",
129
+ },
130
+ {
131
+ key: "table",
132
+ name: "Table",
133
+ desc: "Table displays structured data in rows and columns with support for sorting, selection, and custom cell rendering.",
134
+ },
135
+ {
136
+ key: "token",
137
+ name: "Token",
138
+ desc: "Tokens display compact metadata labels such as tags, categories, or filters. They can be dismissible and support selection state.",
139
+ },
140
+ {
141
+ key: "tooltip",
142
+ name: "Tooltip",
143
+ desc: "Tooltips show concise helper text when users hover over or focus an element. They clarify icons, truncated labels, and controls.",
144
+ },
145
+ ],
146
+ },
147
+ {
148
+ label: "Layout",
149
+ items: [
150
+ {
151
+ key: "card",
152
+ name: "Card",
153
+ desc: "Cards group related content and actions in a contained surface. They can include headers, media, body text, and action bars.",
154
+ },
155
+ {
156
+ key: "divider",
157
+ name: "Divider",
158
+ desc: "Dividers separate content into distinct sections with a subtle or strong horizontal line. They can optionally include a label.",
159
+ },
160
+ {
161
+ key: "grid",
162
+ name: "Grid",
163
+ desc: "Grid provides a CSS grid-based layout container with configurable columns, rows, and gap. It simplifies responsive multi-column designs.",
164
+ },
165
+ {
166
+ key: "stack",
167
+ name: "Stack",
168
+ desc: "Stack arranges child elements in a row or column with consistent gap spacing. It is the primary tool for one-dimensional layout composition.",
169
+ },
170
+ ],
171
+ },
172
+ {
173
+ label: "Navigation",
174
+ items: [
175
+ {
176
+ key: "breadcrumbs",
177
+ name: "Breadcrumbs",
178
+ desc: "Breadcrumbs show the user's current location within a navigation hierarchy. They provide quick links back to parent pages.",
179
+ },
180
+ {
181
+ key: "sidenav",
182
+ name: "SideNav",
183
+ desc: "SideNav renders a vertical navigation panel with links, sections, and collapsible groups. It is used as the primary nav in dashboard layouts.",
184
+ },
185
+ {
186
+ key: "tablist",
187
+ name: "TabList",
188
+ desc: "TabList switches between content views using a horizontal row of tabs. Only one tab is active at a time, and content changes without a page reload.",
189
+ },
190
+ {
191
+ key: "topnav",
192
+ name: "TopNav",
193
+ desc: "TopNav provides an app-level navigation bar across the top of the page. It holds branding, primary links, search, and user actions.",
194
+ },
195
+ ],
196
+ },
197
+ {
198
+ label: "Form",
199
+ items: [
200
+ {
201
+ key: "checkboxinput",
202
+ name: "CheckboxInput",
203
+ desc: "CheckboxInput renders a single checkbox with a label. It is used for boolean opt-in choices like terms acceptance or feature toggles.",
204
+ },
205
+ {
206
+ key: "selector",
207
+ name: "Selector",
208
+ desc: "Selector lets users pick a single item from a dropdown list. It supports search, grouping, and custom option rendering.",
209
+ },
210
+ {
211
+ key: "switch",
212
+ name: "Switch",
213
+ desc: "Switch toggles a setting between on and off states with immediate effect. It is used for preferences, feature flags, and real-time controls.",
214
+ },
215
+ {
216
+ key: "textinput",
217
+ name: "TextInput",
218
+ desc: "TextInput is a single-line text field for short user input like names, emails, and search queries. It supports icons, prefixes, and validation.",
219
+ },
220
+ {
221
+ key: "typeahead",
222
+ name: "Typeahead",
223
+ desc: "Typeahead provides an autocomplete search input that suggests results as the user types. It supports async data sources and custom rendering.",
224
+ },
225
+ ],
226
+ },
225
227
  ];
226
228
 
227
229
  // Every count in this template is DERIVED from the array above, never written as
@@ -231,8 +233,8 @@ const COMPONENT_CATEGORIES = [
231
233
  // "twenty-eight" against 31 entries and the XLE header said 15 for a category
232
234
  // of 18.
233
235
  const COMPONENT_TOTAL = COMPONENT_CATEGORIES.reduce(
234
- (sum, category) => sum + category.items.length,
235
- 0,
236
+ (sum, category) => sum + category.items.length,
237
+ 0,
236
238
  );
237
239
 
238
240
  // ---------------------------------------------------------------------------
@@ -240,88 +242,74 @@ const COMPONENT_TOTAL = COMPONENT_CATEGORIES.reduce(
240
242
  // ---------------------------------------------------------------------------
241
243
 
242
244
  export default function DocumentationCatalog() {
243
- return (
244
- <Layout
245
- height="fill"
246
- contentWidth={1200}
247
- content={
248
- <LayoutContent padding={8}>
249
- <VStack gap={10}>
250
- <Card variant="transparent" padding={10}>
251
- <HStack gap={8} vAlign="center">
252
- <StackItem size="fill">
253
- <VStack gap={4}>
254
- <Heading level={1} type="display-1">
255
- The coven grimoire
256
- </Heading>
257
- <Text type="large" weight="normal" color="secondary">
258
- Every incantation in the Astryx spellbook, with{' '}
259
- {COMPONENT_TOTAL} components for building beautiful,
260
- accessible products after dark.
261
- </Text>
262
- <HStack>
263
- <Button
264
- label="Enter the grimoire"
265
- variant="primary"
266
- />
267
- </HStack>
268
- </VStack>
269
- </StackItem>
270
- </HStack>
271
- </Card>
245
+ return (
246
+ <Layout
247
+ height="fill"
248
+ contentWidth={1200}
249
+ content={
250
+ <LayoutContent padding={8}>
251
+ <VStack gap={10}>
252
+ <Card variant="transparent" padding={10}>
253
+ <HStack gap={8} vAlign="center">
254
+ <StackItem size="fill">
255
+ <VStack gap={4}>
256
+ <Heading level={1} type="display-1">
257
+ The coven grimoire
258
+ </Heading>
259
+ <Text type="large" weight="normal" color="secondary">
260
+ Every incantation in the Astryx spellbook, with {COMPONENT_TOTAL} components
261
+ for building beautiful, accessible products after dark.
262
+ </Text>
263
+ <HStack>
264
+ <Button label="Enter the grimoire" variant="primary" />
265
+ </HStack>
266
+ </VStack>
267
+ </StackItem>
268
+ </HStack>
269
+ </Card>
272
270
 
273
- {COMPONENT_CATEGORIES.map(category => (
274
- <VStack key={category.label} gap={4}>
275
- <HStack justify="between" vAlign="center">
276
- <Heading level={2}>{category.label}</Heading>
277
- <Text
278
- type="body"
279
- color="secondary"
280
- hasTabularNumbers>
281
- {category.items.length}{' '}
282
- {category.items.length === 1 ? 'spell' : 'spells'}
283
- </Text>
284
- </HStack>
285
- <Grid columns={{minWidth: 260}} gap={4} style={cardGrid}>
286
- {category.items.map(item => (
287
- <ClickableCard
288
- key={item.key}
289
- label={`Open ${item.name}`}
290
- href={SELF_HASH}
291
- variant="transparent"
292
- padding={4}>
293
- <VStack gap={3}>
294
- <Card
295
- variant="muted"
296
- padding={0}
297
- minHeight={160}
298
- style={galleryImageClip}>
299
- <SceneTile
300
- label={`${item.name} sigil`}
301
- hue={
302
- SHELF_HUES[category.label] ??
303
- 'var(--dracula-comment)'
304
- }
305
- size="lg"
306
- />
307
- </Card>
308
- <VStack gap={1}>
309
- <Text type="body" weight="semibold">
310
- {item.name}
311
- </Text>
312
- <Text type="body" color="secondary" maxLines={3}>
313
- {item.desc}
314
- </Text>
315
- </VStack>
316
- </VStack>
317
- </ClickableCard>
318
- ))}
319
- </Grid>
320
- </VStack>
321
- ))}
322
- </VStack>
323
- </LayoutContent>
324
- }
325
- />
326
- );
271
+ {COMPONENT_CATEGORIES.map((category) => (
272
+ <VStack key={category.label} gap={4}>
273
+ <HStack justify="between" vAlign="center">
274
+ <Heading level={2}>{category.label}</Heading>
275
+ <Text type="body" color="secondary" hasTabularNumbers>
276
+ {category.items.length} {category.items.length === 1 ? "spell" : "spells"}
277
+ </Text>
278
+ </HStack>
279
+ <Grid columns={{ minWidth: 260 }} gap={4} style={cardGrid}>
280
+ {category.items.map((item) => (
281
+ <ClickableCard
282
+ key={item.key}
283
+ label={`Open ${item.name}`}
284
+ href={SELF_HASH}
285
+ variant="transparent"
286
+ padding={4}
287
+ >
288
+ <VStack gap={3}>
289
+ <Card variant="muted" padding={0} minHeight={160} style={galleryImageClip}>
290
+ <SceneTile
291
+ label={`${item.name} sigil`}
292
+ hue={SHELF_HUES[category.label] ?? "var(--dracula-comment)"}
293
+ size="lg"
294
+ />
295
+ </Card>
296
+ <VStack gap={1}>
297
+ <Text type="body" weight="semibold">
298
+ {item.name}
299
+ </Text>
300
+ <Text type="body" color="secondary" maxLines={3}>
301
+ {item.desc}
302
+ </Text>
303
+ </VStack>
304
+ </VStack>
305
+ </ClickableCard>
306
+ ))}
307
+ </Grid>
308
+ </VStack>
309
+ ))}
310
+ </VStack>
311
+ </LayoutContent>
312
+ }
313
+ />
314
+ );
327
315
  }
@@ -1,6 +1,7 @@
1
1
  export default {
2
- type: 'page',
3
- name: 'Page Editor',
4
- description: 'Block builder with sidebar config and preview',
5
- category: 'tooling',
2
+ type: "page",
3
+ name: "Page Editor",
4
+ description: "Block builder with sidebar config and preview",
5
+ keywords: ["editor", "ide", "code", "workspace", "files", "developer"],
6
+ category: "tooling",
6
7
  };