@astryxdesign/cli 0.1.0-canary.f94dd07 → 0.1.1-canary.a514b99
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/CHANGELOG.md +68 -0
- package/README.md +117 -75
- package/bin/astryx.mjs +22 -7
- package/docs/icons.doc.mjs +1 -1
- package/docs/migration.doc.mjs +2 -2
- package/docs/shape.doc.mjs +1 -1
- package/docs/styling.doc.mjs +2 -2
- package/docs/theme.doc.dense.mjs +2 -2
- package/docs/theme.doc.mjs +14 -0
- package/docs/theme.doc.zh.mjs +2 -2
- package/docs/working-with-ai.doc.mjs +4 -4
- package/package.json +8 -8
- package/src/api/search.mjs +207 -13
- package/src/api/template.mjs +2 -1
- package/src/codemods/__tests__/registry.test.mjs +1 -0
- package/src/codemods/registry.mjs +1 -0
- package/src/codemods/runner.mjs +105 -51
- package/src/codemods/transforms/v0.1.0/__tests__/migrate-xds-config-surfaces.test.mjs +116 -0
- package/src/codemods/transforms/v0.1.0/__tests__/migrate-xds-module-specifiers.test.mjs +51 -0
- package/src/codemods/transforms/v0.1.0/index.mjs +28 -0
- package/src/codemods/transforms/v0.1.0/migrate-xds-config-surfaces.mjs +230 -0
- package/src/codemods/transforms/v0.1.0/migrate-xds-module-specifiers.mjs +84 -0
- package/src/commands/agent-docs.mjs +92 -56
- package/src/commands/agent-docs.path-safety.test.mjs +1 -1
- package/src/commands/agent-docs.test.mjs +66 -10
- package/src/commands/build-theme.import-path.test.mjs +1 -1
- package/src/commands/build-theme.path-safety.test.mjs +1 -1
- package/src/commands/build-theme.prose.test.mjs +1 -1
- package/src/commands/build.mjs +196 -0
- package/src/commands/component-package.test.mjs +1 -1
- package/src/commands/component.test.mjs +1 -1
- package/src/commands/docs.test.mjs +1 -1
- package/src/commands/doctor.test.mjs +1 -1
- package/src/commands/external-showcase.test.mjs +1 -1
- package/src/commands/init.mjs +9 -1
- package/src/commands/interactive-guard.test.mjs +1 -1
- package/src/commands/json-contract.test.mjs +10 -3
- package/src/commands/swizzle-gap-safety.test.mjs +1 -1
- package/src/commands/swizzle.path-safety.test.mjs +1 -1
- package/src/commands/template.path-safety.test.mjs +1 -1
- package/src/commands/template.test.mjs +1 -1
- package/src/commands/upgrade.mjs +353 -169
- package/src/commands/upgrade.test.mjs +41 -27
- package/src/index.mjs +1 -0
- package/src/lib/config.mjs +12 -0
- package/src/lib/config.test.mjs +42 -0
- package/src/lib/error-codes.mjs +3 -0
- package/src/types/error-codes.d.ts +1 -0
- package/src/utils/interactive.mjs +1 -1
- package/src/utils/interactive.test.mjs +2 -0
- package/src/utils/package-manager.test.mjs +1 -1
- package/src/utils/path-safety.test.mjs +1 -1
- package/src/utils/paths.test.mjs +8 -8
- package/src/utils/update-check.mjs +4 -26
- package/src/utils/update-check.test.mjs +2 -64
- package/templates/blocks/components/AppShell/AppShellContentOnly.tsx +1 -9
- package/templates/blocks/components/AppShell/AppShellShowcase.tsx +1 -10
- package/templates/blocks/components/AppShell/AppShellSideNavOnly.tsx +1 -9
- package/templates/blocks/components/AppShell/AppShellTopNavOnly.tsx +1 -9
- package/templates/blocks/components/AppShell/AppShellTopNavWithSideNav.tsx +1 -9
- package/templates/blocks/components/AppShell/AppShellWithBanner.tsx +1 -9
- package/templates/blocks/components/AspectRatio/AspectRatioShowcase.tsx +12 -19
- package/templates/blocks/components/Banner/BannerShowcase.tsx +1 -8
- package/templates/blocks/components/Blockquote/BlockquoteShowcase.tsx +1 -8
- package/templates/blocks/components/Carousel/CarouselShowcase.tsx +2 -12
- package/templates/blocks/components/ChatComposerDrawer/ChatComposerDrawerShowcase.tsx +6 -9
- package/templates/blocks/components/ChatLayout/ChatLayoutPanelChat.tsx +10 -12
- package/templates/blocks/components/ChatMessageList/ChatMessageListDensity.tsx +1 -9
- package/templates/blocks/components/ChatMessageList/ChatMessageListFullFeatured.tsx +1 -9
- package/templates/blocks/components/ChatMessageList/ChatMessageListShowcase.tsx +1 -9
- package/templates/blocks/components/ChatMessageMetadata/ChatMessageMetadataShowcase.tsx +1 -8
- package/templates/blocks/components/ChatSendButton/ChatSendButtonInComposer.tsx +1 -8
- package/templates/blocks/components/Citation/CitationInlineText.tsx +4 -4
- package/templates/blocks/components/Code/CodeInlineInParagraph.tsx +1 -8
- package/templates/blocks/components/CodeBlock/CodeBlockBashCommand.tsx +1 -1
- package/templates/blocks/components/CodeBlock/CodeBlockJSONConfig.tsx +1 -1
- package/templates/blocks/components/CommandPaletteItem/CommandPaletteItemShowcase.tsx +9 -12
- package/templates/blocks/components/ContextMenu/ContextMenuShowcase.tsx +13 -15
- package/templates/blocks/components/Divider/DividerShowcase.tsx +1 -8
- package/templates/blocks/components/Divider/DividerVertical.tsx +7 -9
- package/templates/blocks/components/Field/FieldShowcase.tsx +1 -8
- package/templates/blocks/components/FormLayout/FormLayoutHorizontal.tsx +1 -6
- package/templates/blocks/components/Grid/GridResponsiveAutoFit.tsx +1 -9
- package/templates/blocks/components/HoverCard/HoverCardInlineTextHoverCard.tsx +4 -6
- package/templates/blocks/components/HoverCard/HoverCardInteractiveContent.tsx +1 -6
- package/templates/blocks/components/HoverCard/HoverCardProfileHoverCard.tsx +2 -8
- package/templates/blocks/components/HoverCard/HoverCardShowcase.tsx +1 -8
- package/templates/blocks/components/MoreMenu/MoreMenuInToolbar.tsx +2 -12
- package/templates/blocks/components/OverflowList/OverflowListOverflowBadges.tsx +8 -11
- package/templates/blocks/components/OverflowList/OverflowListOverflowDropdownActions.tsx +9 -12
- package/templates/blocks/components/Overlay/OverlayBottomStrip.tsx +4 -17
- package/templates/blocks/components/Overlay/OverlayHoverReveal.tsx +15 -16
- package/templates/blocks/components/Overlay/OverlayShowcase.tsx +5 -21
- package/templates/blocks/components/Pagination/PaginationDotsCarousel.tsx +2 -14
- package/templates/blocks/components/Pagination/PaginationPageSize.tsx +12 -14
- package/templates/blocks/components/Pagination/PaginationVariants.tsx +1 -8
- package/templates/blocks/components/Pagination/PaginationWithTable.tsx +2 -14
- package/templates/blocks/components/Tokenizer/TokenizerClear.tsx +1 -6
- package/templates/blocks/components/Tokenizer/TokenizerCreatable.tsx +2 -7
- package/templates/blocks/components/Tokenizer/TokenizerEndContent.tsx +1 -6
- package/templates/blocks/components/Tokenizer/TokenizerIcon.tsx +1 -6
- package/templates/blocks/components/Tokenizer/TokenizerMaxEntries.tsx +1 -6
- package/templates/blocks/components/Tokenizer/TokenizerOverflow.tsx +2 -7
- package/templates/blocks/components/Tokenizer/TokenizerShowcase.tsx +1 -6
- package/templates/blocks/components/Tokenizer/TokenizerStates.tsx +4 -9
- package/templates/blocks/components/Toolbar/ToolbarCardHeader.tsx +1 -10
- package/templates/blocks/components/Toolbar/ToolbarSizes.tsx +1 -8
- package/templates/blocks/components/Toolbar/ToolbarTableFilter.tsx +1 -8
- package/templates/blocks/components/Toolbar/ToolbarThreeSlot.tsx +1 -10
- package/templates/blocks/components/Toolbar/ToolbarWithTabs.tsx +8 -11
- package/templates/pages/ai-chat/page.tsx +71 -64
- package/templates/pages/ai-chat-landing/page.tsx +8 -12
- package/templates/pages/centered-hero/page.tsx +13 -15
- package/templates/pages/classic-gallery/page.tsx +27 -34
- package/templates/pages/detail-page/page.tsx +18 -18
- package/templates/pages/documentation/page.tsx +11 -14
- package/templates/pages/documentation-design/page.tsx +10 -13
- package/templates/pages/documentation-technical/page.tsx +15 -16
- package/templates/pages/editor/page.tsx +42 -54
- package/templates/pages/file-explorer/page.tsx +13 -16
- package/templates/pages/form-two-column/page.tsx +13 -17
- package/templates/pages/gallery-hero/page.tsx +13 -15
- package/templates/pages/ide/page.tsx +32 -39
- package/templates/pages/library/page.tsx +16 -23
- package/templates/pages/login/page.tsx +14 -18
- package/templates/pages/login-card/page.tsx +14 -18
- package/templates/pages/login-split/page.tsx +50 -48
- package/templates/pages/login-sso/page.tsx +9 -13
- package/templates/pages/mixed-gallery/page.tsx +51 -45
- package/templates/pages/payment-form/page.tsx +56 -70
- package/templates/pages/product-detail/page.tsx +27 -33
- package/templates/pages/product-gallery/page.tsx +7 -13
- package/templates/pages/settings-dialog/page.tsx +35 -43
- package/templates/pages/settings-sidebar/page.tsx +39 -47
- package/templates/pages/side-gallery/page.tsx +6 -9
- package/templates/pages/table-grouped/page.tsx +11 -15
- package/templates/pages/theme-showcase/page.tsx +33 -37
|
@@ -2,54 +2,59 @@
|
|
|
2
2
|
|
|
3
3
|
'use client';
|
|
4
4
|
|
|
5
|
+
import type {CSSProperties} from 'react';
|
|
5
6
|
import {VStack, Layout, LayoutContent} from '@astryxdesign/core/Layout';
|
|
6
7
|
import {Text, Heading} from '@astryxdesign/core/Text';
|
|
7
8
|
import {AspectRatio} from '@astryxdesign/core/AspectRatio';
|
|
8
|
-
import * as stylex from '@stylexjs/stylex';
|
|
9
9
|
|
|
10
10
|
// ─── Styles ────────────────────────────────────────────────────────────────
|
|
11
11
|
// The masonry needs a responsive column count AND a hero that spans 2 columns
|
|
12
12
|
// on desktop but goes full-width on mobile. Grid forces grid-template-columns
|
|
13
13
|
// inline, so a responsive span can't be expressed through its props — this is a
|
|
14
14
|
// @container grid (the sanctioned Astryx pattern for container-responsive layout).
|
|
15
|
-
//
|
|
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).
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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. No objectFit prop on AspectRatio (#2582).
|
|
26
|
+
const imgStyle: CSSProperties = {
|
|
27
|
+
width: '100%',
|
|
28
|
+
height: '100%',
|
|
29
|
+
objectFit: 'cover',
|
|
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
|
+
@container gallery (max-width: 720px) {
|
|
50
|
+
.mixed-gallery-grid {
|
|
51
|
+
grid-template-columns: minmax(0, 1fr);
|
|
52
|
+
}
|
|
53
|
+
.mixed-gallery-hero {
|
|
54
|
+
grid-column: 1 / -1;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
`;
|
|
53
58
|
|
|
54
59
|
// ─── Gallery Data ───────────────────────────────────────────────────────────
|
|
55
60
|
|
|
@@ -89,15 +94,15 @@ const IMAGES: GalleryImage[] = [
|
|
|
89
94
|
function GalleryCard({
|
|
90
95
|
image,
|
|
91
96
|
ratio,
|
|
92
|
-
|
|
97
|
+
className,
|
|
93
98
|
}: {
|
|
94
99
|
image: GalleryImage;
|
|
95
100
|
ratio: number;
|
|
96
|
-
|
|
101
|
+
className?: string;
|
|
97
102
|
}) {
|
|
98
103
|
return (
|
|
99
|
-
<AspectRatio ratio={ratio}
|
|
100
|
-
<img src={image.src} alt={image.title} {
|
|
104
|
+
<AspectRatio ratio={ratio} className={className} style={clipStyle}>
|
|
105
|
+
<img src={image.src} alt={image.title} style={imgStyle} />
|
|
101
106
|
</AspectRatio>
|
|
102
107
|
);
|
|
103
108
|
}
|
|
@@ -111,7 +116,8 @@ export default function MixedGalleryTemplate() {
|
|
|
111
116
|
contentWidth={1400}
|
|
112
117
|
content={
|
|
113
118
|
<LayoutContent padding={6}>
|
|
114
|
-
<
|
|
119
|
+
<style>{GALLERY_CSS}</style>
|
|
120
|
+
<VStack gap={6} style={containerStyle}>
|
|
115
121
|
{/* Header */}
|
|
116
122
|
<VStack gap={2} hAlign="center">
|
|
117
123
|
<Heading level={1} justify="center">
|
|
@@ -129,12 +135,12 @@ export default function MixedGalleryTemplate() {
|
|
|
129
135
|
(being 2 columns wide) it matches the row height exactly. All
|
|
130
136
|
rows are therefore the same height. Responsive via @container:
|
|
131
137
|
3 columns → 1 column at ≤720px. */}
|
|
132
|
-
<div
|
|
138
|
+
<div className="mixed-gallery-grid">
|
|
133
139
|
{/* Hero — spans 2 columns; 3:1 keeps it level with the sidebar */}
|
|
134
140
|
<GalleryCard
|
|
135
141
|
image={IMAGES[0]}
|
|
136
142
|
ratio={3 / 1}
|
|
137
|
-
|
|
143
|
+
className="mixed-gallery-hero"
|
|
138
144
|
/>
|
|
139
145
|
|
|
140
146
|
{/* Sidebar — same height as the hero */}
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
'use client';
|
|
4
4
|
|
|
5
|
-
import {useState} from 'react';
|
|
6
|
-
import * as stylex from '@stylexjs/stylex';
|
|
5
|
+
import {useState, type CSSProperties} from 'react';
|
|
7
6
|
import {
|
|
8
7
|
VStack,
|
|
9
8
|
HStack,
|
|
@@ -36,12 +35,6 @@ import {ShieldCheckIcon} from '@heroicons/react/24/outline';
|
|
|
36
35
|
import {LockClosedIcon} from '@heroicons/react/24/outline';
|
|
37
36
|
import {CheckCircleIcon} from '@heroicons/react/24/outline';
|
|
38
37
|
import {TruckIcon} from '@heroicons/react/24/outline';
|
|
39
|
-
import {
|
|
40
|
-
colorVars,
|
|
41
|
-
spacingVars,
|
|
42
|
-
radiusVars,
|
|
43
|
-
borderVars,
|
|
44
|
-
} from '@astryxdesign/core/theme/tokens.stylex';
|
|
45
38
|
|
|
46
39
|
// ── Constants ─────────────────────────────────────────────────────────────────
|
|
47
40
|
|
|
@@ -156,51 +149,48 @@ const TAX = 18.4;
|
|
|
156
149
|
const fmt = (n: number) => `$${n.toFixed(2)}`;
|
|
157
150
|
|
|
158
151
|
// ── Styles ────────────────────────────────────────────────────────────────────
|
|
152
|
+
// Plain inline styles using Astryx design-token CSS variables (declared at
|
|
153
|
+
// :root by `@astryxdesign/core/astryx.css`). No StyleX compiler required.
|
|
159
154
|
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
borderStyle: 'solid',
|
|
200
|
-
borderColor: colorVars['--color-border'],
|
|
201
|
-
backgroundColor: colorVars['--color-background-surface'],
|
|
202
|
-
},
|
|
203
|
-
});
|
|
155
|
+
const fullWidth: CSSProperties = {width: '100%'};
|
|
156
|
+
// LayoutContent clips overflow by default, which traps position:sticky
|
|
157
|
+
// children (the sticky order summary). With height="auto" the page scrolls
|
|
158
|
+
// at the window, so let overflow be visible here so sticky can pin.
|
|
159
|
+
const visibleOverflow: CSSProperties = {overflow: 'visible'};
|
|
160
|
+
// Form column flex-basis so the two checkout columns share width evenly.
|
|
161
|
+
const formColBasis: CSSProperties = {flexBasis: 0};
|
|
162
|
+
// Space the Order Summary content below its collapsible trigger title.
|
|
163
|
+
const summaryContent: CSSProperties = {paddingBlockStart: 'var(--spacing-2)'};
|
|
164
|
+
// Order-summary column: sticky beside the form on desktop.
|
|
165
|
+
const summarySticky: CSSProperties = {
|
|
166
|
+
flexBasis: 0,
|
|
167
|
+
position: 'sticky',
|
|
168
|
+
top: 'var(--spacing-4)',
|
|
169
|
+
alignSelf: 'flex-start',
|
|
170
|
+
};
|
|
171
|
+
// On mobile the summary moves above the form.
|
|
172
|
+
const summaryMobileOrder: CSSProperties = {order: -1};
|
|
173
|
+
// Express-checkout brand buttons (fixed brand colors).
|
|
174
|
+
const paypalButton: CSSProperties = {
|
|
175
|
+
backgroundColor: '#FFC439',
|
|
176
|
+
borderColor: '#FFC439',
|
|
177
|
+
};
|
|
178
|
+
// Official Google Pay dark button: black background with the unaltered
|
|
179
|
+
// dark-variant mark (white "Google Pay" text + full-color G), per the
|
|
180
|
+
// Google Pay brand guidelines.
|
|
181
|
+
const gpayButton: CSSProperties = {backgroundColor: '#000', borderColor: '#000'};
|
|
182
|
+
// Brand logos inside the express-checkout buttons.
|
|
183
|
+
const brandLogo: CSSProperties = {height: 'var(--spacing-5)', width: 'auto'};
|
|
184
|
+
// Accepted card-network marks (Visa/Mastercard/Amex), shared style.
|
|
185
|
+
const cardLogo: CSSProperties = {
|
|
186
|
+
height: 'var(--spacing-7)',
|
|
187
|
+
width: 'auto',
|
|
188
|
+
borderRadius: 'var(--radius-element)',
|
|
189
|
+
borderWidth: 'var(--border-width)',
|
|
190
|
+
borderStyle: 'solid',
|
|
191
|
+
borderColor: 'var(--color-border)',
|
|
192
|
+
backgroundColor: 'var(--color-background-surface)',
|
|
193
|
+
};
|
|
204
194
|
|
|
205
195
|
export default function PaymentFormPage() {
|
|
206
196
|
const isMobile = useMediaQuery('(max-width: 767px)');
|
|
@@ -278,7 +268,7 @@ export default function PaymentFormPage() {
|
|
|
278
268
|
<Layout
|
|
279
269
|
height="auto"
|
|
280
270
|
content={
|
|
281
|
-
<LayoutContent padding={0}
|
|
271
|
+
<LayoutContent padding={0} style={visibleOverflow}>
|
|
282
272
|
<Center axis="horizontal">
|
|
283
273
|
<Section
|
|
284
274
|
variant="transparent"
|
|
@@ -306,7 +296,7 @@ export default function PaymentFormPage() {
|
|
|
306
296
|
vAlign="start">
|
|
307
297
|
<StackItem
|
|
308
298
|
size="fill"
|
|
309
|
-
|
|
299
|
+
style={isMobile ? undefined : formColBasis}>
|
|
310
300
|
<VStack gap={8}>
|
|
311
301
|
{/* Sign in */}
|
|
312
302
|
<VStack gap={1}>
|
|
@@ -509,11 +499,11 @@ export default function PaymentFormPage() {
|
|
|
509
499
|
variant="primary"
|
|
510
500
|
size="lg"
|
|
511
501
|
onClick={() => {}}
|
|
512
|
-
|
|
502
|
+
style={paypalButton}>
|
|
513
503
|
<img
|
|
514
504
|
src="https://www.paypalobjects.com/webstatic/mktg/Logo/pp-logo-100px.png"
|
|
515
505
|
alt="PayPal"
|
|
516
|
-
{
|
|
506
|
+
style={brandLogo}
|
|
517
507
|
/>
|
|
518
508
|
</Button>
|
|
519
509
|
{/* Google Pay */}
|
|
@@ -522,11 +512,11 @@ export default function PaymentFormPage() {
|
|
|
522
512
|
variant="primary"
|
|
523
513
|
size="lg"
|
|
524
514
|
onClick={() => {}}
|
|
525
|
-
|
|
515
|
+
style={gpayButton}>
|
|
526
516
|
<img
|
|
527
517
|
src="https://pay.google.com/about/static_kcs/images/logos/google-pay-logo.svg"
|
|
528
518
|
alt="Google Pay"
|
|
529
|
-
{
|
|
519
|
+
style={brandLogo}
|
|
530
520
|
/>
|
|
531
521
|
</Button>
|
|
532
522
|
</Grid>
|
|
@@ -552,17 +542,17 @@ export default function PaymentFormPage() {
|
|
|
552
542
|
<img
|
|
553
543
|
src="https://raw.githubusercontent.com/aaronfagan/svg-credit-card-payment-icons/main/flat/visa.svg"
|
|
554
544
|
alt="Visa"
|
|
555
|
-
{
|
|
545
|
+
style={cardLogo}
|
|
556
546
|
/>
|
|
557
547
|
<img
|
|
558
548
|
src="https://raw.githubusercontent.com/aaronfagan/svg-credit-card-payment-icons/main/flat/mastercard.svg"
|
|
559
549
|
alt="Mastercard"
|
|
560
|
-
{
|
|
550
|
+
style={cardLogo}
|
|
561
551
|
/>
|
|
562
552
|
<img
|
|
563
553
|
src="https://raw.githubusercontent.com/aaronfagan/svg-credit-card-payment-icons/main/flat/amex.svg"
|
|
564
554
|
alt="Amex"
|
|
565
|
-
{
|
|
555
|
+
style={cardLogo}
|
|
566
556
|
/>
|
|
567
557
|
</HStack>
|
|
568
558
|
<TextInput
|
|
@@ -719,7 +709,7 @@ export default function PaymentFormPage() {
|
|
|
719
709
|
placeholder="Enter promo code"
|
|
720
710
|
value={promo}
|
|
721
711
|
onChange={setPromo}
|
|
722
|
-
|
|
712
|
+
style={fullWidth}
|
|
723
713
|
/>
|
|
724
714
|
</StackItem>
|
|
725
715
|
<Button
|
|
@@ -811,14 +801,14 @@ export default function PaymentFormPage() {
|
|
|
811
801
|
label="Place Order"
|
|
812
802
|
variant="primary"
|
|
813
803
|
size="lg"
|
|
814
|
-
|
|
804
|
+
style={fullWidth}
|
|
815
805
|
onClick={() => setSubmitted(true)}
|
|
816
806
|
/>
|
|
817
807
|
<Button
|
|
818
808
|
label="Continue Shopping"
|
|
819
809
|
variant="secondary"
|
|
820
810
|
size="lg"
|
|
821
|
-
|
|
811
|
+
style={fullWidth}
|
|
822
812
|
onClick={() => {}}
|
|
823
813
|
/>
|
|
824
814
|
</VStack>
|
|
@@ -843,18 +833,14 @@ export default function PaymentFormPage() {
|
|
|
843
833
|
|
|
844
834
|
<StackItem
|
|
845
835
|
size="fill"
|
|
846
|
-
|
|
847
|
-
isMobile
|
|
848
|
-
? styles.summaryMobileOrder
|
|
849
|
-
: styles.summarySticky
|
|
850
|
-
}>
|
|
836
|
+
style={isMobile ? summaryMobileOrder : summarySticky}>
|
|
851
837
|
<Card padding={5}>
|
|
852
838
|
<VStack gap={4}>
|
|
853
839
|
{/* Accordion header — clickable on mobile only */}
|
|
854
840
|
<Collapsible
|
|
855
841
|
trigger="Order Summary"
|
|
856
842
|
defaultIsOpen={true}>
|
|
857
|
-
<VStack gap={4}
|
|
843
|
+
<VStack gap={4} style={summaryContent}>
|
|
858
844
|
{/* Line items */}
|
|
859
845
|
{ORDER_ITEMS.map(item => (
|
|
860
846
|
<VStack key={item.id} gap={3}>
|
|
@@ -24,36 +24,34 @@ import {Divider} from '@astryxdesign/core/Divider';
|
|
|
24
24
|
import {Collapsible, CollapsibleGroup} from '@astryxdesign/core/Collapsible';
|
|
25
25
|
import {AspectRatio} from '@astryxdesign/core/AspectRatio';
|
|
26
26
|
import {SelectableCard} from '@astryxdesign/core/SelectableCard';
|
|
27
|
-
import
|
|
27
|
+
import type {CSSProperties} from 'react';
|
|
28
28
|
|
|
29
29
|
// Custom CSS here is limited to what Astryx components can't express today:
|
|
30
30
|
// - image fill + corner radius (no Image primitive — #2582)
|
|
31
31
|
// - the sticky info column (no sticky prop on Astryx layout primitives — #2613)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
},
|
|
56
|
-
});
|
|
32
|
+
// Keeps the info column in view while the gallery scrolls. No sticky prop on
|
|
33
|
+
// Astryx layout primitives.
|
|
34
|
+
const stickyInfo: CSSProperties = {
|
|
35
|
+
position: 'sticky',
|
|
36
|
+
top: 'var(--spacing-8)',
|
|
37
|
+
alignSelf: 'start',
|
|
38
|
+
};
|
|
39
|
+
// Fills the AspectRatio box + rounds corners. No objectFit/radius props on
|
|
40
|
+
// AspectRatio (#2582).
|
|
41
|
+
const heroImage: CSSProperties = {
|
|
42
|
+
width: '100%',
|
|
43
|
+
height: '100%',
|
|
44
|
+
objectFit: 'cover',
|
|
45
|
+
borderRadius: 'var(--radius-container)',
|
|
46
|
+
};
|
|
47
|
+
// Fills the thumbnail card. Corner radius + selection ring come from
|
|
48
|
+
// SelectableCard; the image only needs to fill and cover (#2582).
|
|
49
|
+
const thumbImage: CSSProperties = {
|
|
50
|
+
width: '100%',
|
|
51
|
+
height: '100%',
|
|
52
|
+
objectFit: 'cover',
|
|
53
|
+
display: 'block',
|
|
54
|
+
};
|
|
57
55
|
|
|
58
56
|
import {MinusIcon, PlusIcon, StarIcon} from '@heroicons/react/24/outline';
|
|
59
57
|
import {StarIcon as StarIconSolid} from '@heroicons/react/24/solid';
|
|
@@ -133,11 +131,7 @@ function ImageGallery({
|
|
|
133
131
|
return (
|
|
134
132
|
<VStack gap={3}>
|
|
135
133
|
<AspectRatio ratio={4 / 5}>
|
|
136
|
-
<img
|
|
137
|
-
{...stylex.props(pageStyles.heroImage)}
|
|
138
|
-
src={heroSrc}
|
|
139
|
-
alt={PRODUCT.name}
|
|
140
|
-
/>
|
|
134
|
+
<img style={heroImage} src={heroSrc} alt={PRODUCT.name} />
|
|
141
135
|
</AspectRatio>
|
|
142
136
|
<Grid columns={3} gap={2}>
|
|
143
137
|
{thumbnails.map((src, i) => (
|
|
@@ -151,7 +145,7 @@ function ImageGallery({
|
|
|
151
145
|
width="100%"
|
|
152
146
|
height="100%">
|
|
153
147
|
<img
|
|
154
|
-
{
|
|
148
|
+
style={thumbImage}
|
|
155
149
|
src={src}
|
|
156
150
|
alt={`Product image ${i + 1}`}
|
|
157
151
|
/>
|
|
@@ -301,7 +295,7 @@ export default function ProductDetailTemplate() {
|
|
|
301
295
|
selected={selectedThumb}
|
|
302
296
|
onSelect={setSelectedThumb}
|
|
303
297
|
/>
|
|
304
|
-
<VStack gap={0}
|
|
298
|
+
<VStack gap={0} style={stickyInfo}>
|
|
305
299
|
<ProductInfo />
|
|
306
300
|
</VStack>
|
|
307
301
|
</Grid>
|
|
@@ -10,19 +10,17 @@ import {AspectRatio} from '@astryxdesign/core/AspectRatio';
|
|
|
10
10
|
import {Card} from '@astryxdesign/core/Card';
|
|
11
11
|
import {Icon} from '@astryxdesign/core/Icon';
|
|
12
12
|
import {ArrowRightIcon} from '@heroicons/react/24/outline';
|
|
13
|
-
import
|
|
13
|
+
import type {CSSProperties} from 'react';
|
|
14
14
|
|
|
15
15
|
// ─── Styles ─────────────────────────────────────────────────────────────────
|
|
16
16
|
// The only custom CSS is the image fill — there is no Image primitive to
|
|
17
17
|
// fill the AspectRatio box with `object-fit` (#2582).
|
|
18
18
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
},
|
|
25
|
-
});
|
|
19
|
+
const image: CSSProperties = {
|
|
20
|
+
width: '100%',
|
|
21
|
+
height: '100%',
|
|
22
|
+
objectFit: 'cover',
|
|
23
|
+
};
|
|
26
24
|
|
|
27
25
|
// ─── Product Data ───────────────────────────────────────────────────────────
|
|
28
26
|
|
|
@@ -100,11 +98,7 @@ function ProductCard({product}: {product: Product}) {
|
|
|
100
98
|
<VStack gap={3}>
|
|
101
99
|
<Card padding={0}>
|
|
102
100
|
<AspectRatio ratio={1}>
|
|
103
|
-
<img
|
|
104
|
-
src={product.image}
|
|
105
|
-
alt={product.name}
|
|
106
|
-
{...stylex.props(styles.image)}
|
|
107
|
-
/>
|
|
101
|
+
<img src={product.image} alt={product.name} style={image} />
|
|
108
102
|
</AspectRatio>
|
|
109
103
|
</Card>
|
|
110
104
|
<VStack gap={1}>
|