astryx-dracula 0.2.1 → 0.3.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 (83) hide show
  1. package/BRAND.md +30 -18
  2. package/README.md +17 -12
  3. package/USAGE.md +29 -10
  4. package/astryx-dracula.js +19 -13
  5. package/astryx-dracula.variants.d.ts +15 -0
  6. package/package.json +59 -17
  7. package/shared/auth-chrome-config.ts +18 -0
  8. package/shared/auth-chrome.tsx +25 -0
  9. package/shared/auth-copy.ts +22 -0
  10. package/shared/chaptered-doc-config.ts +92 -0
  11. package/shared/chaptered-doc.tsx +332 -0
  12. package/shared/chart-hues.ts +27 -0
  13. package/shared/chart-labels.tsx +44 -0
  14. package/shared/chart-legend.tsx +100 -0
  15. package/shared/chart-panel-style.ts +13 -0
  16. package/shared/data-bar.tsx +160 -0
  17. package/shared/gallery-image.ts +20 -0
  18. package/shared/login-demo.ts +7 -0
  19. package/shared/metric-delta.tsx +36 -0
  20. package/shared/order-desk.tsx +273 -0
  21. package/shared/revenue-chart.tsx +174 -0
  22. package/shared/scene-castle.tsx +322 -0
  23. package/shared/scene-frame.tsx +88 -0
  24. package/shared/scene-hues.ts +49 -0
  25. package/shared/scene-tile.tsx +128 -0
  26. package/shared/settings-data.ts +125 -0
  27. package/shared/settings-rows.tsx +179 -0
  28. package/shared/sparkline.tsx +94 -0
  29. package/shared/sso-icons.tsx +30 -0
  30. package/templates/ai-chat-landing.tsx +66 -33
  31. package/templates/ai-chat.tsx +36 -19
  32. package/templates/blank.tsx +4 -3
  33. package/templates/centered-hero.tsx +14 -125
  34. package/templates/classic-gallery.tsx +20 -66
  35. package/templates/contact-form.tsx +59 -39
  36. package/templates/dashboard-portfolio.tsx +143 -226
  37. package/templates/dashboard.tsx +122 -122
  38. package/templates/detail-page.tsx +95 -91
  39. package/templates/documentation-design.template.mjs +1 -1
  40. package/templates/documentation-design.tsx +83 -96
  41. package/templates/documentation-technical.template.mjs +1 -1
  42. package/templates/documentation-technical.tsx +29 -19
  43. package/templates/documentation.template.mjs +1 -1
  44. package/templates/documentation.tsx +52 -74
  45. package/templates/editor.tsx +112 -84
  46. package/templates/file-explorer.tsx +131 -84
  47. package/templates/form-two-column.tsx +61 -125
  48. package/templates/gallery-hero.tsx +15 -171
  49. package/templates/ide.tsx +22 -20
  50. package/templates/incident-console.tsx +104 -70
  51. package/templates/kanban-board.tsx +99 -42
  52. package/templates/library.template.mjs +2 -2
  53. package/templates/library.tsx +37 -42
  54. package/templates/login-card.tsx +58 -87
  55. package/templates/login-split.tsx +88 -126
  56. package/templates/login-sso.tsx +105 -64
  57. package/templates/login.tsx +107 -53
  58. package/templates/messaging-shell.tsx +171 -144
  59. package/templates/mixed-gallery.tsx +29 -130
  60. package/templates/payment-form.tsx +368 -290
  61. package/templates/product-detail.tsx +39 -58
  62. package/templates/product-gallery.tsx +30 -41
  63. package/templates/product-tour.template.mjs +6 -0
  64. package/templates/product-tour.tsx +916 -0
  65. package/templates/settings-dialog.tsx +135 -282
  66. package/templates/settings-sidebar.tsx +178 -268
  67. package/templates/settings.tsx +41 -14
  68. package/templates/shell-nav.tsx +31 -24
  69. package/templates/shell-side-nav.tsx +29 -20
  70. package/templates/shell-top-nav.tsx +80 -44
  71. package/templates/side-gallery.tsx +38 -94
  72. package/templates/table-grouped.tsx +62 -34
  73. package/templates/table-page-chart.tsx +23 -302
  74. package/templates/table-page-heatmap-status.tsx +156 -92
  75. package/templates/table-page-shoe-store-heatmap.tsx +18 -293
  76. package/templates/table-page.tsx +23 -7
  77. package/templates/table.tsx +23 -8
  78. package/templates/tech-report.template.mjs +6 -0
  79. package/templates/tech-report.tsx +1486 -0
  80. package/templates/theme-showcase.template.mjs +1 -1
  81. package/templates/theme-showcase.tsx +299 -237
  82. package/theme.css +76 -14
  83. package/tokens.css +425 -30
