astryx-dracula 0.2.0 → 0.2.1

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 (45) hide show
  1. package/README.md +6 -0
  2. package/package.json +1 -1
  3. package/templates/ai-chat-landing.tsx +2 -0
  4. package/templates/ai-chat.tsx +5 -1
  5. package/templates/blank.tsx +2 -0
  6. package/templates/centered-hero.tsx +2 -0
  7. package/templates/classic-gallery.tsx +2 -0
  8. package/templates/contact-form.tsx +5 -3
  9. package/templates/dashboard-portfolio.tsx +5 -3
  10. package/templates/dashboard.tsx +6 -4
  11. package/templates/detail-page.tsx +11 -9
  12. package/templates/documentation-design.tsx +5 -3
  13. package/templates/documentation-technical.tsx +5 -3
  14. package/templates/documentation.tsx +3 -1
  15. package/templates/editor.tsx +10 -8
  16. package/templates/file-explorer.tsx +3 -1
  17. package/templates/form-two-column.tsx +3 -1
  18. package/templates/gallery-hero.tsx +2 -0
  19. package/templates/ide.tsx +6 -2
  20. package/templates/incident-console.tsx +3 -1
  21. package/templates/kanban-board.tsx +2 -0
  22. package/templates/library.tsx +2 -0
  23. package/templates/login-card.tsx +2 -0
  24. package/templates/login-split.tsx +7 -9
  25. package/templates/login-sso.tsx +5 -7
  26. package/templates/login.tsx +2 -0
  27. package/templates/messaging-shell.tsx +2 -0
  28. package/templates/mixed-gallery.tsx +3 -1
  29. package/templates/payment-form.tsx +2 -0
  30. package/templates/product-detail.tsx +4 -2
  31. package/templates/product-gallery.tsx +2 -0
  32. package/templates/settings-dialog.tsx +15 -9
  33. package/templates/settings-sidebar.tsx +2 -0
  34. package/templates/settings.tsx +2 -0
  35. package/templates/shell-nav.tsx +2 -0
  36. package/templates/shell-side-nav.tsx +2 -0
  37. package/templates/shell-top-nav.tsx +2 -0
  38. package/templates/side-gallery.tsx +3 -1
  39. package/templates/table-grouped.tsx +3 -1
  40. package/templates/table-page-chart.tsx +7 -1
  41. package/templates/table-page-heatmap-status.tsx +2 -0
  42. package/templates/table-page-shoe-store-heatmap.tsx +7 -1
  43. package/templates/table-page.tsx +2 -0
  44. package/templates/table.tsx +2 -0
  45. package/templates/theme-showcase.tsx +15 -13
package/README.md CHANGED
@@ -62,3 +62,9 @@ demo/ showcase source, deployed to GitHub Pages
62
62
  | `bun run theme:build`| Rebuild `theme.css` from the source |
63
63
  | `bun run theme:check`| Fail if committed theme outputs are stale |
64
64
  | `bun run build` | Typecheck plus showcase build |
65
+
66
+ ## Attribution & License
67
+
68
+ - **Astryx Design System**: Created by the Astryx team at Meta Platforms, Inc. under the [MIT License](https://github.com/facebook/astryx/blob/main/LICENSE). The 43 template files in `templates/` are derived from Astryx's open source page templates and adapted for the Dracula brand (pure Dracula spec retokening, recharts replaced with zero-dependency inline SVGs, heroicons mapped to Lucide, XLE/XLO structural expression headers, and responsive layout hardening).
69
+ - **Dracula Theme**: Color palette and specification by [Zeno Rocha and the Dracula Theme community](https://draculatheme.com).
70
+ - **Package & Additions**: Released under the [MIT License](LICENSE).
package/package.json CHANGED
@@ -64,5 +64,5 @@
64
64
  "@astryxdesign/cli"
65
65
  ],
66
66
  "type": "module",
67
- "version": "0.2.0"
67
+ "version": "0.2.1"
68
68
  }
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > LC > V[g=8 a=center] > (V[g=1] > (H[g=2 a=center] > Ic + Tx.lg"Hi, Vlad") + Hd"Where should we start?"[level=1 type=display-2]) + ChC"Ask anything" + (V[g=6] > (TgG"Category" > Tg"Writing"*4) + (G[c={min:280} g=3] > (CC[p=4] > V[g=0.5] > Hd"Draft"[level=4] + Tx"Compose"[t=body])*4))
2
4
 
3
5
  import {useRef, useState, type CSSProperties} from 'react';
4
6
 
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > LC[p=0] > H > (SI[fill] > ChL > ChML > (ChM > ChB)*4 + ChC"Ask a follow up...") + (C.transparent > Tbar + S.section > MD) ;; Dlg#artifact[variant=fullscreen] > L > (DH"JWT Token Refresh" + (LC[p=0] > S.section > MD))
2
4
 
3
5
  import {useRef, useState, type CSSProperties} from 'react';
4
6
 
