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