@@ -1,93 +1,30 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
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)
3
+ // L > LC[p=6] > V[g=8] > ((V[g=2 a=center] > Hd"Every corner of the castle, caught after dark."[level=1] + Tx"Relics, sketches, and moonlit views from the coven archives, collected over one long Transylvanian night."[t=body]) + (V[g=3] > (V[g=2] > AR[ratio=3/1] + Tx"The castle at moonrise"[t=body]) + (G[c={min:280} g=4] > (V[g=2] > AR[ratio=3/2] + Tx"Coven gathering"[t=body]) + (V[g=2] > AR[ratio=3/2] + Tx"Belfry view"[t=body]) + (V[g=2] > AR[ratio=3/2] + Tx"Crypt archives"[t=body]) + (V[g=2] > AR[ratio=3/2] + Tx"Midnight garden"[t=body]))))
4
4
 
5
- import type {CSSProperties} from 'react';
6
5
  import {VStack, Layout, LayoutContent} from '@astryxdesign/core/Layout';
7
6
  import {Text, Heading} from '@astryxdesign/core/Text';
8
7
  import {AspectRatio} from '@astryxdesign/core/AspectRatio';
8
+ import {Grid} from '@astryxdesign/core/Grid';
9
+ import {galleryImageClip} from 'astryx-dracula/shared/gallery-image';
10
+ import {SceneTile} from 'astryx-dracula/shared/scene-tile';
11
+ import type {SceneHue} from 'astryx-dracula/shared/scene-hues';
9
12
 
10
13
  // ─── Styles ────────────────────────────────────────────────────────────────
