@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.
Files changed (137) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/README.md +117 -75
  3. package/bin/astryx.mjs +22 -7
  4. package/docs/icons.doc.mjs +1 -1
  5. package/docs/migration.doc.mjs +2 -2
  6. package/docs/shape.doc.mjs +1 -1
  7. package/docs/styling.doc.mjs +2 -2
  8. package/docs/theme.doc.dense.mjs +2 -2
  9. package/docs/theme.doc.mjs +14 -0
  10. package/docs/theme.doc.zh.mjs +2 -2
  11. package/docs/working-with-ai.doc.mjs +4 -4
  12. package/package.json +8 -8
  13. package/src/api/search.mjs +207 -13
  14. package/src/api/template.mjs +2 -1
  15. package/src/codemods/__tests__/registry.test.mjs +1 -0
  16. package/src/codemods/registry.mjs +1 -0
  17. package/src/codemods/runner.mjs +105 -51
  18. package/src/codemods/transforms/v0.1.0/__tests__/migrate-xds-config-surfaces.test.mjs +116 -0
  19. package/src/codemods/transforms/v0.1.0/__tests__/migrate-xds-module-specifiers.test.mjs +51 -0
  20. package/src/codemods/transforms/v0.1.0/index.mjs +28 -0
  21. package/src/codemods/transforms/v0.1.0/migrate-xds-config-surfaces.mjs +230 -0
  22. package/src/codemods/transforms/v0.1.0/migrate-xds-module-specifiers.mjs +84 -0
  23. package/src/commands/agent-docs.mjs +92 -56
  24. package/src/commands/agent-docs.path-safety.test.mjs +1 -1
  25. package/src/commands/agent-docs.test.mjs +66 -10
  26. package/src/commands/build-theme.import-path.test.mjs +1 -1
  27. package/src/commands/build-theme.path-safety.test.mjs +1 -1
  28. package/src/commands/build-theme.prose.test.mjs +1 -1
  29. package/src/commands/build.mjs +196 -0
  30. package/src/commands/component-package.test.mjs +1 -1
  31. package/src/commands/component.test.mjs +1 -1
  32. package/src/commands/docs.test.mjs +1 -1
  33. package/src/commands/doctor.test.mjs +1 -1
  34. package/src/commands/external-showcase.test.mjs +1 -1
  35. package/src/commands/init.mjs +9 -1
  36. package/src/commands/interactive-guard.test.mjs +1 -1
  37. package/src/commands/json-contract.test.mjs +10 -3
  38. package/src/commands/swizzle-gap-safety.test.mjs +1 -1
  39. package/src/commands/swizzle.path-safety.test.mjs +1 -1
  40. package/src/commands/template.path-safety.test.mjs +1 -1
  41. package/src/commands/template.test.mjs +1 -1
  42. package/src/commands/upgrade.mjs +353 -169
  43. package/src/commands/upgrade.test.mjs +41 -27
  44. package/src/index.mjs +1 -0
  45. package/src/lib/config.mjs +12 -0
  46. package/src/lib/config.test.mjs +42 -0
  47. package/src/lib/error-codes.mjs +3 -0
  48. package/src/types/error-codes.d.ts +1 -0
  49. package/src/utils/interactive.mjs +1 -1
  50. package/src/utils/interactive.test.mjs +2 -0
  51. package/src/utils/package-manager.test.mjs +1 -1
  52. package/src/utils/path-safety.test.mjs +1 -1
  53. package/src/utils/paths.test.mjs +8 -8
  54. package/src/utils/update-check.mjs +4 -26
  55. package/src/utils/update-check.test.mjs +2 -64
  56. package/templates/blocks/components/AppShell/AppShellContentOnly.tsx +1 -9
  57. package/templates/blocks/components/AppShell/AppShellShowcase.tsx +1 -10
  58. package/templates/blocks/components/AppShell/AppShellSideNavOnly.tsx +1 -9
  59. package/templates/blocks/components/AppShell/AppShellTopNavOnly.tsx +1 -9
  60. package/templates/blocks/components/AppShell/AppShellTopNavWithSideNav.tsx +1 -9
  61. package/templates/blocks/components/AppShell/AppShellWithBanner.tsx +1 -9
  62. package/templates/blocks/components/AspectRatio/AspectRatioShowcase.tsx +12 -19
  63. package/templates/blocks/components/Banner/BannerShowcase.tsx +1 -8
  64. package/templates/blocks/components/Blockquote/BlockquoteShowcase.tsx +1 -8
  65. package/templates/blocks/components/Carousel/CarouselShowcase.tsx +2 -12
  66. package/templates/blocks/components/ChatComposerDrawer/ChatComposerDrawerShowcase.tsx +6 -9
  67. package/templates/blocks/components/ChatLayout/ChatLayoutPanelChat.tsx +10 -12
  68. package/templates/blocks/components/ChatMessageList/ChatMessageListDensity.tsx +1 -9
  69. package/templates/blocks/components/ChatMessageList/ChatMessageListFullFeatured.tsx +1 -9
  70. package/templates/blocks/components/ChatMessageList/ChatMessageListShowcase.tsx +1 -9
  71. package/templates/blocks/components/ChatMessageMetadata/ChatMessageMetadataShowcase.tsx +1 -8
  72. package/templates/blocks/components/ChatSendButton/ChatSendButtonInComposer.tsx +1 -8
  73. package/templates/blocks/components/Citation/CitationInlineText.tsx +4 -4
  74. package/templates/blocks/components/Code/CodeInlineInParagraph.tsx +1 -8
  75. package/templates/blocks/components/CodeBlock/CodeBlockBashCommand.tsx +1 -1
  76. package/templates/blocks/components/CodeBlock/CodeBlockJSONConfig.tsx +1 -1
  77. package/templates/blocks/components/CommandPaletteItem/CommandPaletteItemShowcase.tsx +9 -12
  78. package/templates/blocks/components/ContextMenu/ContextMenuShowcase.tsx +13 -15
  79. package/templates/blocks/components/Divider/DividerShowcase.tsx +1 -8
  80. package/templates/blocks/components/Divider/DividerVertical.tsx +7 -9
  81. package/templates/blocks/components/Field/FieldShowcase.tsx +1 -8
  82. package/templates/blocks/components/FormLayout/FormLayoutHorizontal.tsx +1 -6
  83. package/templates/blocks/components/Grid/GridResponsiveAutoFit.tsx +1 -9
  84. package/templates/blocks/components/HoverCard/HoverCardInlineTextHoverCard.tsx +4 -6
  85. package/templates/blocks/components/HoverCard/HoverCardInteractiveContent.tsx +1 -6
  86. package/templates/blocks/components/HoverCard/HoverCardProfileHoverCard.tsx +2 -8
  87. package/templates/blocks/components/HoverCard/HoverCardShowcase.tsx +1 -8
  88. package/templates/blocks/components/MoreMenu/MoreMenuInToolbar.tsx +2 -12
  89. package/templates/blocks/components/OverflowList/OverflowListOverflowBadges.tsx +8 -11
  90. package/templates/blocks/components/OverflowList/OverflowListOverflowDropdownActions.tsx +9 -12
  91. package/templates/blocks/components/Overlay/OverlayBottomStrip.tsx +4 -17
  92. package/templates/blocks/components/Overlay/OverlayHoverReveal.tsx +15 -16
  93. package/templates/blocks/components/Overlay/OverlayShowcase.tsx +5 -21
  94. package/templates/blocks/components/Pagination/PaginationDotsCarousel.tsx +2 -14
  95. package/templates/blocks/components/Pagination/PaginationPageSize.tsx +12 -14
  96. package/templates/blocks/components/Pagination/PaginationVariants.tsx +1 -8
  97. package/templates/blocks/components/Pagination/PaginationWithTable.tsx +2 -14
  98. package/templates/blocks/components/Tokenizer/TokenizerClear.tsx +1 -6
  99. package/templates/blocks/components/Tokenizer/TokenizerCreatable.tsx +2 -7
  100. package/templates/blocks/components/Tokenizer/TokenizerEndContent.tsx +1 -6
  101. package/templates/blocks/components/Tokenizer/TokenizerIcon.tsx +1 -6
  102. package/templates/blocks/components/Tokenizer/TokenizerMaxEntries.tsx +1 -6
  103. package/templates/blocks/components/Tokenizer/TokenizerOverflow.tsx +2 -7
  104. package/templates/blocks/components/Tokenizer/TokenizerShowcase.tsx +1 -6
  105. package/templates/blocks/components/Tokenizer/TokenizerStates.tsx +4 -9
  106. package/templates/blocks/components/Toolbar/ToolbarCardHeader.tsx +1 -10
  107. package/templates/blocks/components/Toolbar/ToolbarSizes.tsx +1 -8
  108. package/templates/blocks/components/Toolbar/ToolbarTableFilter.tsx +1 -8
  109. package/templates/blocks/components/Toolbar/ToolbarThreeSlot.tsx +1 -10
  110. package/templates/blocks/components/Toolbar/ToolbarWithTabs.tsx +8 -11
  111. package/templates/pages/ai-chat/page.tsx +71 -64
  112. package/templates/pages/ai-chat-landing/page.tsx +8 -12
  113. package/templates/pages/centered-hero/page.tsx +13 -15
  114. package/templates/pages/classic-gallery/page.tsx +27 -34
  115. package/templates/pages/detail-page/page.tsx +18 -18
  116. package/templates/pages/documentation/page.tsx +11 -14
  117. package/templates/pages/documentation-design/page.tsx +10 -13
  118. package/templates/pages/documentation-technical/page.tsx +15 -16
  119. package/templates/pages/editor/page.tsx +42 -54
  120. package/templates/pages/file-explorer/page.tsx +13 -16
  121. package/templates/pages/form-two-column/page.tsx +13 -17
  122. package/templates/pages/gallery-hero/page.tsx +13 -15
  123. package/templates/pages/ide/page.tsx +32 -39
  124. package/templates/pages/library/page.tsx +16 -23
  125. package/templates/pages/login/page.tsx +14 -18
  126. package/templates/pages/login-card/page.tsx +14 -18
  127. package/templates/pages/login-split/page.tsx +50 -48
  128. package/templates/pages/login-sso/page.tsx +9 -13
  129. package/templates/pages/mixed-gallery/page.tsx +51 -45
  130. package/templates/pages/payment-form/page.tsx +56 -70
  131. package/templates/pages/product-detail/page.tsx +27 -33
  132. package/templates/pages/product-gallery/page.tsx +7 -13
  133. package/templates/pages/settings-dialog/page.tsx +35 -43
  134. package/templates/pages/settings-sidebar/page.tsx +39 -47
  135. package/templates/pages/side-gallery/page.tsx +6 -9
  136. package/templates/pages/table-grouped/page.tsx +11 -15
  137. 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