@@ -121,7 +123,7 @@ const AI_CHAT_CSS = `
121
123
  // Artifact content
122
124
 
123
125
  const MENTION_TOKENS = [
124
- {value: '@agent', label: '@Agent', variant: 'blue' as const},
126
+ {value: '@agent', label: '@Agent', variant: 'cyan' as const},
125
127
  ];
126
128
 
127
129
  const ARTIFACT_TITLE = 'JWT Token Refresh: Design & Rollout';
@@ -440,6 +442,7 @@ The fix is to catch \`TokenExpiredError\` specifically and attempt a refresh bef
440
442
  <CodeBlock
441
443
  title="middleware.ts"
442
444
  language="typescript"
445
+ width="100%"
443
446
  code={`async function authMiddleware(req: Request) {
444
447
  try {
445
448
  const decoded = validateToken(req.headers.authorization);
@@ -556,6 +559,7 @@ The fix is to catch \`TokenExpiredError\` specifically and attempt a refresh bef
556
559
  <CodeBlock
557
560
  title="middleware.test.ts"
558
561
  language="typescript"
562
+ width="100%"
559
563
  code={`describe('authMiddleware', () => {
560
564
  it('refreshes an expired token silently', async () => {
561
565
  const expiredToken = createExpiredJWT(mockUser);
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > LC > Tx.lg"A blank crypt awaits its story"
2
4
 
3
5
  import {Layout, LayoutContent} from '@astryxdesign/core/Layout';
4
6
  import {Text} from '@astryxdesign/core/Text';
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > LC > (V[g6 a=center] > Hd"Hero"[level=1] + Tx"Remit"[t=body] + (H[j=center g3] > B.primary"CTA" + B"Secondary"))
2
4
 
3
5
  import type {CSSProperties} from 'react';
4
6
  import {VStack, HStack, Layout, LayoutContent} from '@astryxdesign/core/Layout';
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > LC[p=0] > Ctr > V[g=8] > (V[g=4 a=center] > (V[g=2 a=center] > Hd"Hung after dark"[level=1] + Tx"A coven-curated wall"[t=body]) + (TL > Tab"All"! + Tab"Lifestyle" + Tab"Scenery" + Tab"Home") + Tx"10 pieces on the wall"[t=supporting]) + (G[g=4] > (C[p=0] > AR)*6)
2
4
 
3
5
  import {useState, type CSSProperties} from 'react';
4
6
  import {VStack, Layout, LayoutContent} from '@astryxdesign/core/Layout';
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // Ctr > V[a=center] > S.section[p=6] > V[g=6] > (V[g=2 a=center] > Hd"Let's brew after dark"[level=1] + Tx"Tell us a bit"[t=body]) + (G[c={min:200} g=4] > (C > V[g=3] > Ic + (V[g=1] > Tx"Title"[t=body] + Tx"Desc"[t=supporting]))*3) + (G[c={min:260} g=4] > TI"Full Name" + TI"Email") + (G[c={min:260} g=4] > TI"Company" + TI"Phone") + D + (V[g=5] > (V[g=2] > Tx"Goals"[t=label] + (H[g=2] > Tk"Goal"*3)) + SE"Timeline" + SE"Budget" + (RL"Source" > RLI*5) + TA"Notes" + CB"Decision maker") + (V[g=3] > B.primary"Submit" + (H[j=center g=1] > Tx[t=supporting] > Lk"Privacy Policy"))
2
4
 
3
5
  import {useState} from 'react';
4
6
  import {VStack, HStack} from '@astryxdesign/core/Layout';
@@ -7,7 +9,7 @@ import {Section} from '@astryxdesign/core/Section';
7
9
  import {Grid} from '@astryxdesign/core/Grid';
8
10
  import {Card} from '@astryxdesign/core/Card';
9
11
  import {Button} from '@astryxdesign/core/Button';
10
- import {Text} from '@astryxdesign/core/Text';
12
+ import {Text, Heading} from '@astryxdesign/core/Text';
11
13
  import {Icon} from '@astryxdesign/core/Icon';
12
14
  import {TextInput} from '@astryxdesign/core/TextInput';
13
15
  import {Selector} from '@astryxdesign/core/Selector';
@@ -112,9 +114,9 @@ export default function ContactForm() {
112
114
  <VStack gap={6}>
113
115
  {/* Header */}
114
116
  <VStack gap={2} hAlign="center" style={{textAlign: 'center'}}>
115
- <Text type="display-1" weight="bold">
117
+ <Heading level={1} type="display-1">
116
118
  Let&apos;s brew after dark
117
- </Text>
119
+ </Heading>
118
120
  <Text type="body" color="secondary">
119
121
  Tell us a bit about what you&apos;re summoning — the coven
120
122
  would love to help it take flight.
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > LC > V[g=6] > (H[j=between a=center] > Hd"The night vault"[level=1] + DM"1 year") + (G[c=4 g=4] > (C > V[g=2] > Hd"Label"[level=4] + (H[g=2] > Hd"$1.2M"[level=2] + Tx"+2.4%"[t=body]))*4) + (G[c=4 g=4] > (GS[c=3] > C > V[g=4] > (H[j=between] > Hd"Vault value"[level=3] + Lk"View details") + AR) + (GS[c=1] > C > V[g=4] > (H[j=between] > Hd"Top holdings"[level=3] + Lk"View all") + UL)) + D + (H[j=between a=start] > (V[g=1] > Hd"Market at midnight"[level=2] + Tx"Past 24 hours under moonlight"[t=body]) + B"View more") + (G[c=3 g=4] > (C > V[g=3] > Hd"Index"[level=4] + Tx"$5,200"[t=body])*3) + (C > V[g=4] > Hd"Trending Stocks"[level=3] + T)
2
4
 
3
5
  import {useState} from 'react';
4
6
 
@@ -493,7 +495,7 @@ function MarketCard({
493
495
  </VStack>
494
496
  <Sparkline data={spark} positive={positive} />
495
497
  <HStack gap={3} vAlign="center">
496
- <Text type="display-3" weight="bold" hasTabularNumbers>
498
+ <Text type="display-3" weight="semibold" hasTabularNumbers>
497
499
  {price}
498
500
  </Text>
499
501
  <HStack gap={1} vAlign="center">
@@ -560,7 +562,7 @@ const trendingColumns: TableColumn<StockRow>[] = [
560
562
  header: 'Ticker',
561
563
  width: proportional(1),
562
564
  renderCell: (row: StockRow) => (
563
- <Text type="body" weight="bold">
565
+ <Text type="body" weight="semibold">
564
566
  {row.ticker}
565
567
  </Text>
566
568
  ),
@@ -665,7 +667,7 @@ function AssetRow({
665
667
  }) {
666
668
  return (
667
669
  <ListItem
668
- label={<Text weight="bold">{ticker}</Text>}
670
+ label={<Text weight="semibold">{ticker}</Text>}
669
671
  description={name}
670
672
  href="#/templates/dashboard-portfolio"
671
673
  startContent={<Avatar name={ticker} size="md" />}
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > LC[p=6] > V[g=6] > (V[g=6] > (H[j=between a=center] > Hd"Awake after dark"[level=3] + B.secondary"Reload") + C[p=3]) + (G[c=4 g=4] > C*4) + D + (H[j=between a=center] > Hd"Night denizens"[level=3] + B.secondary"View more") + (G[c=2 g=4] > C*2) + D + (H[j=between a=center] > Hd"Engagement"[level=3] + B.secondary"View more") + (G[c=2 g=4] > (C > V[g=6] > (H[j=between a=center] > Hd"Top pages"[level=4] + Lk"All pages") + T)*2)
2
4
 
3
5
  import {VStack, HStack, Layout, LayoutContent} from '@astryxdesign/core/Layout';
4
6
  import {Text, Heading} from '@astryxdesign/core/Text';
@@ -192,7 +194,7 @@ const regionData = [
192
194
  {
193
195
  label: 'NORAM',
194
196
  value: 38,
195
- color: 'var(--dracula-comment)',
197
+ color: 'var(--dracula-cyan)',
196
198
  },
197
199
  {
198
200
  label: 'EMEA',
@@ -209,14 +211,14 @@ const regionData = [
209
211
  value: 8,
210
212
  color: 'var(--dracula-purple)',
211
213
  },
212
- {label: 'Other', value: 4, color: 'var(--dracula-selection)'},
214
+ {label: 'Other', value: 4, color: 'var(--dracula-comment)'},
213
215
  ];
214
216
 
215
217
  const roleData = [
216
218
  {
217
219
  label: 'Engineer',
218
220
  value: 45,
219
- color: 'var(--dracula-comment)',
221
+ color: 'var(--dracula-cyan)',
220
222
  },
221
223
  {
222
224
  label: 'Manager',
@@ -233,7 +235,7 @@ const roleData = [
233
235
  value: 12,
234
236
  color: 'var(--dracula-purple)',
235
237
  },
236
- {label: 'Other', value: 8, color: 'var(--dracula-selection)'},
238
+ {label: 'Other', value: 8, color: 'var(--dracula-comment)'},
237
239
  ];
238
240
 
239
241
  // Engagement — Top pages
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > (LH > V[g=4] > (H[j=between] > Lk"All orders" + (H[g=2] > B"Restock" + B"Edit")) + (H[g=2 a=center] > Hd"#1001"[level=1] + Bd.warning"Unfulfilled") + (H[j=between] > TL > Tab"Details"! + Tab"Invoices" + Tab"Timeline")) + (LC > V[g=4] > (C > V[g=4] > (H[j=between] > Hd"Items"[level=2] + B"Fulfill item") + UL) + (C > V[g=4] > (H[j=between] > Hd"Invoice"[level=2] + B"Send Invoice") + ML) + (S > V[g=4] > Hd"Timeline"[level=2] + UL)) + (LP[w=320] > V[g=4] > Col"Notes" + Col"Customer" + Col"Fraud Analysis")
2
4
 
3
5
  import {useState} from 'react';
4
6
  import {useMediaQuery} from '@astryxdesign/core/hooks';
@@ -209,7 +211,7 @@ function PageHeader({
209
211
  <HStack gap={4} vAlign="start">
210
212
  <StackItem size="fill">
211
213
  <VStack gap={0}>
212
- <Link href="#/templates/detail-page" color="secondary">
214
+ <Link href="#/templates/detail-page">
213
215
  <HStack gap={1} vAlign="center">
214
216
  <Icon icon={ArrowLeft} size="sm" color="inherit" />
215
217
  All orders
@@ -234,7 +236,7 @@ function PageHeader({
234
236
  </HStack>
235
237
  <HStack gap={1} vAlign="center">
236
238
  <Bullet />
237
- <Badge variant="warning" label="Unfulfilled" />
239
+ <Badge variant="orange" label="Unfulfilled" />
238
240
  </HStack>
239
241
  <HStack gap={1} vAlign="center">
240
242
  <Bullet />
@@ -256,7 +258,7 @@ function PageHeader({
256
258
  </HStack>
257
259
  <HStack gap={1} vAlign="center">
258
260
  <Bullet />
259
- <Link href="#/templates/detail-page" color="secondary">
261
+ <Link href="#/templates/detail-page">
260
262
  See all
261
263
  </Link>
262
264
  </HStack>
@@ -328,7 +330,7 @@ function ItemsCard() {
328
330
  <StackItem size="fill">
329
331
  <HStack gap={2} vAlign="center">
330
332
  <Heading level={2}>Items</Heading>
331
- <Badge variant="warning" label="Unfulfilled" />
333
+ <Badge variant="orange" label="Unfulfilled" />
332
334
  </HStack>
333
335
  </StackItem>
334
336
  <HStack gap={2}>
@@ -363,7 +365,7 @@ function ItemsCard() {
363
365
  <VStack gap={0} hAlign="end">
364
366
  <Text
365
367
  type="body"
366
- weight="bold"
368
+ weight="semibold"
367
369
  maxLines={1}
368
370
  hasTabularNumbers>
369
371
  {fmt(product.price * product.qty)}
@@ -394,7 +396,7 @@ function InvoiceCard() {
394
396
  <StackItem size="fill">
395
397
  <HStack gap={2} vAlign="center">
396
398
  <Heading level={2}>Invoice</Heading>
397
- <Badge variant="success" label="Paid" />
399
+ <Badge variant="green" label="Paid" />
398
400
  </HStack>
399
401
  </StackItem>
400
402
  <HStack gap={2}>
@@ -453,7 +455,7 @@ function InvoiceCard() {
453
455
  <MetadataListItem label="Total">
454
456
  <HStack>
455
457
  <StackItem size="fill" />
456
- <Text type="body" weight="bold" hasTabularNumbers>
458
+ <Text type="body" weight="semibold" hasTabularNumbers>
457
459
  {fmt(TOTAL)}
458
460
  </Text>
459
461
  </HStack>
@@ -507,7 +509,7 @@ function TimelineSection() {
507
509
  <VStack gap={2}>
508
510
  <Card variant="muted" padding={3}>
509
511
  <VStack gap={1}>
510
- <Text type="body" weight="bold">
512
+ <Text type="body" weight="semibold">
511
513
  {item.user}
512
514
  </Text>
513
515
  <Text type="body">{item.text}</Text>
@@ -581,7 +583,7 @@ function PanelContent() {
581
583
  Customer is a repeat buyer — 3rd order this quarter. Prefers
582
584
  moonlight and sage glazes. Requested gift wrapping for the mug set.
583
585
  Ships to a residential address in CA.{' '}
584
- <Link href="#/templates/detail-page" color="secondary">
586
+ <Link href="#/templates/detail-page">
585
587
  Show more
586
588
  </Link>
587
589
  </Text>
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > (LC > V[g=8] > (V[g=2] > Tx.display-1"Button" + Tx"March 30, 2026"[t=supporting]) + (C.muted[p=0] > Ctr[h=360]) + (V[g=4] > Hd"Usage"[level=2] + Tx.lg"Usage" + Hd"Best practices"[level=3] + T) + D + (V[g=4] > Hd"Examples"[level=2] + Tx.lg"Explore") + (V[g=8] > (C[p=0] > (S[p=3] > H[j=between] > Tx"Title"[t=body] + (H[g=1] > B"Open in Craft" + IB)) + Ctr[h=280] + (S.muted[p=3] > V[g=3] > (TL > Tab"Description"! + Tab"Code") + Tx"Description"[t=body]))*2)) + (LP > Outline)
2
4
 
3
5
  import {useCallback, useState, useMemo, type CSSProperties} from 'react';
4
6
  import {Heading, Text} from '@astryxdesign/core/Text';
@@ -532,11 +534,11 @@ function ComponentDetailView({activeNav}: {activeNav: string}) {
532
534
  label="Button"
533
535
  variant="secondary"
534
536
  icon={<Icon icon={Plus} />}
535
- endContent={<Badge label="New" variant="info" />}
537
+ endContent={<Badge label="New" variant="cyan" />}
536
538
  />
537
539
  ),
538
540
  avatar: <Avatar name="Vlad" size="lg" />,
539
- badge: <Badge label="Success" variant="success" />,
541
+ badge: <Badge label="Success" variant="green" />,
540
542
  card: (
541
543
  <Card>
542
544
  <VStack gap={2}>
@@ -635,7 +637,7 @@ function ComponentDetailView({activeNav}: {activeNav: string}) {
635
637
  renderCell: (item: Record<string, unknown>) => (
636
638
  <Badge
637
639
  label={item.type === 'do' ? 'Do' : "Don't"}
638
- variant={item.type === 'do' ? 'success' : 'error'}
640
+ variant={item.type === 'do' ? 'green' : 'red'}
639
641
  />
640
642
  ),
641
643
  },
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > (LC > V[g=8] > (V[g=2] > Tx.display-1"Getting started with Astryx Dracula" + Tx"Last updated March 30, 2026"[t=supporting]) + (C > V[g=3] > (H[j=between] > (H[g=2] > Ic + Tx"AI Assistance"[t=body]) + (H > B"Copy prompt" + DM)) + Tx"Prompt description"[t=body]) + (V[g=4] > Hd"Prerequisites"[level=2] + UL) + D + (V[g=4] > Hd"Install the package"[level=2] + Tx"Description"[t=body] + (V[g=2] > Tx"Step"[t=body] + Cd)*3) + D + (V[g=4] > Hd"Configure theming"[level=2] + Tx"Description"[t=body] + Cd + Tx"Note"[t=body]) + D + (V[g=4] > Hd"Next steps"[level=2] + UL)) + (LP > Outline)
2
4
 
3
5
  import {useCallback, useState, type CSSProperties} from 'react';
4
6
  import {Heading, Text} from '@astryxdesign/core/Text';
@@ -165,7 +167,7 @@ export default function DocumentationTechnical() {
165
167
  gives you access to all components, tokens, and utilities.
166
168
  </Text>
167
169
  <VStack gap={2}>
168
- <Text type="body" weight="bold">
170
+ <Text type="body" weight="semibold">
169
171
  Step 1: Install the core package
170
172
  </Text>
171
173
  <CodeBlock
@@ -175,7 +177,7 @@ export default function DocumentationTechnical() {
175
177
  />
176
178
  </VStack>
177
179
  <VStack gap={2}>
178
- <Text type="body" weight="bold">
180
+ <Text type="body" weight="semibold">
179
181
  Step 2: Import the precompiled styles
180
182
  </Text>
181
183
  <Text type="body" color="secondary">
@@ -191,7 +193,7 @@ import '@astryxdesign/core/astryx.css';`}
191
193
  />
192
194
  </VStack>
193
195
  <VStack gap={2}>
194
- <Text type="body" weight="bold">
196
+ <Text type="body" weight="semibold">
195
197
  Step 3: Import your first component
196
198
  </Text>
197
199
  <CodeBlock
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > LC > V[g=10] > (C[p=10] > (H[g=8 a=center] > (V[g=4] > Tx.display-1"The coven grimoire" + 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"Category"[level=2] + Tx"18 spells"[t=supporting]) + (G[c=4 g=2] > (CC[p=2] > V[g=3] > C[p=0] + (V[g=1] > Tx"AppShell"[t=body] + Tx"Description"[t=body]))*4))*4
2
4
 
3
5
  import type {CSSProperties} from 'react';
4
6
  import {Heading, Text} from '@astryxdesign/core/Text';
@@ -326,7 +328,7 @@ export default function DocumentationCatalog() {
326
328
  />
327
329
  </Card>
328
330
  <VStack gap={0.5}>
329
- <Text type="body" weight="bold">
331
+ <Text type="body" weight="semibold">
330
332
  {item.name}
331
333
  </Text>
332
334
  <Text type="body" color="secondary" maxLines={3}>
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > (LP[w=320] > V[g=4] > (S[p=4] > V[g=4] > Hd"Page Editor"[level=2] + Tbar) + (V[g=4] > (TL > Tab"Blocks"! + Tab"Properties") + D + (S[p=4] > V[g=2] > Hd"Add Block"[level=3] + UL + Hd"Layers"[level=3] + UL))) + (LC > V[g=4] > C*3)
2
4
 
3
5
  import {useState, useCallback, type CSSProperties} from 'react';
4
6
  import {useMediaQuery} from '@astryxdesign/core/hooks';
@@ -109,7 +111,7 @@ const TRANSACTION_COLUMNS: TableColumn<Transaction>[] = [
109
111
  <HStack gap={3} vAlign="center">
110
112
  <Icon icon={CATEGORY_ICONS[item.category] || Sparkles} />
111
113
  <VStack gap={0}>
112
- <Text type="label" weight="semibold">
114
+ <Text type="body" weight="semibold">
113
115
  {item.name}
114
116
  </Text>
115
117
  <Text type="supporting" color="secondary">
@@ -134,7 +136,7 @@ const TRANSACTION_COLUMNS: TableColumn<Transaction>[] = [
134
136
  header: 'Amount',
135
137
  width: proportional(1, {minWidth: 90}),
136
138
  renderCell: (item: Transaction) => (
137
- <Text type="label" weight="semibold" hasTabularNumbers>
139
+ <Text type="body" weight="semibold" hasTabularNumbers>
138
140
  {item.amount}
139
141
  </Text>
140
142
  ),
@@ -314,14 +316,14 @@ const clickable: CSSProperties = {
314
316
  // Selection ring on the active block — Card has no `isSelected` state.
315
317
  const selectedCard: CSSProperties = {
316
318
  outline: '2px solid',
317
- outlineColor: 'var(--color-border-blue)',
319
+ outlineColor: 'var(--color-accent)',
318
320
  outlineOffset: -2,
319
321
  };
320
322
  // Circular muted chip behind the CTA icon — Center handles the centering
321
323
  // and sizing; only the surface (radius + fill) needs custom CSS.
322
324
  const iconCircle: CSSProperties = {
323
325
  borderRadius: '50%',
324
- backgroundColor: 'var(--color-background-muted)',
326
+ backgroundColor: 'var(--color-selection)',
325
327
  };
326
328
 
327
329
  // ---------------------------------------------------------------------------
@@ -470,7 +472,7 @@ function BlockPreview({
470
472
  <Heading level={2}>
471
473
  {(props.heading as string) || 'Hero Heading'}
472
474
  </Heading>
473
- <Text type="supporting" color="secondary">
475
+ <Text type="body" color="secondary">
474
476
  {(props.subheading as string) || 'Subtitle text goes here'}
475
477
  </Text>
476
478
  {(props.buttonLabel as string) && (
@@ -596,10 +598,10 @@ function BlockPreview({
596
598
  <Icon icon={Lock} color="secondary" />
597
599
  </Center>
598
600
  <VStack gap={1}>
599
- <Text type="label" weight="semibold">
601
+ <Heading level={4}>
600
602
  {(props.heading as string) || 'Notice'}
601
- </Text>
602
- <Text type="supporting" color="secondary">
603
+ </Heading>
604
+ <Text type="body" color="secondary">
603
605
  {(props.description as string) || 'Description text'}
604
606
  </Text>
605
607
  </VStack>
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > (Tbar[size=sm] > (H > IB"Go back" + IB"Go forward" + Tx"Folder"[t=label]) + (SG"View mode" > SGI*4) + (H > IB"Group" + IB"Share" + IB"Tags" + IB"More" + IB"Search")) + (LC[p=0 !scroll] > H[h=fill] > (S.transparent[p=2 w=240 dv=[end]] > UL[density=compact !hasDividers] > (LI > Ic + Tx"Item"[t=body])*3)*3 + (S.transparent[p=6] > V[g=4 a=center] > Av[size=96] + (V[g=1 a=center] > Tx"Name"[t=label] + Tx"Kind"[t=supporting]) + (ML"Information" > MLI*3)))
2
4
 
3
5
  import {useState, useMemo, type CSSProperties} from 'react';
4
6
  import {Layout, LayoutContent} from '@astryxdesign/core/Layout';
@@ -551,7 +553,7 @@ export default function FileExplorer() {
551
553
  <Text type="label" maxLines={1}>
552
554
  {selectedFile.name}
553
555
  </Text>
554
- <Text type="supporting">
556
+ <Text type="supporting" color="secondary">
555
557
  {getFileExtension(selectedFile.name)} Document
556
558
  </Text>
557
559
  </VStack>
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // Ctr > S.transparent[p=10] > V[g=10] > (G[c={min:320} g=10] > (V[g=6] > (V[g=3] > Hd"Let's conjure together"[level=1 t=display-1] + Tx"Tell us what you're brewing"[t=body]) + AR) + (C[p=8] > V[g=4] > Tx"Your details"[t=label] + TI"Full name" + (G[c={min:180} g=3] > TI"Email" + TI"Company") + (G[c={min:180} g=3] > TI"Job title" + TI"Phone") + (V[g=2] > Tx"Reason"[t=label] + (H[g=2] > Tk"Reason"*3)) + SE"Budget" + TA"Project details" + B.primary"Send it into the night")) + (V[g=6] > D + (G[c={min:200} g=6] > (V[g=1 a=center] > Tx"General"[t=supporting] + Lk"hello@castle.dracula")*3))
2
4
 
3
5
  import {useState, type CSSProperties} from 'react';
4
6
  import {VStack, HStack} from '@astryxdesign/core/Layout';
@@ -249,7 +251,7 @@ export default function TwoColumnForm() {
249
251
  <Token
250
252
  key={reason}
251
253
  label={reason}
252
- color={inquiryReason === reason ? 'blue' : 'default'}
254
+ color={inquiryReason === reason ? 'yellow' : 'default'}
253
255
  onClick={() =>
254
256
  setInquiryReason(prev =>
255
257
  prev === reason ? '' : reason,
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > LC[p=6] > V[g=10] > (V[g=6 a=center] > (V[g=3 a=center] > Hd"Little haunts, everywhere you roam"[level=1 t=display-2] + Tx"Sometimes all it takes"[t=body]) + (H[j=center g=3] > B.primary"Enter the gallery" + B.secondary"Read the lore")) + (G[c={min:200} g=4] > AR*3)
2
4
 
3
5
  import type {CSSProperties} from 'react';
4
6
  import {VStack, HStack, Layout, LayoutContent} from '@astryxdesign/core/Layout';
package/templates/ide.tsx CHANGED
@@ -1,8 +1,11 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > (LP[p=4] > V[g=2] > TI"Search files" + TreeList) + (LC[p=0] > V > (SI[fill] > Cd) + (V > (TL > Tab"Terminal"! + Tab"Problems" + Tab"Output" + Tab"Debug") + Cd)) + (LP[p=4] > V[g=3] > (SG > SGI"Properties"! + SGI"History") + (V[g=3] > (V[g=1] > Hd"NightCounter.tsx"[level=3] + Tx"src/components/NightCounter.tsx"[t=supporting]) + ML + (V[g=2] > B.secondary"Format Document" + B.secondary"Go to Definition" + B.secondary"Find References")))
2
4
 
3
5
  import {useState, useMemo, type CSSProperties} from 'react';
4
6
 
5
7
  import {Layout, LayoutContent, LayoutPanel} from '@astryxdesign/core/Layout';
8
+ import {StatusDot} from '@astryxdesign/core/StatusDot';
6
9
  import {ResizeHandle, useResizable} from '@astryxdesign/core/Resizable';
7
10
  import {Text, Heading} from '@astryxdesign/core/Text';
8
11
  import {Center} from '@astryxdesign/core/Center';
@@ -507,8 +510,9 @@ export default function IdeWorkspace() {
507
510
  </Text>
508
511
  }
509
512
  startContent={
510
- <span
511
- style={styles.historyTimelineDot}
513
+ <StatusDot
514
+ variant="neutral"
515
+ label="Timeline marker"
512
516
  />
513
517
  }
514
518
  />
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > (LH > H[g3 a=center] > (H[g2 a=center] > Hd"Night watch"[level=1] + Tx"3 investigating"[t=supporting]) + SegmentedControl"Filter by status" + B"Declare incident") + (LC[p0] > V[g0] > (H > PowerSearch"Search the night watch...") + (List > (ListItem)*6)) + (LayoutPanel[w380 p0] > V[g4] > (V[g2] > (H[g2 a=center] > StatusDot + Tx"INC-2417"[t=supporting] + Token"Investigating") + Hd"Checkout API elevated 5xx rate"[level=2]) + (H[g2] > B.primary"Mark mitigated" + B.secondary"Escalate") + Divider + MetadataList + Divider + (V[g2] > Hd"Timeline"[level=3] + List))
2
4
 
3
5
  /**
4
6
  * Incident Console — an on-call incident response tool for the night watch.
@@ -415,7 +417,7 @@ function IncidentInspector({incident}: {incident: Incident}) {
415
417
  </VStack>
416
418
 
417
419
  <HStack gap={2}>
418
- <Button label={nextAction} size="sm" />
420
+ <Button label={nextAction} variant="primary" size="sm" />
419
421
  <Button label="Escalate" variant="secondary" size="sm" />
420
422
  </HStack>
421
423
 
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // S > L > (LH[divider] > Tbar > (Hd"Sprint Board"[level=3] + Bd.neutral"8") + (H[g=2] > SE + D.strong + IB"Sort" + IB"Filter" + IB"Search" + B.primary"Add task")) + (LC[p=0] > G[c=4 g=4] > (C.muted[p=0] > L > (LH[divider] > H[j=between a=center] > (H[g=2 a=center] > SD + Hd"To-do"[level=4] + Ic) + Tx) + (LC[p=2] > V[g=2] > (C[p=3] > V[g=2] > (H[j=between] > (H[g=1] > Bd + Bd) + MM) + (V[g=1] > Hd[level=4] + Tx) + Tx)*2))*4)
2
4
 
3
5
  import {
4
6
  useEffect,
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > (LH[divider] > Hd"Library"[level=1]) + (LC[p=6] > V[g=6] > (V[g=4] > TI"Search the stacks..." + (H[a=center g=4] > (SI[fill] > TgG"Filter" > OFL > Tg"All"! + Tg"Layout" + Tg"Forms") + DM"Sort")) + D + (V[g=6] > (H[j=between a=center] > Hd"Layout"[level=2] + Tx"6 items"[t=supporting]) + (G[c={min:320} g=4] > (C[p=0] > AR + (S.transparent[p=4] > V[g=1] > Hd"Card"[level=3] + Tx"Description"[t=body]))*4)))
2
4
 
3
5
  import {useState, useMemo, type CSSProperties} from 'react';
4
6
  import {Layout, LayoutHeader, LayoutContent} from '@astryxdesign/core/Layout';
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // C[p4] > V[g3] > (Hd"Sign in"[level=3] + F > (TI"Email"[t=email req] + TI"Password"[t=password req]) + B.primary"Enter the night")
2
4
 
3
5
  import {useState, type CSSProperties} from 'react';
4
6
  import {Moon} from 'lucide-react';
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // Ctr > V[g4] > (C[p0] > G[c{min:240} g8 a=stretch] > (S[p0] > V[g4] > (H[g2] > Ic + Tx"Castle Dracula"[t=body]) + (V[g4] > (V[g1] > Hd"Welcome back to the night"[level=2] + Tx"Sign in to your crypt"[t=body]) + (V[g2] > TI"Email"[t=email] + TI"Password"[t=password]) + B.primary"Enter the night" + D"Or continue with" + (G[c2 g3] > B.secondary"Apple" + B.secondary"Google")) + (Tx"New to the castle?"[t=supporting] > Lk"Sign up")) + (C[p0] > AR)) + (V[a=center] > Tx"Terms"[t=supporting])
2
4
 
3
5
  import {useState, type CSSProperties} from 'react';
4
6
  import {VStack, HStack, StackItem} from '@astryxdesign/core/Layout';
@@ -174,7 +176,7 @@ export default function LoginSplit() {
174
176
  <VStack gap={4} height="100%">
175
177
  <HStack gap={2} vAlign="center">
176
178
  <Icon icon={Moon} color="accent" />
177
- <Text type="body" weight="bold">
179
+ <Text type="body" weight="semibold">
178
180
  Castle Dracula
179
181
  </Text>
180
182
  </HStack>
@@ -232,11 +234,7 @@ export default function LoginSplit() {
232
234
  />
233
235
  {loginFailed && (
234
236
  <VStack hAlign="end">
235
- <Link
236
- href="#/templates/login-split"
237
- size="sm"
238
- color="secondary"
239
- type="supporting">
237
+ <Link href="#/templates/login-split">
240
238
  Forgot your password?
241
239
  </Link>
242
240
  </VStack>
@@ -276,7 +274,7 @@ export default function LoginSplit() {
276
274
  {!isSuccess && (
277
275
  <Text type="supporting" color="secondary">
278
276
  New to the castle?{' '}
279
- <Link href="#/templates/login-split" type="supporting">
277
+ <Link href="#/templates/login-split">
280
278
  Sign up
281
279
  </Link>
282
280
  </Text>
@@ -302,11 +300,11 @@ export default function LoginSplit() {
302
300
  <VStack hAlign="center">
303
301
  <Text type="supporting" color="secondary">
304
302
  By clicking continue, you agree to our{' '}
305
- <Link href="#/templates/login-split" type="supporting">
303
+ <Link href="#/templates/login-split">
306
304
  Terms of Service
307
305
  </Link>{' '}
308
306
  and{' '}
309
- <Link href="#/templates/login-split" type="supporting">
307
+ <Link href="#/templates/login-split">
310
308
  Privacy Policy
311
309
  </Link>
312
310
  .
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // Ctr > C[p8 mw400] > V[g4] > (V[g1 a=center] > Hd"Welcome back to the night"[level=2] + Tx"Whisper your details"[t=body]) + (V[g2] > TI"Work email"[t=email] + TI"Password"[t=password]) + Lk"Having trouble signing in?" + B.primary"Enter the night" + D"Or sign in with" + B.secondary"Continue with SSO" + (V[a=center] > Tx"New to the castle?"[t=supporting])
2
4
 
3
5
  import {useState, type CSSProperties} from 'react';
4
6
  import {VStack, HStack} from '@astryxdesign/core/Layout';
@@ -135,7 +137,7 @@ export default function LoginSso() {
135
137
  />
136
138
  </VStack>
137
139
 
138
- <Link href="#/templates/login-sso" size="sm" color="secondary" type="supporting">
140
+ <Link href="#/templates/login-sso">
139
141
  Having trouble signing in?
140
142
  </Link>
141
143
 
@@ -160,7 +162,7 @@ export default function LoginSso() {
160
162
  <VStack hAlign="center">
161
163
  <Text type="supporting" color="secondary">
162
164
  New to the castle?{' '}
163
- <Link href="#/templates/login-sso" type="supporting">
165
+ <Link href="#/templates/login-sso">
164
166
  Request access
165
167
  </Link>
166
168
  </Text>
@@ -243,11 +245,7 @@ export default function LoginSso() {
243
245
  />
244
246
  {loginFailed && (
245
247
  <VStack hAlign="end">
246
- <Link
247
- href="#/templates/login-sso"
248
- size="sm"
249
- color="secondary"
250
- type="supporting">
248
+ <Link href="#/templates/login-sso">
251
249
  Forgot password?
252
250
  </Link>
253
251
  </VStack>
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // Ctr > V[g=4 a=center] > (V[g=2 a=center] > Ic + Tx"Castle Dracula"[t=body]) + (C[p=8] > V[g=4] > (V[g=1 a=center] > Hd"Welcome back to the night"[level=2] + Tx"Sign in to your crypt"[t=body]) + TI"Email"[t=email] + TI"Password"[t=password] + B.primary"Enter the night")
2
4
 
3
5
  import {useState, type CSSProperties} from 'react';
4
6
  import {Moon} from 'lucide-react';
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > (LP[w68] > V > Av + (V > IB*4) + IB) + (LP[w260] > V > (H > Hd"Night Watch"[level=3] + IB) + TI"Jump to..." + (V > Tx"Channels"[t=label] + (List > (ListItem)*4)) + (V > Tx"Direct messages"[t=label] + (List > (ListItem)*3))) + (LC[p0] > ChL > ChML > (ChM > ChB)*6 + ChC) + (LP[w340] > V > (H > Hd"Thread"[level=3] + IB) + (ChL > ChML > (ChM > ChB)*3 + ChC))
2
4
 
3
5
  /**
4
6
  * Messaging Shell — Slack-style column frame for team messaging tools.
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > LC[p=6] > V[g=6] > (V[g=2 a=center] > Hd"Every corner of the castle, caught after dark."[level=1] + Tx"Relics, sketches, and moonlit views"[t=body]) + (G[g=4] > (V[g=2] > AR + Tx"Title"[t=supporting])*5)
2
4
 
3
5
  import type {CSSProperties} from 'react';
4
6
  import {VStack, Layout, LayoutContent} from '@astryxdesign/core/Layout';
@@ -154,7 +156,7 @@ export default function MixedGallery() {
154
156
  <Heading level={1} justify="center">
155
157
  Every corner of the castle, caught after dark.
156
158
  </Heading>
157
- <Text type="body" justify="center">
159
+ <Text type="body" color="secondary" justify="center">
158
160
  Relics, sketches, and moonlit views from the coven archives —
159
161
  collected over one long Transylvanian night.
160
162
  </Text>
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > LC[p=0] > Ctr > (S > V[g=5] > (V[g=1] > Hd"Payment Request"[level=1] + Tx"Review your order"[t=body]) + (H > (SI > V[g=6] > (C > V[g=3] > Hd"Sign in"[level=3] + B) + (F > TI"Email" + TI"Address" + B.primary"Place Order")) + (SI > C[p=5] > (Col > V[g=4] > (H > Tmb + V[g=1] > Tx + Tx)*3 + D + (H > Tx + Tx) + Bn.info))))
2
4
 
3
5
  import {useState, type CSSProperties} from 'react';
4
6
  import {
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > LC[p=6] > G[c={min:360} g=8] > (V[g=4] > AR + (G[c=3 g=3] > C*6)) + (V[g=6] > (V[g=2] > Hd"Midnight Ceremony Mug & Plate Set"[level=1 t=display-2] + (H[g=2] > Tx"$89.00"[t=large] + Tx"$119.00"[t=body] + Bd.pink"Sale")) + Tx"A hand-thrown mug and plate set"[t=large] + (V[g=2] > Tx"Glaze"[t=label] + SG) + (V[g=2] > Tx"Finish"[t=label] + SG) + (V[g=2] > Tx"Quantity"[t=label] + (H[g=1] > B.ghost"-" + TI"1" + B.ghost"+")) + (V[g=2] > B.primary"Add to Cart" + B.secondary"Buy it now") + (ColG > Col"Composition" + Col"Delivery & Returns" + Col"Dimensions"))
2
4
 
3
5
  import {useState} from 'react';
4
6
  import {VStack, HStack, Layout, LayoutContent} from '@astryxdesign/core/Layout';
@@ -85,7 +87,7 @@ function StarRating({rating, count}: {rating: number; count: number}) {
85
87
  <Icon key={`full-${i}`} icon={Star} size="sm" color="warning" />
86
88
  ))}
87
89
  {Array.from({length: empty}, (_, i) => (
88
- <Icon key={`empty-${i}`} icon={Star} size="sm" />
90
+ <Icon key={`empty-${i}`} icon={Star} size="sm" color="disabled" />
89
91
  ))}
90
92
  <Text type="body" color="secondary" hasTabularNumbers>
91
93
  {rating} ({count})
@@ -199,7 +201,7 @@ function ProductInfo() {
199
201
  <Text type="body" color="secondary" hasStrikethrough hasTabularNumbers>
200
202
  {fmt(PRODUCT.originalPrice)}
201
203
  </Text>
202
- <Badge variant="error" label="Sale" />
204
+ <Badge variant="pink" label="Sale" />
203
205
  </HStack>
204
206
  </VStack>
205
207
  <Text type="large" weight="normal">
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > LC > V[g=6] > (G[c={min:280} g=4 a=start] > Hd"Small comforts for the midnight hours."[level=1] + (V[g=3 a=start] > Tx"Provisions from the castle workshops"[t=body] + B.primary"Browse the collection")) + (G[c={min:300} g=6] > (V[g=3] > (C[p=0] > AR[ratio=1]) + (V[g=1] > Hd"Nightfall Stoneware Mug"[level=3] + Tx"Description"[t=body color=secondary] + Tx.lg"$75.00"))*6)
2
4
 
3
5
  import {VStack, Layout, LayoutContent} from '@astryxdesign/core/Layout';
4
6
  import {Text, Heading} from '@astryxdesign/core/Text';
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > LC > Ctr[h=80vh] > B.primary"Open settings"[opens=#settings] ;; Dlg#settings > L > (LP[w=280 divider p=3] > V[g=4] > Hd"Account settings"[level=2] + (List > LI"Personal information"*8)) + (LC[p=6] > V[g=6] > DH"Account" + (V[g=4] > (H[j=between] > (V[g=0] > Tx"Legal name"[weight=semibold] + Tx"Vlad Dracul"[t=supporting color=secondary]) + Link"Edit")*4))
2
4
 
3
5
  import React, {useState, type CSSProperties} from 'react';
4
6
  import {
@@ -71,6 +73,10 @@ const actionNoWrap: CSSProperties = {
71
73
  whiteSpace: 'nowrap',
72
74
  };
73
75
 
76
+ // Same-route hash: demo links stay focusable anchors without escaping the
77
+ // template through the hash router (bare "#" would drop back to the home page).
78
+ const SELF_HASH = '#/templates/settings-dialog';
79
+
74
80
  const NAV_ITEMS = [
75
81
  {label: 'Personal information', icon: User},
76
82
  {label: 'Login & security', icon: Lock},
@@ -178,7 +184,7 @@ function ExpandableRow({
178
184
  </Text>
179
185
  </VStack>
180
186
  <Link
181
- href="#/templates/settings-dialog"
187
+ href={SELF_HASH}
182
188
  onClick={(e: React.MouseEvent) => {
183
189
  e.preventDefault();
184
190
  onEdit();
@@ -212,7 +218,7 @@ function InfoRowItem({
212
218
  {value}
213
219
  </Text>
214
220
  </VStack>
215
- {action && <Link>{action}</Link>}
221
+ {action && <Link href={SELF_HASH}>{action}</Link>}
216
222
  </HStack>
217
223
  <Divider />
218
224
  </>
@@ -570,7 +576,7 @@ export default function SettingsDialog() {
570
576
  </VStack>
571
577
  </StackItem>
572
578
  {device.action && (
573
- <Link style={actionNoWrap}>
579
+ <Link href={SELF_HASH} style={actionNoWrap}>
574
580
  {device.action}
575
581
  </Link>
576
582
  )}
@@ -598,7 +604,7 @@ export default function SettingsDialog() {
598
604
  This action cannot be undone
599
605
  </Text>
600
606
  </VStack>
601
- <Link>Deactivate</Link>
607
+ <Link href={SELF_HASH}>Deactivate</Link>
602
608
  </HStack>
603
609
  <Divider />
604
610
  </VStack>
@@ -802,7 +808,7 @@ export default function SettingsDialog() {
802
808
  <Text type="body" weight="semibold">
803
809
  Blocked people
804
810
  </Text>
805
- <Link>View</Link>
811
+ <Link href={SELF_HASH}>View</Link>
806
812
  </HStack>
807
813
  <Divider />
808
814
  </VStack>
@@ -824,7 +830,7 @@ export default function SettingsDialog() {
824
830
  <Heading level={3}>Reviews</Heading>
825
831
  <Text type="supporting" color="secondary">
826
832
  Choose what&apos;s shared when you write a review.{' '}
827
- <Link type="supporting">Learn more</Link>
833
+ <Link href={SELF_HASH}>Learn more</Link>
828
834
  </Text>
829
835
  <VStack gap={4}>
830
836
  <Switch
@@ -868,7 +874,7 @@ export default function SettingsDialog() {
868
874
  <Card>
869
875
  <HStack hAlign="between" vAlign="center">
870
876
  <Text type="body">Request my personal data</Text>
871
- <Link>Request</Link>
877
+ <Link href={SELF_HASH}>Request</Link>
872
878
  </HStack>
873
879
  </Card>
874
880
  <Switch
@@ -882,7 +888,7 @@ export default function SettingsDialog() {
882
888
  <Card>
883
889
  <HStack hAlign="between" vAlign="center">
884
890
  <Text type="body">Delete my account</Text>
885
- <Link>Delete</Link>
891
+ <Link href={SELF_HASH}>Delete</Link>
886
892
  </HStack>
887
893
  </Card>
888
894
  <Card variant="muted">
@@ -897,7 +903,7 @@ export default function SettingsDialog() {
897
903
  <Text type="supporting" color="secondary">
898
904
  We&apos;re committed to keeping your data
899
905
  protected. See details in our{' '}
900
- <Link type="supporting">
906
+ <Link href={SELF_HASH}>
901
907
  Privacy Policy
902
908
  </Link>
903
909
  .
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > (LP > V[g=4] > Hd"Account settings"[level=2] + (UL > LI*8) + D + LI) + (LC[p=4] > V[g=6] > Hd"Personal info"[level=2] + (V > (H[j=between a=center] > (V > Tx"Legal name" + Tx"Vlad Dracul"[t=supporting]) + Lk"Edit")*7) + (C.muted > V[g=4] > (H[g=3 a=start] > Ic + (V[g=1] > Tx"Why is info hidden" + Tx[t=supporting]))*3))
2
4
 
3
5
  import {useState, type CSSProperties} from 'react';
4
6
  import {useMediaQuery} from '@astryxdesign/core/hooks';
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // V[g6] > (V[g1] > Hd"Settings"[level=2] + Tx"Profile"[t=body]) + (G[c2 g4] > C[p4] + C[p4])
2
4
 
3
5
  import {useState} from 'react';
4
6
  import {useMediaQuery} from '@astryxdesign/core/hooks';
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // A[cp=0 @topNav=(TN) @sideNav=(SN > TL)] > L > (LH[divider] > H[g=2] > C.muted[p=0]*3) + (LC[p=6] > V[g=2] > (H[g=3 a=center] > C.muted[p=0] + C.muted[p=0])*8)
2
4
 
3
5
  import {Fragment, useState, useMemo, useEffect} from 'react';
4
6
  import {AppShell} from '@astryxdesign/core/AppShell';
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // A[cp=0 @sideNav=(SN > SNI"New chat" + SNI"Search" + SNI"Library" + D + (SNI"Personal" > SNI"Weekend trip planning")*3)] > L > (LC[p=6] > V[g=5] > (H > C.muted[p=0])*4) + (LF > TI"Message Night Owl")
2
4
 
3
5
  import {useState} from 'react';
4
6
  import {AppShell} from '@astryxdesign/core/AppShell';
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // A[cp=6 @topNav=(TN > TNI"Shop" + TNI"Brands" + TNI"Sale" + TNI"Service")] > V[g=10] > C.muted[p=0] + (V[g=4] > C.muted[p=0] + (G[c={min:160} g=4] > (V[g=2] > C.muted[p=0] + C.muted[p=0])*6))*3
2
4
 
3
5
  import type {CSSProperties} from 'react';
4
6
  import {AppShell} from '@astryxdesign/core/AppShell';
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > LC > G[c{min:360} g8 a=center] > (V[g6] > (V[g3] > Tx"AFTER DARK"[t=supporting] + Hd"Make every night"[level=1] + Tx"The smallest rituals"[t=body]) + B.primary"Explore the night" + (V[g4] > D + (H[g6] > (V > Tx"12k+"[t=large] + Tx"Night shots"[t=supporting])*3))) + (G[c3 g3] > AR*9)
2
4
 
3
5
  import type {CSSProperties} from 'react';
4
6
  import {VStack, HStack, Layout, LayoutContent} from '@astryxdesign/core/Layout';
@@ -103,7 +105,7 @@ function NightScene({alt, hue, index}: {alt: string; hue: string; index: number}
103
105
  function StatBlock({value, label}: {value: string; label: string}) {
104
106
  return (
105
107
  <VStack gap={0}>
106
- <Text type="large" weight="bold" hasTabularNumbers>
108
+ <Text type="large" weight="semibold" hasTabularNumbers>
107
109
  {value}
108
110
  </Text>
109
111
  <Text type="supporting" color="secondary">
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > (LH[divider] > V[g=4] > (H[j=between a=center] > Hd"Night-shift issues"[level=2] + B.primary"Raise issue") + (H[g=2 a=center] > PS + B.secondary"View Options")) + (LC[p=0] > T[hover] > (TR > THC*7) + (TR > TC*7)*4)
2
4
 
3
5
  import React, {useState, useMemo} from 'react';
4
6
  import {useResizable, ResizeHandle} from '@astryxdesign/core/Resizable';
@@ -787,7 +789,7 @@ function TaskDetailPanel({
787
789
  <Text type="label">Labels</Text>
788
790
  <HStack gap={2}>
789
791
  {task.tags.map(tag => (
790
- <Badge key={tag} variant="neutral" label={tag} />
792
+ <Badge key={tag} variant="yellow" label={tag} />
791
793
  ))}
792
794
  </HStack>
793
795
  </VStack>
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > (LH[divider] > H[a=center g=2] > (SI[size=fill] > Hd"Matcha Bar"[level=1]) + IB"Filter"[variant=ghost] + IB"Export"[variant=ghost] + B.primary"New order") + (LC[p=3] > V[g=4] > C[p=3] + (T[hover] > (TR > THC"Order" + THC"Product" + THC"Amount" + THC"Customer" + THC"Email" + THC"Status" + THC"Date") + (TR > TC"ORD-1001" + TC"Ceremonial Matcha Latte" + TC"$6" + TC"Sarah Chen" + TC"sarah.chen@acme.co" + (TC > Bd.green"Completed") + TC"2025-01-15")*6))
2
4
 
3
5
  import type {CSSProperties} from 'react';
4
6
  import {
@@ -668,7 +670,11 @@ export default function ChartTable() {
668
670
  variant="ghost"
669
671
  tooltip="Export"
670
672
  />
671
- <Button label="New order" icon={<Icon icon={Plus} size="sm" />} />
673
+ <Button
674
+ label="New order"
675
+ variant="primary"
676
+ icon={<Icon icon={Plus} size="sm" />}
677
+ />
672
678
  </HStack>
673
679
  </LayoutHeader>
674
680
  }
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > (LH > H[g2 a=center] > Hd"Status"[level=1] + IB*2 + B"Refresh") + (LC[p3] > V[g4] > (V[g3] > C[p3] + Tx"Incidents by day and hour"[t=supporting] + (H[g4] > (H[g2] > Tx[t=supporting])*4)) + (T > (TR > THC*8) + (TR > TC*8)*5))
2
4
 
3
5
  import {
4
6
  VStack,
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > (LH > H[g2 a=center] > Hd"Midnight Kicks"[level=1] + IB*2 + B.primary"New order") + (LC[p3] > V[g4] > (V[g3] > C[p3] + Tx"Daily revenue"[t=supporting] + (H[g2 a=center] > Ic + Tx"Revenue"[t=supporting])) + (T > (TR > THC*7) + (TR > TC*7)*5))
2
4
 
3
5
  import type {CSSProperties} from 'react';
4
6
  import {
@@ -1013,7 +1015,11 @@ export default function ShoeStoreTable() {
1013
1015
  variant="ghost"
1014
1016
  tooltip="Export"
1015
1017
  />
1016
- <Button label="New order" icon={<Icon icon={Plus} size="sm" />} />
1018
+ <Button
1019
+ label="New order"
1020
+ variant="primary"
1021
+ icon={<Icon icon={Plus} size="sm" />}
1022
+ />
1017
1023
  </HStack>
1018
1024
  </LayoutHeader>
1019
1025
  }
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > (LH[divider] > H[g=2 a=center] > (SI[fill] > Hd"Familiars"[level=1]) + IB"Filter" + IB"Download" + B.primary"Add") + (LC[p=3] > V[g=4] > PS + (T[hover] > (TR > THC*3) + (TR > TC*3)*3))
2
4
 
3
5
  import {useState, useMemo} from 'react';
4
6
  import {
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > LC > V[g6] > (V[g1] > Hd"Vault"[level=2] + Tx"Remit"[t=body]) + (C[p0] > T[striped] > (TR > THC"Name" + THC"Status" + THC"Updated") + (TR > TC"Blood Vial" + (TC > Bd.success"Active") + TC"2025-01-15")*3)
2
4
 
3
5
  import {useState} from 'react';
4
6
  import {Layout, LayoutHeader, LayoutContent, HStack} from '@astryxdesign/core/Layout';
@@ -1,4 +1,6 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // TN"Nocturne" + (S[p6] > V[g10] > (Ctr > V[g4 a=center] > Tx"Little haunts"[t=display-2] + Tx"We believe"[t=body]) + (G[c{min:200,max:3} g4] > (C[p0] > AR + V[g2 a=center] > Bd + Hd"Product"[level=2] + Tx"Description"[t=body] + (H[g2] > NI + B"Add to cart"))*3)) + (V[g8] > (G[c{min:200} g4] > (GS[c1] > C > Hd"Checkout"[level=2]) + (GS[c2] > C > Hd"Night Owl AI"[level=2])) + (G[c{min:200} g4] > (GS[c3] > C > T) + (GS[c1] > C > Hd"Revenue"[level=2])))
2
4
 
3
5
  import {type CSSProperties, type ReactNode} from 'react';
4
6
  import {
@@ -555,7 +557,7 @@ function CheckoutCard({isMobile}: {isMobile: boolean}) {
555
557
  label="Economy Shipping"
556
558
  description="Delivered in 5–7 business days"
557
559
  endContent={
558
- <Text type="body" weight="bold" hasTabularNumbers>
560
+ <Text type="body" weight="semibold" hasTabularNumbers>
559
561
  $12.00
560
562
  </Text>
561
563
  }
@@ -565,7 +567,7 @@ function CheckoutCard({isMobile}: {isMobile: boolean}) {
565
567
  label="Standard Shipping"
566
568
  description="Delivered in 3–5 business days"
567
569
  endContent={
568
- <Text type="body" weight="bold" hasTabularNumbers>
570
+ <Text type="body" weight="semibold" hasTabularNumbers>
569
571
  $16.00
570
572
  </Text>
571
573
  }
@@ -575,7 +577,7 @@ function CheckoutCard({isMobile}: {isMobile: boolean}) {
575
577
  label="Express Shipping"
576
578
  description="Delivered in 1–2 business days"
577
579
  endContent={
578
- <Text type="body" weight="bold" hasTabularNumbers>
580
+ <Text type="body" weight="semibold" hasTabularNumbers>
579
581
  $24.00
580
582
  </Text>
581
583
  }
@@ -583,7 +585,7 @@ function CheckoutCard({isMobile}: {isMobile: boolean}) {
583
585
  </RadioList>
584
586
 
585
587
  <VStack gap={2} style={styles.checkoutStack}>
586
- <Text type="label" weight="bold">
588
+ <Text type="label" weight="semibold">
587
589
  Payment method
588
590
  </Text>
589
591
  <Grid columns={isMobile ? 1 : {minWidth: 70, max: 3}} gap={2}>
@@ -597,7 +599,7 @@ function CheckoutCard({isMobile}: {isMobile: boolean}) {
597
599
  hAlign="center"
598
600
  style={styles.paymentCardContent}>
599
601
  <CreditCard size={20} />
600
- <Text type="supporting" weight="bold">
602
+ <Text type="supporting" weight="semibold">
601
603
  Card
602
604
  </Text>
603
605
  </VStack>
@@ -612,7 +614,7 @@ function CheckoutCard({isMobile}: {isMobile: boolean}) {
612
614
  hAlign="center"
613
615
  style={styles.paymentCardContent}>
614
616
  <Smartphone size={20} />
615
- <Text type="supporting" weight="bold">
617
+ <Text type="supporting" weight="semibold">
616
618
  Apple Pay
617
619
  </Text>
618
620
  </VStack>
@@ -627,7 +629,7 @@ function CheckoutCard({isMobile}: {isMobile: boolean}) {
627
629
  hAlign="center"
628
630
  style={styles.paymentCardContent}>
629
631
  <Wallet size={20} />
630
- <Text type="supporting" weight="bold">
632
+ <Text type="supporting" weight="semibold">
631
633
  Google Pay
632
634
  </Text>
633
635
  </VStack>
@@ -773,7 +775,7 @@ function ChatCard() {
773
775
  label="Items"
774
776
  description="Moonphase Watch · Belfry Throw"
775
777
  endContent={
776
- <Text type="body" weight="bold" hasTabularNumbers>
778
+ <Text type="body" weight="semibold" hasTabularNumbers>
777
779
  $248
778
780
  </Text>
779
781
  }
@@ -782,7 +784,7 @@ function ChatCard() {
782
784
  label="Shipping"
783
785
  description="UPS Ground"
784
786
  endContent={
785
- <Text type="body" weight="bold" hasTabularNumbers>
787
+ <Text type="body" weight="semibold" hasTabularNumbers>
786
788
  $12
787
789
  </Text>
788
790
  }
@@ -914,7 +916,7 @@ function LatestActivityCard({isMobile}: {isMobile: boolean}) {
914
916
 
915
917
  <Grid columns={isMobile ? 1 : 2} gap={3}>
916
918
  <VStack gap={0}>
917
- <Text type="display-3" weight="bold" hasTabularNumbers>
919
+ <Text type="display-3" weight="semibold" hasTabularNumbers>
918
920
  18K
919
921
  </Text>
920
922
  <Text type="supporting" color="secondary">
@@ -922,7 +924,7 @@ function LatestActivityCard({isMobile}: {isMobile: boolean}) {
922
924
  </Text>
923
925
  </VStack>
924
926
  <VStack gap={0}>
925
- <Text type="display-3" weight="bold" hasTabularNumbers>
927
+ <Text type="display-3" weight="semibold" hasTabularNumbers>
926
928
  +12%
927
929
  </Text>
928
930
  <Text type="supporting" color="secondary">
@@ -952,7 +954,7 @@ function LatestActivityCard({isMobile}: {isMobile: boolean}) {
952
954
  endContent={
953
955
  <Text
954
956
  type="body"
955
- weight="bold"
957
+ weight="semibold"
956
958
  hasTabularNumbers
957
959
  color={item.amount < 0 ? 'secondary' : 'primary'}>
958
960
  {formatAmount(item.amount)}
@@ -1061,7 +1063,7 @@ function ItemCell({row}: {row: InventoryRow}) {
1061
1063
  <HStack gap={3} vAlign="center">
1062
1064
  <ThumbSwatch hue={row.hue} label={row.name} />
1063
1065
  <VStack gap={0} style={{minWidth: 0}}>
1064
- <Text type="body" weight="bold">
1066
+ <Text type="body" weight="semibold">
1065
1067
  {row.name}
1066
1068
  </Text>
1067
1069
  <Text type="supporting" color="secondary">