@astryxdesign/cli 0.1.7 → 0.1.8-canary.0c4d8d7

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 (134) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +115 -19
  3. package/docs/cli-integrations.doc.mjs +150 -0
  4. package/docs/elevation.doc.mjs +79 -1
  5. package/docs/getting-started.doc.mjs +9 -9
  6. package/docs/migration.doc.mjs +18 -18
  7. package/docs/principles.doc.dense.mjs +1 -1
  8. package/docs/principles.doc.mjs +6 -6
  9. package/docs/principles.doc.zh.mjs +1 -1
  10. package/docs/styling-libraries.doc.mjs +3 -3
  11. package/docs/styling.doc.mjs +4 -4
  12. package/docs/theme.doc.dense.mjs +2 -2
  13. package/docs/theme.doc.mjs +7 -7
  14. package/docs/theme.doc.zh.mjs +1 -1
  15. package/docs/tokens.doc.mjs +1 -1
  16. package/docs/working-with-ai.doc.mjs +19 -19
  17. package/package.json +13 -11
  18. package/scripts/postinstall.mjs +74 -0
  19. package/src/api/doctor.mjs +3 -3
  20. package/src/api/error.mjs +2 -2
  21. package/src/codemods/__tests__/registry.test.mjs +1 -0
  22. package/src/codemods/ensure-jscodeshift.mjs +11 -27
  23. package/src/codemods/registry.mjs +1 -0
  24. package/src/codemods/run-codemod.mjs +1 -1
  25. package/src/codemods/runner.mjs +2 -2
  26. package/src/codemods/transforms/v0.1.0/__tests__/drop-xds-prefix-imports.test.mjs +42 -7
  27. package/src/codemods/transforms/v0.1.0/__tests__/migrate-xds-module-specifiers.test.mjs +43 -0
  28. package/src/codemods/transforms/v0.1.0/drop-xds-prefix-imports.mjs +102 -3
  29. package/src/codemods/transforms/v0.1.0/migrate-xds-module-specifiers.mjs +72 -6
  30. package/src/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +161 -0
  31. package/src/codemods/transforms/v0.1.8/index.mjs +19 -0
  32. package/src/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +234 -0
  33. package/src/commands/agent-docs.mjs +136 -20
  34. package/src/commands/agent-docs.test.mjs +123 -10
  35. package/src/commands/build-theme.mjs +10 -71
  36. package/src/commands/build.mjs +15 -15
  37. package/src/commands/cli-postinstall.test.mjs +42 -0
  38. package/src/commands/component/index.mjs +4 -4
  39. package/src/commands/discover.mjs +7 -5
  40. package/src/commands/docs.mjs +4 -4
  41. package/src/commands/hook/index.mjs +4 -4
  42. package/src/commands/init.mjs +48 -152
  43. package/src/commands/init.next-steps.test.mjs +1 -1
  44. package/src/commands/interactive-guard.test.mjs +19 -22
  45. package/src/commands/json-contract.test.mjs +2 -2
  46. package/src/commands/layout.mjs +1 -1
  47. package/src/commands/search.mjs +4 -4
  48. package/src/commands/setup-nudge.test.mjs +108 -0
  49. package/src/commands/swizzle.mjs +12 -35
  50. package/src/commands/template.mjs +11 -31
  51. package/src/commands/upgrade.mjs +138 -32
  52. package/src/commands/upgrade.test.mjs +155 -1
  53. package/src/index.mjs +40 -6
  54. package/src/lib/cli-error.mjs +2 -2
  55. package/src/lib/component-format.mjs +2 -1
  56. package/src/lib/json-shim.mjs +1 -1
  57. package/src/lib/json.mjs +3 -3
  58. package/src/lib/term-log.mjs +48 -0
  59. package/src/types/api.d.ts +4 -9
  60. package/src/types/base.d.ts +24 -3
  61. package/src/types/build.d.ts +23 -0
  62. package/src/types/index.d.ts +1 -0
  63. package/src/types/swizzle.d.ts +4 -0
  64. package/src/types/template-api.d.ts +4 -1
  65. package/src/types/upgrade.d.ts +39 -2
  66. package/src/utils/package-manager.mjs +108 -4
  67. package/src/utils/package-manager.test.mjs +108 -1
  68. package/src/utils/path-safety.mjs +0 -18
  69. package/src/utils/update-check.mjs +5 -4
  70. package/src/utils/update-check.test.mjs +3 -3
  71. package/templates/blocks/components/Avatar/AvatarFallbackChain.tsx +4 -4
  72. package/templates/blocks/components/Avatar/AvatarGroup.tsx +2 -2
  73. package/templates/blocks/components/Avatar/AvatarInitialsFallback.tsx +1 -1
  74. package/templates/blocks/components/Avatar/AvatarShowcase.tsx +4 -4
  75. package/templates/blocks/components/Avatar/AvatarUserCard.tsx +1 -1
  76. package/templates/blocks/components/Avatar/AvatarWithImage.tsx +4 -4
  77. package/templates/blocks/components/Avatar/AvatarWithStatus.tsx +3 -3
  78. package/templates/blocks/components/AvatarGroup/AvatarGroupShowcase.tsx +2 -2
  79. package/templates/blocks/components/AvatarGroupOverflow/AvatarGroupOverflowCustomText.tsx +1 -1
  80. package/templates/blocks/components/AvatarGroupOverflow/AvatarGroupOverflowDefault.tsx +1 -1
  81. package/templates/blocks/components/AvatarGroupOverflow/AvatarGroupOverflowShowcase.tsx +2 -2
  82. package/templates/blocks/components/AvatarStatusDot/AvatarStatusDotShowcase.tsx +3 -3
  83. package/templates/blocks/components/AvatarStatusDot/AvatarStatusDotVariants.tsx +3 -3
  84. package/templates/blocks/components/Banner/BannerFloating.doc.mjs +14 -0
  85. package/templates/blocks/components/Banner/BannerFloating.tsx +16 -0
  86. package/templates/blocks/components/Button/ButtonFloating.doc.mjs +14 -0
  87. package/templates/blocks/components/Button/ButtonFloating.tsx +37 -0
  88. package/templates/blocks/components/ButtonGroup/ButtonGroupFloating.doc.mjs +14 -0
  89. package/templates/blocks/components/ButtonGroup/ButtonGroupFloating.tsx +23 -0
  90. package/templates/blocks/components/Card/CardElevations.doc.mjs +14 -0
  91. package/templates/blocks/components/Card/CardElevations.tsx +32 -0
  92. package/templates/blocks/components/Card/ClickableCardElevated.doc.mjs +14 -0
  93. package/templates/blocks/components/Card/ClickableCardElevated.tsx +21 -0
  94. package/templates/blocks/components/Card/SelectableCardElevated.doc.mjs +14 -0
  95. package/templates/blocks/components/Card/SelectableCardElevated.tsx +37 -0
  96. package/templates/blocks/components/Carousel/CarouselSnap.tsx +1 -1
  97. package/templates/blocks/components/ChatComposer/ChatComposerFlat.doc.mjs +14 -0
  98. package/templates/blocks/components/ChatComposer/ChatComposerFlat.tsx +75 -0
  99. package/templates/blocks/components/ChatMessage/ChatMessageAvatarName.tsx +2 -2
  100. package/templates/blocks/components/ChatMessage/ChatMessageMultiBubble.tsx +1 -1
  101. package/templates/blocks/components/ChatMessageBubble/ChatMessageBubbleGrouping.tsx +1 -1
  102. package/templates/blocks/components/ChatMessageBubble/ChatMessageBubbleMetadata.tsx +1 -1
  103. package/templates/blocks/components/ChatMessageList/ChatMessageListDensity.tsx +5 -9
  104. package/templates/blocks/components/ChatMessageList/ChatMessageListFullFeatured.tsx +1 -1
  105. package/templates/blocks/components/CodeBlock/CodeBlockTerminal.tsx +1 -1
  106. package/templates/blocks/components/HoverCard/HoverCardShowcase.tsx +1 -1
  107. package/templates/blocks/components/IconButton/IconButtonFloating.doc.mjs +14 -0
  108. package/templates/blocks/components/IconButton/IconButtonFloating.tsx +37 -0
  109. package/templates/blocks/components/Item/ItemWithMedia.tsx +2 -2
  110. package/templates/blocks/components/ListItem/ListItemWithMedia.tsx +2 -2
  111. package/templates/blocks/components/OverflowList/OverflowListCappedToolbar.doc.mjs +14 -0
  112. package/templates/blocks/components/OverflowList/OverflowListCappedToolbar.tsx +39 -0
  113. package/templates/blocks/components/OverflowList/OverflowListMultiRowTags.doc.mjs +14 -0
  114. package/templates/blocks/components/OverflowList/OverflowListMultiRowTags.tsx +44 -0
  115. package/templates/blocks/components/Pagination/PaginationDotsCarousel.tsx +2 -6
  116. package/templates/blocks/components/Stack/StackFillItem.tsx +2 -6
  117. package/templates/blocks/components/TabList/TabListTabsWithActions.doc.mjs +1 -1
  118. package/templates/blocks/components/TabList/TabListTabsWithActions.tsx +2 -7
  119. package/templates/blocks/components/Table/TableRowStatusTable.doc.mjs +14 -0
  120. package/templates/blocks/components/Table/TableRowStatusTable.tsx +59 -0
  121. package/templates/blocks/components/Thumbnail/ThumbnailElevated.doc.mjs +14 -0
  122. package/templates/blocks/components/Thumbnail/ThumbnailElevated.tsx +31 -0
  123. package/templates/blocks/components/TypeaheadItem/TypeaheadItemShowcase.tsx +1 -1
  124. package/templates/pages/ai-chat/page.tsx +4 -4
  125. package/templates/pages/dashboard-portfolio/page.tsx +3 -11
  126. package/templates/pages/detail-page/page.tsx +5 -12
  127. package/templates/pages/documentation-design/page.tsx +1 -1
  128. package/templates/pages/messaging-shell/page.tsx +6 -8
  129. package/templates/pages/table-grouped/page.tsx +9 -14
  130. package/templates/pages/table-page/page.tsx +7 -9
  131. package/templates/pages/table-page-heatmap-status/page.tsx +5 -13
  132. package/docs/integration-authoring.md +0 -105
  133. package/src/utils/interactive.mjs +0 -76
  134. package/src/utils/interactive.test.mjs +0 -70