- // Image fill + radius are also custom because Astryx has no image primitive (#2582).
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
- const styles = stylex.create({
18
- // Named inline-size container on the page column so the grid responds to the
19
- // available content width (works inside the sandbox's resizable preview).
20
- container: {
21
- containerType: 'inline-size',
22
- containerName: 'gallery',
23
- },
24
- // 3 columns on desktop, dropping straight to 1 column below 720px (no 2-col
25
- // middle state). minmax(0, 1fr) (not 1fr) so tracks split evenly and ignore
26
- // the images' intrinsic min-width.
27
- grid: {
28
- display: 'grid',
29
- gap: 'var(--spacing-3)',
30
- gridTemplateColumns: {
31
- default: 'repeat(3, minmax(0, 1fr))',
32
- '@container gallery (max-width: 720px)': 'minmax(0, 1fr)',
33
- },
34
- },
35
- // Hero spans 2 columns on desktop, then fills the row once it's single-column.
36
- hero: {
37
- gridColumn: {
38
- default: 'span 2',
39
- '@container gallery (max-width: 720px)': '1 / -1',
40
- },
41
- },
42
- // Fills the AspectRatio box. No objectFit prop on AspectRatio (#2582).
43
- img: {
44
- width: '100%',
45
- height: '100%',
46
- objectFit: 'cover',
47
- },
48
- // Rounds the image corners. No radius prop on AspectRatio (#2582).
49
- clip: {
50
- borderRadius: 'var(--radius-element)',
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
- xstyle,
97
+ className,
93
98
  }: {
94
99
  image: GalleryImage;
95
100
  ratio: number;
96
- xstyle?: stylex.StyleXStyles;
101
+ className?: string;
97
102
  }) {
98
103
  return (
99
- <AspectRatio ratio={ratio} xstyle={[styles.clip, xstyle]}>
100
- <img src={image.src} alt={image.title} {...stylex.props(styles.img)} />
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
- <VStack gap={6} xstyle={styles.container}>
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 {...stylex.props(styles.grid)}>
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
- xstyle={styles.hero}
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 styles = stylex.create({
161
- fullWidth: {width: '100%'},
162
- // LayoutContent clips overflow by default, which traps position:sticky
163
- // children (the sticky order summary). With height="auto" the page scrolls
164
- // at the window, so let overflow be visible here so sticky can pin.
165
- visibleOverflow: {overflow: 'visible'},
166
- // Form column flex-basis so the two checkout columns share width evenly.
167
- formColBasis: {flexBasis: 0},
168
- // Space the Order Summary content below its collapsible trigger title.
169
- summaryContent: {paddingBlockStart: spacingVars['--spacing-2']},
170
- // Order-summary column: sticky beside the form on desktop.
171
- summarySticky: {
172
- flexBasis: 0,
173
- position: 'sticky',
174
- top: spacingVars['--spacing-4'],
175
- alignSelf: 'flex-start',
176
- },
177
- // On mobile the summary moves above the form.
178
- summaryMobileOrder: {order: -1},
179
- // Express-checkout brand buttons (fixed brand colors).
180
- paypalButton: {backgroundColor: '#FFC439', borderColor: '#FFC439'},
181
- // Official Google Pay dark button: black background with the unaltered
182
- // dark-variant mark (white "Google Pay" text + full-color G), per the
183
- // Google Pay brand guidelines.
184
- gpayButton: {backgroundColor: '#000', borderColor: '#000'},
185
- // Brand logos inside the express-checkout buttons.
186
- paypalLogo: {height: spacingVars['--spacing-5'], width: 'auto'},
187
- // Unaltered Google Pay mark (no filter/recolor — brand requirement),
188
- // sized so it keeps comfortable clear space inside the lg button.
189
- gpayLogo: {
190
- height: spacingVars['--spacing-5'],
191
- width: 'auto',
192
- },
193
- // Accepted card-network marks (Visa/Mastercard/Amex), shared style.
194
- cardLogo: {
195
- height: spacingVars['--spacing-7'],
196
- width: 'auto',
197
- borderRadius: radiusVars['--radius-element'],
198
- borderWidth: borderVars['--border-width'],
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} xstyle={styles.visibleOverflow}>
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
- xstyle={isMobile ? undefined : styles.formColBasis}>
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
- xstyle={styles.paypalButton}>
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
- {...stylex.props(styles.paypalLogo)}
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
- xstyle={styles.gpayButton}>
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
- {...stylex.props(styles.gpayLogo)}
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
- {...stylex.props(styles.cardLogo)}
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
- {...stylex.props(styles.cardLogo)}
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
- {...stylex.props(styles.cardLogo)}
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
- xstyle={styles.fullWidth}
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
- xstyle={styles.fullWidth}
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
- xstyle={styles.fullWidth}
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
- xstyle={
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} xstyle={styles.summaryContent}>
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 * as stylex from '@stylexjs/stylex';
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
- const pageStyles = stylex.create({
33
- // Keeps the info column in view while the gallery scrolls. No sticky prop on
34
- // Astryx layout primitives.
35
- stickyInfo: {
36
- position: 'sticky',
37
- top: 'var(--spacing-8)',
38
- alignSelf: 'start',
39
- },
40
- // Fills the AspectRatio box + rounds corners. No objectFit/radius props on
41
- // AspectRatio (#2582).
42
- heroImage: {
43
- width: '100%',
44
- height: '100%',
45
- objectFit: 'cover',
46
- borderRadius: 'var(--radius-container)',
47
- },
48
- // Fills the thumbnail card. Corner radius + selection ring come from
49
- // SelectableCard; the image only needs to fill and cover (#2582).
50
- thumbImage: {
51
- width: '100%',
52
- height: '100%',
53
- objectFit: 'cover',
54
- display: 'block',
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
- {...stylex.props(pageStyles.thumbImage)}
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} xstyle={pageStyles.stickyInfo}>
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 * as stylex from '@stylexjs/stylex';
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 styles = stylex.create({
20
- image: {
21
- width: '100%',
22
- height: '100%',
23
- objectFit: 'cover',
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}>