11
- // The masonry needs a responsive column count AND a hero that spans 2 columns
12
- // on desktop but goes full-width on mobile. Grid forces grid-template-columns
13
- // inline, so a responsive span can't be expressed through its props — this is a
14
- // @container grid (the sanctioned Astryx pattern for container-responsive layout).
15
- // The container query lives in a plain <style> tag below so it needs NO CSS
16
- // compiler. Image fill + radius are custom because Astryx has no image
17
- // primitive (#2582).
18
-
19
- // Named inline-size container on the page column so the grid responds to the
20
- // available content width (works inside the sandbox's resizable preview).
21
- const containerStyle: CSSProperties = {
22
- containerType: 'inline-size',
23
- containerName: 'gallery',
24
- };
25
- // Fills the AspectRatio box with a Dracula placeholder scene. No Image
26
- // primitive in Astryx (#2582), so gallery tiles are inline SVG on brand
27
- // tokens instead of light-mode data-URI bitmaps.
28
- const svgStyle: CSSProperties = {
29
- width: '100%',
30
- height: '100%',
31
- display: 'block',
32
- };
33
- // Rounds the image corners. No radius prop on AspectRatio (#2582).
34
- const clipStyle: CSSProperties = {
35
- borderRadius: 'var(--radius-element)',
36
- };
37
-
38
- // 3 columns on desktop, dropping straight to 1 column below 720px (no 2-col
39
- // middle state). minmax(0, 1fr) (not 1fr) so tracks split evenly and ignore the
40
- // images' intrinsic min-width. The hero spans 2 columns on desktop, then fills
41
- // the row once it's single-column.
42
- const GALLERY_CSS = `
43
- .mixed-gallery-grid {
44
- display: grid;
45
- gap: var(--spacing-3);
46
- grid-template-columns: repeat(3, minmax(0, 1fr));
47
- }
48
- .mixed-gallery-hero {
49
- grid-column: span 2;
50
- }
51
- /* The hero image stretches to the row height instead of keeping its own
52
- ratio: a 3:1 hero spanning 2 columns + 1 gap is taller than the 3:2 sidebar
53
- by exactly gap/3, so ratio-driven heights can never align. The sidebar keeps
54
- its ratio (it defines the row height); the hero flex-fills the leftover cell
55
- height. flex-basis is 0px — not 0%: a percentage basis falls back to content
56
- size against the indefinite grid-row measurement, which would let the hero's
57
- own ratio define the row again. 0px contributes nothing, so the row follows
58
- the sidebar exactly (equal single-line captions keep the math exact), and
59
- the hero grows into it. AspectRatio's aspect-ratio yields once flex gives it
60
- a definite height; the svg slice-fills either way. */
61
- .mixed-gallery-hero > :first-child {
62
- flex: 1 1 0px;
63
- min-height: 0;
64
- }
65
- @container gallery (max-width: 720px) {
66
- .mixed-gallery-grid {
67
- grid-template-columns: minmax(0, 1fr);
68
- }
69
- .mixed-gallery-hero {
70
- grid-column: 1 / -1;
71
- }
72
- /* Single column: no sibling defines the row, so the hero falls back to its
73
- own 3:1 ratio. */
74
- .mixed-gallery-hero > :first-child {
75
- flex: none;
76
- }
77
- }
78
- `;
14
+ // Image fill + radius live in shared/gallery-image (no Image primitive in
15
+ // Astryx, #2582). Tile art lives in shared/scene-tile (large fork).
79
16
 
80
17
  // ─── Gallery Data ───────────────────────────────────────────────────────────
81
18
 
82
19
  interface GalleryImage {
83
20
  title: string;
84
- hue: string;
21
+ hue: SceneHue;
85
22
  }
86
23
 
87
24
  // One accent per tile from the fixed badge vocabulary; the SVG scenes below
88
25
  // resolve to Dracula tokens so tiles stay on-brand in the dark-only theme.