@@ -37,7 +37,7 @@ export default function ChatMessageMultiBubble() {
37
37
  </ChatMessage>
38
38
  <ChatMessage
39
39
  sender="assistant"
40
- avatar={<Avatar name="Agent" size="small" />}>
40
+ avatar={<Avatar name="Agent" size="md" />}>
41
41
  <ChatMessageBubble
42
42
  group="first"
43
43
  name={
@@ -17,7 +17,7 @@ export default function ChatMessageBubbleGrouping() {
17
17
  <ChatMessageList style={{maxWidth: 500}}>
18
18
  <ChatMessage
19
19
  sender="assistant"
20
- avatar={<Avatar name="Agent" size="small" />}>
20
+ avatar={<Avatar name="Agent" size="md" />}>
21
21
  <ChatMessageBubble
22
22
  group="first"
23
23
  name={
@@ -20,7 +20,7 @@ export default function ChatMessageBubbleMetadata() {
20
20
  <ChatMessageList style={{maxWidth: 500}}>
21
21
  <ChatMessage
22
22
  sender="assistant"
23
- avatar={<Avatar name="Agent" size="small" />}>
23
+ avatar={<Avatar name="Agent" size="md" />}>
24
24
  <ChatMessageBubble
25
25
  name={
26
26
  <Text type="supporting" weight="semibold" color="secondary">
@@ -16,9 +16,9 @@ import {Fragment} from 'react';
16
16
  const DENSITIES = ['compact', 'balanced', 'spacious'] as const;
17
17
 
18
18
  const AVATAR_SIZE = {
19
- compact: 'xsmall' as const,
20
- balanced: 'small' as const,
21
- spacious: 'small' as const,
19
+ compact: 'sm' as const,
20
+ balanced: 'md' as const,
21
+ spacious: 'md' as const,
22
22
  };
23
23
 
24
24
  export default function ChatMessageListDensity() {
@@ -34,15 +34,11 @@ export default function ChatMessageListDensity() {
34
34
  <VStack style={{flex: 1, minHeight: 0}}>
35
35
  <ChatMessageList density={density}>
36
36
  <ChatMessage sender="user">
37
- <ChatMessageBubble>
38
- How does density work?
39
- </ChatMessageBubble>
37
+ <ChatMessageBubble>How does density work?</ChatMessageBubble>
40
38
  </ChatMessage>
41
39
  <ChatMessage
42
40
  sender="assistant"
43
- avatar={
44
- <Avatar name="Agent" size={AVATAR_SIZE[density]} />
45
- }>
41
+ avatar={<Avatar name="Agent" size={AVATAR_SIZE[density]} />}>
46
42
  <ChatMessageBubble>
47
43
  Density provides default spacing at every level — message
48
44
  gap, bubble padding, and gap between child elements. Use gap
@@ -42,7 +42,7 @@ export default function ChatMessageListFullFeatured() {
42
42
 
43
43
  <ChatMessage
44
44
  sender="assistant"
45
- avatar={<Avatar name="Agent" size="small" />}>
45
+ avatar={<Avatar name="Agent" size="md" />}>
46
46
  <ChatMessageBubble group="first">
47
47
  <Markdown density="compact">
48
48
  {`Sure! Here's the key pattern from **useReducer.ts**:`}
@@ -7,7 +7,7 @@ import {githubDark} from '@astryxdesign/core/theme/syntax';
7
7
  import {CodeBlock} from '@astryxdesign/core/CodeBlock';
8
8
 
9
9
  const commands = `$ astryx init --features agents
10
- ✓ AI agent docs installed → .claude/CLAUDE.md
10
+ ✓ AI agent docs installed → AGENTS.md
11
11
  $ pnpm astryx component CodeBlock --dense`;
12
12
 
13
13
  export default function CodeBlockTerminal() {
@@ -15,7 +15,7 @@ export default function HoverCardShowcase() {
15
15
  content={
16
16
  <Stack direction="vertical" gap={2} style={{width: 240}}>
17
17
  <Stack direction="horizontal" gap={2} vAlign="center">
18
- <Avatar name="Jane Doe" size="medium" />
18
+ <Avatar name="Jane Doe" size="lg" />
19
19
  <Stack direction="vertical" gap={0}>
20
20
  <Heading level={5}>Jane Doe</Heading>
21
21
  <Text type="supporting" color="secondary">
@@ -0,0 +1,14 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../../../../core/src/docs-types').TemplateDoc} */
4
+ export const doc = {
5
+ type: 'block',
6
+ exampleFor: 'IconButton',
7
+ name: 'IconButton — Floating',
8
+ displayName: 'IconButton — Floating',
9
+ description:
10
+ 'A floating action button (FAB) — the most common floating-button shape is icon-only. Raised here with `elevation="high"`.',
11
+ isReady: true,
12
+ aspectRatio: 4 / 3,
13
+ componentsUsed: ['IconButton', 'Icon', 'Layout', 'Text'],
14
+ };
@@ -0,0 +1,37 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ import {IconButton} from '@astryxdesign/core/IconButton';
6
+ import {Icon} from '@astryxdesign/core/Icon';
7
+ import {Stack} from '@astryxdesign/core/Layout';
8
+ import {Text} from '@astryxdesign/core/Text';
9
+ import {PlusIcon} from '@heroicons/react/24/outline';
10
+
11
+ const VARIANTS = [
12
+ {variant: 'primary' as const, label: 'Primary'},
13
+ {variant: 'secondary' as const, label: 'Secondary'},
14
+ {variant: 'ghost' as const, label: 'Ghost'},
15
+ {variant: 'destructive' as const, label: 'Destructive'},
16
+ ];
17
+
18
+ export default function IconButtonFloating() {
19
+ return (
20
+ <Stack direction="vertical" gap={4}>
21
+ <Text type="supporting" color="secondary">
22
+ FABs are usually icon-only — raise one with `elevation="high"`
23
+ </Text>
24
+ <Stack direction="horizontal" gap={3} vAlign="center">
25
+ {VARIANTS.map(({variant, label}) => (
26
+ <IconButton
27
+ key={variant}
28
+ label={label}
29
+ variant={variant}
30
+ icon={<Icon icon={PlusIcon} />}
31
+ elevation="high"
32
+ />
33
+ ))}
34
+ </Stack>
35
+ </Stack>
36
+ );
37
+ }
@@ -13,14 +13,14 @@ export default function ItemWithMedia() {
13
13
  return (
14
14
  <Stack gap={0}>
15
15
  <Item
16
- startContent={<Avatar name="Ada Lovelace" size="xsmall" />}
16
+ startContent={<Avatar name="Ada Lovelace" size="sm" />}
17
17
  label="Ada Lovelace"
18
18
  description="Design systems engineer"
19
19
  endContent={<Badge label="Owner" variant="purple" />}
20
20
  onClick={() => {}}
21
21
  />
22
22
  <Item
23
- startContent={<Avatar name="Grace Hopper" size="xsmall" />}
23
+ startContent={<Avatar name="Grace Hopper" size="sm" />}
24
24
  label="Grace Hopper"
25
25
  description="Compiler platform"
26
26
  endContent={<Text color="secondary">Online</Text>}
@@ -13,14 +13,14 @@ export default function ListItemWithMedia() {
13
13
  <ListItem
14
14
  label="Ada Lovelace"
15
15
  description="Design systems engineer"
16
- startContent={<Avatar name="Ada Lovelace" size="xsmall" />}
16
+ startContent={<Avatar name="Ada Lovelace" size="sm" />}
17
17
  endContent={<Badge label="Owner" variant="purple" />}
18
18
  onClick={() => {}}
19
19
  />
20
20
  <ListItem
21
21
  label="Grace Hopper"
22
22
  description="Platform infrastructure"
23
- startContent={<Avatar name="Grace Hopper" size="xsmall" />}
23
+ startContent={<Avatar name="Grace Hopper" size="sm" />}
24
24
  endContent={<Badge label="On call" variant="blue" />}
25
25
  onClick={() => {}}
26
26
  />
@@ -0,0 +1,14 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../../../../core/src/docs-types').TemplateDoc} */
4
+ export const doc = {
5
+ type: 'block',
6
+ exampleFor: 'OverflowList',
7
+ name: 'OverflowList — Capped Toolbar',
8
+ displayName: 'OverflowList — Capped Toolbar',
9
+ description:
10
+ 'maxVisibleItems caps the row at three actions even when more would fit; the rest move to a dropdown',
11
+ isReady: true,
12
+ aspectRatio: 4 / 3,
13
+ componentsUsed: ['OverflowList', 'Button', 'DropdownMenu', 'Card', 'Center'],
14
+ };
@@ -0,0 +1,39 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ import {OverflowList} from '@astryxdesign/core/OverflowList';
6
+ import {Button} from '@astryxdesign/core/Button';
7
+ import {DropdownMenu} from '@astryxdesign/core/DropdownMenu';
8
+ import {Card} from '@astryxdesign/core/Card';
9
+ import {Center} from '@astryxdesign/core/Center';
10
+
11
+ const actions = ['Save', 'Edit', 'Duplicate', 'Share', 'Archive', 'Delete'];
12
+
13
+ export default function OverflowListCappedToolbar() {
14
+ return (
15
+ <Center width={420}>
16
+ <Card padding={2}>
17
+ <OverflowList
18
+ gap={2}
19
+ maxVisibleItems={3}
20
+ overflowRenderer={overflowItems => (
21
+ <DropdownMenu
22
+ button={{
23
+ label: `+${overflowItems.length}`,
24
+ variant: 'ghost',
25
+ size: 'sm',
26
+ }}
27
+ items={overflowItems.map(({index}) => ({
28
+ label: actions[index],
29
+ }))}
30
+ />
31
+ )}>
32
+ {actions.map(action => (
33
+ <Button key={action} label={action} size="sm" />
34
+ ))}
35
+ </OverflowList>
36
+ </Card>
37
+ </Center>
38
+ );
39
+ }
@@ -0,0 +1,14 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../../../../core/src/docs-types').TemplateDoc} */
4
+ export const doc = {
5
+ type: 'block',
6
+ exampleFor: 'OverflowList',
7
+ name: 'OverflowList — Multi-row Tags',
8
+ displayName: 'OverflowList — Multi-row Tags',
9
+ description:
10
+ 'Tags wrap onto up to two rows with maxRows, then collapse the rest into a count badge',
11
+ isReady: true,
12
+ aspectRatio: 4 / 3,
13
+ componentsUsed: ['OverflowList', 'Badge', 'Card'],
14
+ };
@@ -0,0 +1,44 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ import {OverflowList} from '@astryxdesign/core/OverflowList';
6
+ import {Badge} from '@astryxdesign/core/Badge';
7
+ import {Card} from '@astryxdesign/core/Card';
8
+
9
+ const tags = [
10
+ 'React',
11
+ 'TypeScript',
12
+ 'StyleX',
13
+ 'Storybook',
14
+ 'Vitest',
15
+ 'Playwright',
16
+ 'ESLint',
17
+ 'Prettier',
18
+ 'Vite',
19
+ 'pnpm',
20
+ ];
21
+
22
+ export default function OverflowListMultiRowTags() {
23
+ return (
24
+ <Card
25
+ padding={2}
26
+ style={{
27
+ resize: 'horizontal',
28
+ overflow: 'hidden',
29
+ minWidth: 120,
30
+ width: 260,
31
+ }}>
32
+ <OverflowList
33
+ gap={1}
34
+ maxRows={2}
35
+ overflowRenderer={overflowItems => (
36
+ <Badge variant="neutral" label={`+${overflowItems.length}`} />
37
+ )}>
38
+ {tags.map(tag => (
39
+ <Badge key={tag} variant="info" label={tag} />
40
+ ))}
41
+ </OverflowList>
42
+ </Card>
43
+ );
44
+ }
@@ -62,12 +62,8 @@ export default function PaginationDotsCarousel() {
62
62
  <Stack direction="vertical" gap={3}>
63
63
  <Stars count={review.stars} />
64
64
  <Text type="body">{review.quote}</Text>
65
- <Stack
66
- direction="horizontal"
67
- gap={3}
68
- vAlign="center"
69
- hAlign="start">
70
- <Avatar name={review.name} size="small" />
65
+ <Stack direction="horizontal" gap={3} vAlign="center" hAlign="start">
66
+ <Avatar name={review.name} size="md" />
71
67
  <Stack direction="vertical" gap={0}>
72
68
  <Text type="supporting" weight="bold">
73
69
  {review.name}
@@ -17,13 +17,9 @@ export default function StackFillItem() {
17
17
  return (
18
18
  <Stack direction="vertical" gap={3} width="100%" style={{maxWidth: 300}}>
19
19
  {USERS.map(user => (
20
- <Stack
21
- key={user.name}
22
- direction="horizontal"
23
- gap={3}
24
- vAlign="center">
20
+ <Stack key={user.name} direction="horizontal" gap={3} vAlign="center">
25
21
  <StackItem size="static">
26
- <Avatar name={user.name} size="small" />
22
+ <Avatar name={user.name} size="md" />
27
23
  </StackItem>
28
24
  <StackItem size="fill">
29
25
  <Stack direction="vertical" gap={0}>
@@ -7,7 +7,7 @@ export const doc = {
7
7
  name: 'TabList — With Actions',
8
8
  displayName: 'TabList — With Actions',
9
9
  description:
10
- 'Page header pattern with tabs on the left and action buttons pushed to the right. When hasDivider is true, pair with a smaller button size (sm) so actions don\'t overpower the tab row.',
10
+ 'Page header pattern with tabs on the left and action buttons pushed to the right. When hasDivider is true, match the Button size to the TabList size so the tabs and actions align to a shared baseline above the divider.',
11
11
  isReady: true,
12
12
  aspectRatio: 4 / 3,
13
13
  componentsUsed: ['TabList', 'Tab', 'Button'],
@@ -55,16 +55,11 @@ export default function TabListTabsWithActions() {
55
55
  <Button
56
56
  label="Filter"
57
57
  variant="ghost"
58
- size="sm"
58
+ size="lg"
59
59
  icon={FilterIcon}
60
60
  isIconOnly
61
61
  />
62
- <Button
63
- label="New item"
64
- variant="primary"
65
- size="sm"
66
- icon={PlusIcon}
67
- />
62
+ <Button label="New item" variant="primary" size="lg" icon={PlusIcon} />
68
63
  </div>
69
64
  </TabList>
70
65
  );
@@ -0,0 +1,14 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../../../../core/src/docs-types').TemplateDoc} */
4
+ export const doc = {
5
+ type: 'block',
6
+ exampleFor: 'useTableRowStatus',
7
+ name: 'useTableRowStatus - Status Dots',
8
+ displayName: 'useTableRowStatus - Status Dots',
9
+ description:
10
+ 'A job table using useTableRowStatus to render a colored status dot (or icon) per row (failed / running / queued). Rows with no status show no dot.',
11
+ isReady: true,
12
+ aspectRatio: 16 / 9,
13
+ componentsUsed: ['Table'],
14
+ };
@@ -0,0 +1,59 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ import {
6
+ Table,
7
+ useTableRowStatus,
8
+ proportional,
9
+ pixel,
10
+ } from '@astryxdesign/core/Table';
11
+ import type {TableColumn, TableRowStatus} from '@astryxdesign/core/Table';
12
+
13
+ interface Job extends Record<string, unknown> {
14
+ id: string;
15
+ name: string;
16
+ owner: string;
17
+ state: 'failed' | 'running' | 'queued' | 'succeeded';
18
+ }
19
+
20
+ const jobs: Job[] = [
21
+ {id: 'j1', name: 'build-core', owner: 'Ava', state: 'failed'},
22
+ {id: 'j2', name: 'lint', owner: 'Liam', state: 'running'},
23
+ {id: 'j3', name: 'unit-tests', owner: 'Zoe', state: 'succeeded'},
24
+ {id: 'j4', name: 'docsite-deploy', owner: 'Max', state: 'queued'},
25
+ {id: 'j5', name: 'smoke-test', owner: 'Mia', state: 'succeeded'},
26
+ ];
27
+
28
+ const columns: TableColumn<Job>[] = [
29
+ {key: 'name', header: 'Job', width: proportional(2)},
30
+ {key: 'owner', header: 'Owner', width: pixel(120)},
31
+ {key: 'state', header: 'State', width: pixel(120)},
32
+ ];
33
+
34
+ function jobStatus(job: Job): TableRowStatus | null {
35
+ switch (job.state) {
36
+ case 'failed':
37
+ return {color: 'error', icon: 'error', label: 'Failed'};
38
+ case 'running':
39
+ return {color: 'warning', icon: 'warning', label: 'Running'};
40
+ case 'queued':
41
+ return {color: 'gray', label: 'Queued'};
42
+ default:
43
+ return null; // succeeded: no dot
44
+ }
45
+ }
46
+
47
+ export default function TableRowStatusTable() {
48
+ const rowStatus = useTableRowStatus<Job>({getStatus: jobStatus});
49
+
50
+ return (
51
+ <Table
52
+ data={jobs}
53
+ columns={columns}
54
+ idKey="id"
55
+ hasHover
56
+ plugins={{rowStatus}}
57
+ />
58
+ );
59
+ }
@@ -0,0 +1,14 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../../../../core/src/docs-types').TemplateDoc} */
4
+ export const doc = {
5
+ type: 'block',
6
+ exampleFor: 'Thumbnail',
7
+ name: 'Thumbnail — Elevated',
8
+ displayName: 'Thumbnail — Elevated',
9
+ description:
10
+ 'Image tiles raised at rest with `elevation`. The default keeps the existing hover-only shadow; a set level lifts the tile off the page.',
11
+ isReady: true,
12
+ aspectRatio: 16 / 9,
13
+ componentsUsed: ['Thumbnail', 'Layout', 'Text'],
14
+ };
@@ -0,0 +1,31 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ import {Thumbnail} from '@astryxdesign/core/Thumbnail';
6
+ import {Stack} from '@astryxdesign/core/Layout';
7
+ import {Text} from '@astryxdesign/core/Text';
8
+
9
+ // Demo imagery is inlined as same-origin data URIs so the example is
10
+ // self-contained. Thumbnail's remove-button overlay uses useImageMode, which
11
+ // FETCHES the image to sample pixels (APCA) for contrast — a cross-origin CDN
12
+ // URL without CORS headers cannot be sampled, so contrast detection fails
13
+ // silently in hosted previews.
14
+ const NIGHT_FOREST =
15
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAwFBMVEX18+H08uDy8d/y8N/v7t/m5NXl49Tk4tPc3NDX1cnW1cnW1cjW1MjV1MjV1MfR0cXIyLzEw7m8vLC3t68wM0QvM0MvM0IvMkIuMkEtMEErLz8iJjkhJTggJTcgJDcfJDYfIzYeIjUcITMbHzIWHiwYGzIXGjEWGjAWGTAVGS8VGC8UGC4UGC0UFy4TFy0TFywTFi0SFiwRFSsQFSkNFR4QFCoPFCkPFCgPEykOEygOEigNEicNEScMESYIDw8ECgr+gzZIAAABqElEQVR42uWQ61aCQBRGD5GylNBMKS9FZgNdNE0cyUvB+79VM8MoF9Fgplau2j/8nO8c9hqAD0ngDwjeJYH1lrfBWoCtYDboNu/Zv7qQYNap1bpCN1gxFh1dNe5WAsCScWqoWttbChAKvHZZ0W6XQoIFpW8ooFmLCG2Rl1BgaZAU5Ac8yg0RlC9nngCRQDFuhQRzinWmkCuYk3lxQoFrlskVqlcTMcEFvYIKoFbNfmEFuIypWaGGkt66tqZuEbjAHZl6SQVF1WqNvpDAHVktXTvR9JbgDZii1+tZI7cYMJXkCASvksB4L5VxHmAsibzgRRIYbjgfCgFDSeBZkh8W1HMIniSBR0mOQPCQA3RgBk4M5DhNZwdEcbKgLXy5iDiZg5gApRYbqTql2FZgMxAKeEWSNUFYx3s2SfU28HPWItrpySSwE2cEdqrYtxgmxgHGScFmHrAGk8SxczIxZnNC1McFOGshShyb4yxB9sI3CXDGnH0MLsD7F5LvvptEgH12Zg1Pn2WuHsjvrwt8308t+nwxT38sgiAE8/RTeagH+vx/F8SeF0Ja8Ak14ia/LgmpZQAAAABJRU5ErkJggg==';
16
+ const GOLDEN_SUNSET =
17
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAkFBMVEX/+uv/7sj6tFr3sVn1r1nzrVjxq1jvqVftp1frpVbpo1bnoVXln1XjnVThm1TfmVPdl1PblVLZk1LXkVLVj1HTjVHRi1DPiVDNh0/LhU/Jg07HgU7Ff03DfU3Be0y/eUy9d0u7dUu5c0u2cEq0bkqybEmwakmuaEisZkiqZEeoYkemYEakXkaiXEVgLjQ8HCjaJlMkAAABI0lEQVR42u3Mx3qDMBSE0Z/03nsvdhxjcnn/twsYjISR5MUkO5+V9N2ZYUPEpogtEdsidkTsitgTsS/iQMShiCMRxyJORJyKOBNxLuJCxKWIKxHXIm5E3Iq4E3Ev4kHEo4gnEc8iXkS8inhLymrJBO8J2UIiw0dc5sRDfEbVRWr1o/pbMMWox9yz6zcLIzMbBTD2VaHu7fr1gjXGA3w5baj5+H0w6x09TDpdaP7rDZhn0sd3y89Y9fcHbPnoYdroZ2w6dQNmg6OHfG4QyrsBC8gdZpVQxtqF4M1mjepFURThTLNgMYsePxaX2WqY6D8GSm2grK2slbGBciHZ9hOE2smNpTuxenhieCdeH06E7qTqvYnImWTbbUSPlKL1wHrgTwZ+AWq+3H5MpRkwAAAAAElFTkSuQmCC';
18
+
19
+ export default function ThumbnailElevated() {
20
+ return (
21
+ <Stack direction="vertical" gap={3}>
22
+ <Text type="supporting" color="secondary">
23
+ Raised tiles — `elevation` lifts an image off the page at rest
24
+ </Text>
25
+ <Stack direction="horizontal" gap={3} vAlign="center">
26
+ <Thumbnail src={NIGHT_FOREST} alt="Forest at night" elevation="low" />
27
+ <Thumbnail src={GOLDEN_SUNSET} alt="Golden sunset" elevation="high" />
28
+ </Stack>
29
+ </Stack>
30
+ );
31
+ }
@@ -40,7 +40,7 @@ export default function TypeaheadItemShowcase() {
40
40
  renderItem={(item: PersonItem) => (
41
41
  <TypeaheadItem
42
42
  item={item}
43
- icon={<Avatar name={item.label} size="small" />}
43
+ icon={<Avatar name={item.label} size="md" />}
44
44
  description={item.auxiliaryData.role}
45
45
  />
46
46
  )}
@@ -390,7 +390,7 @@ export default function AIChatConversationTemplate() {
390
390
  {/* Assistant message: tool calls, markdown, code block */}
391
391
  <ChatMessage
392
392
  sender="assistant"
393
- avatar={<Avatar name="Agent" size="small" />}>
393
+ avatar={<Avatar name="Agent" size="md" />}>
394
394
  <ChatMessageBubble variant="ghost">
395
395
  Looking into the auth files now. Let me read through the
396
396
  code and trace the token refresh flow.
@@ -510,7 +510,7 @@ The fix is to catch \`TokenExpiredError\` specifically and attempt a refresh bef
510
510
  {/* Assistant message: test results table + code block */}
511
511
  <ChatMessage
512
512
  sender="assistant"
513
- avatar={<Avatar name="Agent" size="small" />}>
513
+ avatar={<Avatar name="Agent" size="md" />}>
514
514
  <ChatToolCalls
515
515
  defaultIsExpanded
516
516
  calls={[
@@ -608,7 +608,7 @@ The fix is to catch \`TokenExpiredError\` specifically and attempt a refresh bef
608
608
  {/* Assistant message: artifact card */}
609
609
  <ChatMessage
610
610
  sender="assistant"
611
- avatar={<Avatar name="Agent" size="small" />}>
611
+ avatar={<Avatar name="Agent" size="md" />}>
612
612
  <ChatMessageBubble variant="ghost">
613
613
  <Markdown density="compact">
614
614
  {`I've drafted a design doc covering the problem, the fix, and the test matrix — pulling straight from the changes we just made.\n\nOpen the document below to review it. Want me to expand any section?`}
@@ -647,7 +647,7 @@ The fix is to catch \`TokenExpiredError\` specifically and attempt a refresh bef
647
647
  {/* Assistant message: in-progress tool call */}
648
648
  <ChatMessage
649
649
  sender="assistant"
650
- avatar={<Avatar name="Agent" size="small" />}>
650
+ avatar={<Avatar name="Agent" size="md" />}>
651
651
  <ChatMessageBubble variant="ghost">
652
652
  <Markdown density="compact">
653
653
  {`On it — adding a **Rollout & Monitoring** section with a staged flag ramp and the alert thresholds. Updating the document now.`}
@@ -4,12 +4,7 @@
4
4
 
5
5
  import {useState} from 'react';
6
6
 
7
- import {
8
- VStack,
9
- HStack,
10
- Layout,
11
- LayoutContent,
12
- } from '@astryxdesign/core/Layout';
7
+ import {VStack, HStack, Layout, LayoutContent} from '@astryxdesign/core/Layout';
13
8
  import {Text, Heading} from '@astryxdesign/core/Text';
14
9
  import {Card} from '@astryxdesign/core/Card';
15
10
  import {Grid, GridSpan} from '@astryxdesign/core/Grid';
@@ -642,7 +637,7 @@ function AssetRow({
642
637
  label={<Text weight="bold">{ticker}</Text>}
643
638
  description={name}
644
639
  href="#"
645
- startContent={<Avatar name={ticker} size="small" />}
640
+ startContent={<Avatar name={ticker} size="md" />}
646
641
  endContent={
647
642
  <VStack gap={0} hAlign="end">
648
643
  <Text type="body">{value}</Text>
@@ -693,10 +688,7 @@ export default function DashboardPortfolioTemplate() {
693
688
  {/* KPI metric cards */}
694
689
  <Grid columns={{minWidth: 280, repeat: 'fit'}} gap={4}>
695
690
  {Array.from({length: Math.ceil(metrics.length / 2)}, (_, i) => (
696
- <Grid
697
- key={i}
698
- columns={{minWidth: 280, repeat: 'fit'}}
699
- gap={4}>
691
+ <Grid key={i} columns={{minWidth: 280, repeat: 'fit'}} gap={4}>
700
692
  {metrics.slice(i * 2, i * 2 + 2).map(m => (
701
693
  <MetricCard key={m.label} {...m} />
702
694
  ))}
@@ -199,7 +199,7 @@ function PageHeader({
199
199
  </Text>
200
200
  <HStack gap={1} vAlign="center">
201
201
  <Bullet />
202
- <Avatar name="Jane Doe" size="xsmall" />
202
+ <Avatar name="Jane Doe" size="sm" />
203
203
  <Text type="body" maxLines={1}>
204
204
  Jane Doe
205
205
  </Text>
@@ -444,7 +444,7 @@ function TimelineSection() {
444
444
  {ACTIVITY.map((item, i) => (
445
445
  <VStack key={i} gap={2}>
446
446
  <HStack gap={3} vAlign="start">
447
- <Avatar name={item.user} size="small" />
447
+ <Avatar name={item.user} size="md" />
448
448
  <StackItem size="fill">
449
449
  <VStack gap={2}>
450
450
  <Card variant="muted" padding={3}>
@@ -478,11 +478,7 @@ function TimelineSection() {
478
478
  size="xsm"
479
479
  color="secondary"
480
480
  />
481
- <Icon
482
- icon={HeartIcon}
483
- size="xsm"
484
- color="secondary"
485
- />
481
+ <Icon icon={HeartIcon} size="xsm" color="secondary" />
486
482
  <Text type="supporting" color="secondary">
487
483
  {item.reactions}
488
484
  </Text>
@@ -533,16 +529,13 @@ function PanelContent() {
533
529
  321 Smith Road, CA 38238
534
530
  </MetadataListItem>
535
531
  <MetadataListItem label="Phone">234-</MetadataListItem>
536
- <MetadataListItem label="Email">
537
- janedoe@email.com
538
- </MetadataListItem>
532
+ <MetadataListItem label="Email">janedoe@email.com</MetadataListItem>
539
533
  <MetadataListItem label="Billing Address">
540
534
  Same as shipping address
541
535
  </MetadataListItem>
542
536
  </MetadataList>
543
537
  </Collapsible>
544
- <Collapsible
545
- trigger={<Heading level={4}>Fraud Analysis</Heading>}>
538
+ <Collapsible trigger={<Heading level={4}>Fraud Analysis</Heading>}>
546
539
  <VStack gap={1}>
547
540
  <ProgressBar
548
541
  label="Risk level"
@@ -541,7 +541,7 @@ function ComponentDetailView({activeNav}: {activeNav: string}) {
541
541
  endContent={<Badge label="New" variant="info" />}
542
542
  />
543
543
  ),
544
- avatar: <Avatar name="Alice" size="medium" />,
544
+ avatar: <Avatar name="Alice" size="lg" />,
545
545
  badge: <Badge label="Success" variant="success" />,
546
546
  card: (
547
547
  <Card>