89
26
  const IMAGES: GalleryImage[] = [
90
- {title: 'The castle at moonrise', hue: 'var(--dracula-purple)'},
27
+ {title: 'The castle at moonrise', hue: 'var(--dracula-orange)'},
91
28
  {title: 'Coven gathering', hue: 'var(--dracula-cyan)'},
92
29
  {title: 'Belfry view', hue: 'var(--dracula-pink)'},
93
30
  {title: 'Crypt archives', hue: 'var(--dracula-yellow)'},
@@ -98,42 +35,15 @@ const IMAGES: GalleryImage[] = [
98
35
  // Each tile is an image plus its caption (titles lived only in aria-labels
99
36
  // before, leaving the tiles cryptic). AspectRatio gives every image a
100
37
  // definite, self-contained height from its ratio, so images can't overflow
101
- // their grid cell (no row-track guesswork). The hero image stretches to the
102
- // row height instead via GALLERY_CSS (see above).
38
+ // their grid cell and no tile depends on a neighbour's caption height.
103
39
 
104
- function GalleryCard({
105
- image,
106
- ratio,
107
- className,
108
- }: {
109
- image: GalleryImage;
110
- ratio: number;
111
- className?: string;
112
- }) {
40
+ function GalleryCard({image, ratio}: {image: GalleryImage; ratio: number}) {
113
41
  return (
114
- <VStack gap={2} className={className}>
115
- <AspectRatio ratio={ratio} style={clipStyle}>
116
- <svg
117
- viewBox="0 0 400 300"
118
- preserveAspectRatio="xMidYMid slice"
119
- style={svgStyle}
120
- role="img"
121
- aria-label={image.title}>
122
- <rect width="400" height="300" fill="var(--dracula-bg-light)" />
123
- <g
124
- transform="translate(200 150)"
125
- fill="none"
126
- stroke="var(--dracula-comment)"
127
- strokeWidth="5"
128
- strokeLinecap="round"
129
- strokeLinejoin="round">
130
- <rect x="-44" y="-44" width="88" height="88" rx="5" />
131
- <circle cx="18" cy="-18" r="2.5" fill={image.hue} stroke="none" />
132
- <path d="M-34 30 L-8 0 L10 18 L20 8 L34 24" />
133
- </g>
134
- </svg>
42
+ <VStack gap={2}>
43
+ <AspectRatio ratio={ratio} style={galleryImageClip}>
44
+ <SceneTile label={image.title} hue={image.hue} size="lg" />
135
45
  </AspectRatio>
136
- <Text type="supporting" justify="center">
46
+ <Text type="body" color="secondary" justify="center">
137
47
  {image.title}
138
48
  </Text>
139
49
  </VStack>
@@ -149,41 +59,30 @@ export default function MixedGallery() {
149
59
  contentWidth={1400}
150
60
  content={
151
61
  <LayoutContent padding={6}>
152
- <style>{GALLERY_CSS}</style>
153
- <VStack gap={6} style={containerStyle}>
62
+ <VStack gap={8}>
154
63
  {/* Header */}
155
64
  <VStack gap={2} hAlign="center">
156
65
  <Heading level={1} justify="center">
157
66
  Every corner of the castle, caught after dark.
158
67
  </Heading>
159
68
  <Text type="body" color="secondary" justify="center">
160
- Relics, sketches, and moonlit views from the coven archives —
69
+ Relics, sketches, and moonlit views from the coven archives,
161
70
  collected over one long Transylvanian night.
162
71
  </Text>
163
72
  </VStack>
164
73
 
165
- {/* Featured layout — a wide hero next to a single tile, above a row
166
- of three. The sidebar's 3:2 image defines the top-row height and
167
- the hero stretches to it exactly (equal captions keep the math
168
- exact). The bottom row is three equal 3:2 tiles. Responsive via
169
- @container: 3 columns → 1 column at ≤720px, where the hero
170
- falls back to its 3:1 ratio. */}
171
- <div className="mixed-gallery-grid">
172
- {/* Hero — spans 2 columns and stretches to the sidebar's height */}
173
- <GalleryCard
174
- image={IMAGES[0]}
175
- ratio={3 / 1}
176
- className="mixed-gallery-hero"
177
- />
178
-
179
- {/* Sidebar — its ratio defines the row height */}
180
- <GalleryCard image={IMAGES[2]} ratio={3 / 2} />
181
-
182
- {/* Bottom row — three equal tiles */}
183
- <GalleryCard image={IMAGES[3]} ratio={3 / 2} />
184
- <GalleryCard image={IMAGES[4]} ratio={3 / 2} />
185
- <GalleryCard image={IMAGES[1]} ratio={3 / 2} />
186
- </div>
74
+ {/* Featured layout: the wide 3:1 hero heads the page, then the rest
75
+ of the set reflows as a grid (4 → 2 → 1 columns). Every tile
76
+ keeps its own ratio, so no tile's height depends on another's
77
+ caption wrapping. */}
78
+ <VStack gap={3}>
79
+ <GalleryCard image={IMAGES[0]} ratio={3 / 1} />
80
+ <Grid columns={{minWidth: 280}} gap={4}>
81
+ {IMAGES.slice(1).map(image => (
82
+ <GalleryCard key={image.title} image={image} ratio={3 / 2} />
83
+ ))}
84
+ </Grid>
85
+ </VStack>
187
86
  </VStack>
188
87
  </LayoutContent>
189
88
  }