@astryxdesign/cli 0.1.0-canary.7847c5f → 0.1.0-canary.797f761
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/docs/getting-started.doc.mjs +11 -11
- package/docs/styling.doc.mjs +2 -1
- package/package.json +7 -7
- package/src/commands/init.mjs +1 -1
- package/src/utils/package-manager.mjs +1 -1
- package/templates/pages/documentation/page.tsx +52 -39
- package/templates/pages/documentation-design/page.tsx +55 -80
- package/templates/pages/documentation-technical/page.tsx +54 -96
- package/templates/pages/ide/page.tsx +236 -167
|
@@ -88,7 +88,7 @@ import {VStack} from '@astryxdesign/core/Layout';
|
|
|
88
88
|
export default function Page() {
|
|
89
89
|
return (
|
|
90
90
|
<VStack gap={2}>
|
|
91
|
-
<Button label="Hello
|
|
91
|
+
<Button label="Hello XDS" onClick={() => alert('Hi!')} />
|
|
92
92
|
</VStack>
|
|
93
93
|
);
|
|
94
94
|
}`,
|
|
@@ -96,11 +96,11 @@ export default function Page() {
|
|
|
96
96
|
],
|
|
97
97
|
},
|
|
98
98
|
{
|
|
99
|
-
title: 'Customize with
|
|
99
|
+
title: 'Customize with xstyle',
|
|
100
100
|
content: [
|
|
101
101
|
{
|
|
102
102
|
type: 'prose',
|
|
103
|
-
text: '
|
|
103
|
+
text: 'Every component accepts an `xstyle` prop for StyleX style overrides created via `stylex.create()`.',
|
|
104
104
|
},
|
|
105
105
|
{
|
|
106
106
|
type: 'code',
|
|
@@ -127,19 +127,19 @@ const overrides = stylex.create({
|
|
|
127
127
|
type: 'table',
|
|
128
128
|
headers: ['Example', 'Stack', 'Path'],
|
|
129
129
|
rows: [
|
|
130
|
-
['Next.js', 'Next.js + theme CSS', '
|
|
131
|
-
['Next.js + StyleX', 'Next.js + StyleX for custom styles', '
|
|
132
|
-
['Next.js + Tailwind', 'Next.js + Tailwind bridge', '
|
|
133
|
-
['Next.js Source', 'Next.js importing from source', '
|
|
134
|
-
['Vite', 'Vite', '
|
|
130
|
+
['Next.js', 'Next.js + theme CSS', 'apps/example-nextjs'],
|
|
131
|
+
['Next.js + StyleX', 'Next.js + StyleX for custom styles', 'apps/example-nextjs-stylex'],
|
|
132
|
+
['Next.js + Tailwind', 'Next.js + Tailwind bridge', 'apps/example-nextjs-tailwind'],
|
|
133
|
+
['Next.js Source', 'Next.js importing from source', 'apps/example-nextjs-source'],
|
|
134
|
+
['Vite', 'Vite', 'apps/example-vite'],
|
|
135
135
|
],
|
|
136
136
|
},
|
|
137
137
|
{
|
|
138
138
|
type: 'code',
|
|
139
139
|
lang: 'bash',
|
|
140
140
|
label: 'Clone and run an example',
|
|
141
|
-
code: `git clone https://github.com/
|
|
142
|
-
cd
|
|
141
|
+
code: `git clone https://github.com/facebookexperimental/xds.git
|
|
142
|
+
cd xds/apps/example-nextjs
|
|
143
143
|
pnpm install
|
|
144
144
|
pnpm dev`,
|
|
145
145
|
},
|
|
@@ -157,7 +157,7 @@ pnpm dev`,
|
|
|
157
157
|
lang: 'json',
|
|
158
158
|
label: 'package.json',
|
|
159
159
|
code: `"scripts": {
|
|
160
|
-
"
|
|
160
|
+
"xds": "node node_modules/@astryxdesign/cli/bin/astryx.mjs"
|
|
161
161
|
}`,
|
|
162
162
|
},
|
|
163
163
|
{
|
package/docs/styling.doc.mjs
CHANGED
|
@@ -22,8 +22,9 @@ export const docs = {
|
|
|
22
22
|
type: 'table',
|
|
23
23
|
headers: ['Approach', 'Use for', 'Example'],
|
|
24
24
|
rows: [
|
|
25
|
-
['
|
|
25
|
+
['xstyle prop', 'Overriding a specific component', 'xstyle={styles.override}'],
|
|
26
26
|
['Tailwind utilities', 'Layout, wrappers, and utility styling', 'className="flex gap-3 p-4"'],
|
|
27
|
+
['stylex.create', 'Reusable styles, pseudo-classes, typed tokens', 'stylex.create({ card: { ... } })'],
|
|
27
28
|
['className', 'Integrating with external CSS or Tailwind on components', 'className="my-card shadow-lg"'],
|
|
28
29
|
['Styling-library token aliases', 'Keeping Panda, Chakra, MUI, Emotion, styled-components, UnoCSS, CSS Modules, or Sass in sync with the system', "colors.surface = 'var(--color-background-surface)'"],
|
|
29
30
|
],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/cli",
|
|
3
|
-
"version": "0.1.0-canary.
|
|
3
|
+
"version": "0.1.0-canary.797f761",
|
|
4
4
|
"displayName": "CLI",
|
|
5
5
|
"description": "Scaffold projects, browse templates, generate themes, and get agent-ready docs from the command line.",
|
|
6
6
|
"author": "Meta Open Source",
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
"jscodeshift": "^17.3.0"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"@astryxdesign/core": "0.1.0-canary.
|
|
58
|
-
"@astryxdesign/lab": "0.1.0-canary.
|
|
59
|
-
"@astryxdesign/theme-neutral": "0.1.0-canary.
|
|
57
|
+
"@astryxdesign/core": "0.1.0-canary.797f761",
|
|
58
|
+
"@astryxdesign/lab": "0.1.0-canary.797f761",
|
|
59
|
+
"@astryxdesign/theme-neutral": "0.1.0-canary.797f761"
|
|
60
60
|
},
|
|
61
61
|
"peerDependenciesMeta": {
|
|
62
62
|
"@astryxdesign/core": {
|
|
@@ -70,9 +70,9 @@
|
|
|
70
70
|
}
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
|
-
"@astryxdesign/core": "0.1.0-canary.
|
|
74
|
-
"@astryxdesign/lab": "0.1.0-canary.
|
|
75
|
-
"@astryxdesign/theme-neutral": "0.1.0-canary.
|
|
73
|
+
"@astryxdesign/core": "0.1.0-canary.797f761",
|
|
74
|
+
"@astryxdesign/lab": "0.1.0-canary.797f761",
|
|
75
|
+
"@astryxdesign/theme-neutral": "0.1.0-canary.797f761"
|
|
76
76
|
},
|
|
77
77
|
"scripts": {
|
|
78
78
|
"astryx": "node bin/astryx.mjs",
|
package/src/commands/init.mjs
CHANGED
|
@@ -248,7 +248,7 @@ export function registerInit(program) {
|
|
|
248
248
|
humanLog(' 2. Optionally add a theme:');
|
|
249
249
|
humanLog(" import { neutralTheme } from '@astryxdesign/theme-neutral'");
|
|
250
250
|
humanLog(' <Theme theme={neutralTheme}>...</Theme>');
|
|
251
|
-
humanLog(` 3. ${run}
|
|
251
|
+
humanLog(` 3. ${run} xds --help for all commands`);
|
|
252
252
|
humanLog('');
|
|
253
253
|
});
|
|
254
254
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @file Detect the project's package manager from lockfiles.
|
|
5
5
|
*
|
|
6
6
|
* Returns the correct command prefix for running package binaries
|
|
7
|
-
* (e.g. 'npx
|
|
7
|
+
* (e.g. 'npx xds', 'yarn xds', 'pnpm exec xds').
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import * as fs from 'node:fs';
|
|
@@ -3,23 +3,24 @@
|
|
|
3
3
|
'use client';
|
|
4
4
|
|
|
5
5
|
import * as stylex from '@stylexjs/stylex';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
SideNav,
|
|
8
|
+
SideNavHeading,
|
|
9
|
+
SideNavItem,
|
|
10
|
+
SideNavSection,
|
|
11
|
+
} from '@astryxdesign/core/SideNav';
|
|
12
|
+
import {Text} from '@astryxdesign/core/Text';
|
|
7
13
|
import {Button} from '@astryxdesign/core/Button';
|
|
8
14
|
import {Card} from '@astryxdesign/core/Card';
|
|
9
|
-
import {ClickableCard} from '@astryxdesign/core/ClickableCard';
|
|
10
15
|
import {HStack, VStack, StackItem} from '@astryxdesign/core/Stack';
|
|
11
|
-
import {Layout, LayoutContent} from '@astryxdesign/core/Layout';
|
|
16
|
+
import {Layout, LayoutContent, LayoutPanel} from '@astryxdesign/core/Layout';
|
|
12
17
|
import {Grid} from '@astryxdesign/core/Grid';
|
|
13
18
|
import {radiusVars} from '@astryxdesign/core/theme/tokens.stylex';
|
|
14
19
|
|
|
15
20
|
const styles = stylex.create({
|
|
16
21
|
previewCard: {
|
|
17
|
-
borderRadius: radiusVars['--radius-
|
|
18
|
-
|
|
19
|
-
// Negative margin offsets each card's 8px padding so the grid content stays
|
|
20
|
-
// visually aligned while giving every card a padded hover/click target.
|
|
21
|
-
cardGrid: {
|
|
22
|
-
margin: -8,
|
|
22
|
+
borderRadius: radiusVars['--radius-container'],
|
|
23
|
+
cursor: 'pointer',
|
|
23
24
|
},
|
|
24
25
|
});
|
|
25
26
|
|
|
@@ -212,12 +213,30 @@ const COMPONENT_CATEGORIES = [
|
|
|
212
213
|
export default function DocumentationOverviewPage() {
|
|
213
214
|
return (
|
|
214
215
|
<Layout
|
|
215
|
-
height="
|
|
216
|
+
height="fill"
|
|
216
217
|
contentWidth={1200}
|
|
218
|
+
start={
|
|
219
|
+
<LayoutPanel hasDivider padding={0}>
|
|
220
|
+
<SideNav header={<SideNavHeading heading="Product Name" />}>
|
|
221
|
+
<SideNavSection title="Navigation" isHeaderHidden>
|
|
222
|
+
<SideNavItem label="Home" isSelected />
|
|
223
|
+
<SideNavItem label="Getting started" />
|
|
224
|
+
</SideNavSection>
|
|
225
|
+
|
|
226
|
+
{COMPONENT_CATEGORIES.map(category => (
|
|
227
|
+
<SideNavSection key={category.label} title={category.label}>
|
|
228
|
+
{category.items.map(item => (
|
|
229
|
+
<SideNavItem key={item.key} label={item.name} />
|
|
230
|
+
))}
|
|
231
|
+
</SideNavSection>
|
|
232
|
+
))}
|
|
233
|
+
</SideNav>
|
|
234
|
+
</LayoutPanel>
|
|
235
|
+
}
|
|
217
236
|
content={
|
|
218
237
|
<LayoutContent padding={8}>
|
|
219
238
|
<VStack gap={10}>
|
|
220
|
-
<Card variant="
|
|
239
|
+
<Card variant="cyan" padding={10}>
|
|
221
240
|
<HStack gap={8} vAlign="center">
|
|
222
241
|
<StackItem size="fill">
|
|
223
242
|
<VStack gap={4}>
|
|
@@ -227,7 +246,11 @@ export default function DocumentationOverviewPage() {
|
|
|
227
246
|
beautiful, accessible products.
|
|
228
247
|
</Text>
|
|
229
248
|
<HStack>
|
|
230
|
-
<Button
|
|
249
|
+
<Button
|
|
250
|
+
label="Get started"
|
|
251
|
+
variant="primary"
|
|
252
|
+
size="lg"
|
|
253
|
+
/>
|
|
231
254
|
</HStack>
|
|
232
255
|
</VStack>
|
|
233
256
|
</StackItem>
|
|
@@ -237,35 +260,25 @@ export default function DocumentationOverviewPage() {
|
|
|
237
260
|
|
|
238
261
|
{COMPONENT_CATEGORIES.map(category => (
|
|
239
262
|
<VStack key={category.label} gap={4}>
|
|
240
|
-
<
|
|
241
|
-
<Grid
|
|
242
|
-
columns={{minWidth: 260}}
|
|
243
|
-
gap={2}
|
|
244
|
-
xstyle={styles.cardGrid}>
|
|
263
|
+
<Text type="display-2">{category.label}</Text>
|
|
264
|
+
<Grid columns={{minWidth: 260}} gap={8}>
|
|
245
265
|
{category.items.map(item => (
|
|
246
|
-
<
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
<Text type="body" weight="bold">
|
|
261
|
-
{item.name}
|
|
262
|
-
</Text>
|
|
263
|
-
<Text type="body" color="secondary" maxLines={3}>
|
|
264
|
-
{item.desc}
|
|
265
|
-
</Text>
|
|
266
|
-
</VStack>
|
|
266
|
+
<VStack key={item.key} gap={3}>
|
|
267
|
+
<Card
|
|
268
|
+
variant="muted"
|
|
269
|
+
padding={0}
|
|
270
|
+
minHeight={160}
|
|
271
|
+
xstyle={styles.previewCard}
|
|
272
|
+
/>
|
|
273
|
+
<VStack gap={0.5}>
|
|
274
|
+
<Text type="body" weight="bold">
|
|
275
|
+
{item.name}
|
|
276
|
+
</Text>
|
|
277
|
+
<Text type="body" color="secondary">
|
|
278
|
+
{item.desc}
|
|
279
|
+
</Text>
|
|
267
280
|
</VStack>
|
|
268
|
-
</
|
|
281
|
+
</VStack>
|
|
269
282
|
))}
|
|
270
283
|
</Grid>
|
|
271
284
|
</VStack>
|
|
@@ -2,8 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
'use client';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {useState, useMemo} from 'react';
|
|
6
6
|
import * as stylex from '@stylexjs/stylex';
|
|
7
|
+
import {
|
|
8
|
+
SideNav,
|
|
9
|
+
SideNavHeading,
|
|
10
|
+
SideNavItem,
|
|
11
|
+
SideNavSection,
|
|
12
|
+
} from '@astryxdesign/core/SideNav';
|
|
7
13
|
import {Heading, Text} from '@astryxdesign/core/Text';
|
|
8
14
|
import {Button} from '@astryxdesign/core/Button';
|
|
9
15
|
import {IconButton} from '@astryxdesign/core/IconButton';
|
|
@@ -14,10 +20,8 @@ import {Token} from '@astryxdesign/core/Token';
|
|
|
14
20
|
import {Banner} from '@astryxdesign/core/Banner';
|
|
15
21
|
import {CodeBlock} from '@astryxdesign/core/CodeBlock';
|
|
16
22
|
import {TabList, Tab} from '@astryxdesign/core/TabList';
|
|
17
|
-
import {Selector} from '@astryxdesign/core/Selector';
|
|
18
23
|
import {HStack, VStack, StackItem} from '@astryxdesign/core/Stack';
|
|
19
24
|
import {Layout, LayoutContent, LayoutPanel} from '@astryxdesign/core/Layout';
|
|
20
|
-
import {useMediaQuery} from '@astryxdesign/core/hooks';
|
|
21
25
|
import {Dialog, DialogHeader} from '@astryxdesign/core/Dialog';
|
|
22
26
|
import {Divider} from '@astryxdesign/core/Divider';
|
|
23
27
|
import {Tooltip} from '@astryxdesign/core/Tooltip';
|
|
@@ -25,7 +29,6 @@ import {Table, pixel} from '@astryxdesign/core/Table';
|
|
|
25
29
|
import {Icon} from '@astryxdesign/core/Icon';
|
|
26
30
|
import {Section} from '@astryxdesign/core/Section';
|
|
27
31
|
import {Center} from '@astryxdesign/core/Center';
|
|
28
|
-
import {Outline, type OutlineItem} from '@astryxdesign/core/Outline';
|
|
29
32
|
import {
|
|
30
33
|
ArrowTopRightOnSquareIcon,
|
|
31
34
|
ArrowsPointingOutIcon,
|
|
@@ -34,25 +37,8 @@ import {
|
|
|
34
37
|
|
|
35
38
|
const styles = stylex.create({
|
|
36
39
|
tabListFlush: {marginInlineStart: '-12px'},
|
|
37
|
-
outlinePanel: {
|
|
38
|
-
position: 'sticky',
|
|
39
|
-
top: 24,
|
|
40
|
-
alignSelf: 'start',
|
|
41
|
-
paddingBlockStart: 120,
|
|
42
|
-
},
|
|
43
40
|
});
|
|
44
41
|
|
|
45
|
-
const COMPONENT_OUTLINE_ITEMS: OutlineItem[] = [
|
|
46
|
-
{id: 'usage', label: 'Usage', level: 2},
|
|
47
|
-
{id: 'best-practices', label: 'Best practices', level: 3},
|
|
48
|
-
{id: 'examples', label: 'Examples', level: 2},
|
|
49
|
-
];
|
|
50
|
-
|
|
51
|
-
const COMPONENT_OUTLINE_OPTIONS = COMPONENT_OUTLINE_ITEMS.map(item => ({
|
|
52
|
-
value: item.id,
|
|
53
|
-
label: item.label,
|
|
54
|
-
}));
|
|
55
|
-
|
|
56
42
|
// ---------------------------------------------------------------------------
|
|
57
43
|
// DialogPreview — stateful dialog preview for component previews
|
|
58
44
|
// ---------------------------------------------------------------------------
|
|
@@ -507,21 +493,14 @@ function getComponentDocs(key: string) {
|
|
|
507
493
|
// ComponentDetailView
|
|
508
494
|
// ---------------------------------------------------------------------------
|
|
509
495
|
|
|
510
|
-
function ComponentDetailView({
|
|
496
|
+
function ComponentDetailView({
|
|
497
|
+
activeNav,
|
|
498
|
+
nav,
|
|
499
|
+
}: {
|
|
500
|
+
activeNav: string;
|
|
501
|
+
nav: React.ReactNode;
|
|
502
|
+
}) {
|
|
511
503
|
const [exampleTabs, setExampleTabs] = useState<Record<string, string>>({});
|
|
512
|
-
const [activeId, setActiveId] = useState<string | undefined>(
|
|
513
|
-
COMPONENT_OUTLINE_ITEMS[0]?.id,
|
|
514
|
-
);
|
|
515
|
-
const isMobile = useMediaQuery('(max-width: 768px)');
|
|
516
|
-
|
|
517
|
-
const scrollToId = useCallback((id: string) => {
|
|
518
|
-
setActiveId(id);
|
|
519
|
-
const target = document.getElementById(id);
|
|
520
|
-
if (target != null) {
|
|
521
|
-
target.scrollIntoView({behavior: 'smooth', block: 'start'});
|
|
522
|
-
window.history.pushState(null, '', `#${id}`);
|
|
523
|
-
}
|
|
524
|
-
}, []);
|
|
525
504
|
|
|
526
505
|
const EXAMPLE_PREVIEWS: Record<string, React.ReactNode[]> = {
|
|
527
506
|
button: [
|
|
@@ -577,42 +556,25 @@ function ComponentDetailView({activeNav}: {activeNav: string}) {
|
|
|
577
556
|
|
|
578
557
|
return (
|
|
579
558
|
<Layout
|
|
580
|
-
height="
|
|
559
|
+
height="fill"
|
|
581
560
|
contentWidth={960}
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
label="On this page"
|
|
587
|
-
role="complementary"
|
|
588
|
-
xstyle={styles.outlinePanel}>
|
|
589
|
-
<Outline
|
|
590
|
-
items={COMPONENT_OUTLINE_ITEMS}
|
|
591
|
-
onActiveIdChange={setActiveId}
|
|
592
|
-
/>
|
|
593
|
-
</LayoutPanel>
|
|
594
|
-
)
|
|
561
|
+
start={
|
|
562
|
+
<LayoutPanel hasDivider padding={0}>
|
|
563
|
+
{nav}
|
|
564
|
+
</LayoutPanel>
|
|
595
565
|
}
|
|
596
566
|
content={
|
|
597
|
-
<LayoutContent
|
|
567
|
+
<LayoutContent padding={8}>
|
|
598
568
|
<VStack gap={8}>
|
|
599
569
|
<VStack gap={2}>
|
|
600
570
|
<Text type="display-1">{getComponentName(activeNav)}</Text>
|
|
601
571
|
<Text type="supporting" color="secondary">
|
|
602
572
|
March 30, 2026 · Updated 5:40 p.m. PST
|
|
603
573
|
</Text>
|
|
604
|
-
{isMobile && (
|
|
605
|
-
<Selector
|
|
606
|
-
label="On this page"
|
|
607
|
-
isLabelHidden
|
|
608
|
-
options={COMPONENT_OUTLINE_OPTIONS}
|
|
609
|
-
value={activeId}
|
|
610
|
-
onChange={scrollToId}
|
|
611
|
-
width="100%"
|
|
612
|
-
/>
|
|
613
|
-
)}
|
|
614
574
|
</VStack>
|
|
615
575
|
|
|
576
|
+
<Divider />
|
|
577
|
+
|
|
616
578
|
<Card variant="muted" padding={0}>
|
|
617
579
|
<Center height={360}>
|
|
618
580
|
{COMPONENT_PREVIEWS[activeNav] ?? (
|
|
@@ -624,18 +586,13 @@ function ComponentDetailView({activeNav}: {activeNav: string}) {
|
|
|
624
586
|
</Card>
|
|
625
587
|
|
|
626
588
|
<VStack gap={4}>
|
|
627
|
-
<Heading
|
|
628
|
-
Usage
|
|
629
|
-
</Heading>
|
|
589
|
+
<Heading level={2}>Usage</Heading>
|
|
630
590
|
<Text type="large" weight="normal">
|
|
631
591
|
{docs.usage}
|
|
632
592
|
</Text>
|
|
633
|
-
<Heading
|
|
634
|
-
Best practices
|
|
635
|
-
</Heading>
|
|
593
|
+
<Heading level={3}>Best practices</Heading>
|
|
636
594
|
<Table
|
|
637
595
|
data={docs.bestPractices as Record<string, unknown>[]}
|
|
638
|
-
dividers="none"
|
|
639
596
|
columns={[
|
|
640
597
|
{
|
|
641
598
|
key: 'type',
|
|
@@ -659,15 +616,14 @@ function ComponentDetailView({activeNav}: {activeNav: string}) {
|
|
|
659
616
|
},
|
|
660
617
|
]}
|
|
661
618
|
density="spacious"
|
|
619
|
+
dividers="rows"
|
|
662
620
|
/>
|
|
663
621
|
</VStack>
|
|
664
622
|
|
|
665
623
|
<Divider />
|
|
666
624
|
|
|
667
625
|
<VStack gap={4}>
|
|
668
|
-
<Heading
|
|
669
|
-
Examples
|
|
670
|
-
</Heading>
|
|
626
|
+
<Heading level={2}>Examples</Heading>
|
|
671
627
|
<Text type="large" weight="normal">
|
|
672
628
|
Explore common configurations, variations, and states for this
|
|
673
629
|
component.
|
|
@@ -719,10 +675,7 @@ function ComponentDetailView({activeNav}: {activeNav: string}) {
|
|
|
719
675
|
<TabList
|
|
720
676
|
value={activeTab}
|
|
721
677
|
onChange={value =>
|
|
722
|
-
setExampleTabs(prev => ({
|
|
723
|
-
...prev,
|
|
724
|
-
[tabKey]: value,
|
|
725
|
-
}))
|
|
678
|
+
setExampleTabs(prev => ({...prev, [tabKey]: value}))
|
|
726
679
|
}
|
|
727
680
|
size="sm"
|
|
728
681
|
xstyle={styles.tabListFlush}>
|
|
@@ -732,11 +685,7 @@ function ComponentDetailView({activeNav}: {activeNav: string}) {
|
|
|
732
685
|
{activeTab === 'description' ? (
|
|
733
686
|
<Text type="body">{example.description}</Text>
|
|
734
687
|
) : (
|
|
735
|
-
<CodeBlock
|
|
736
|
-
code={example.code}
|
|
737
|
-
language="tsx"
|
|
738
|
-
width="100%"
|
|
739
|
-
/>
|
|
688
|
+
<CodeBlock code={example.code} language="tsx" />
|
|
740
689
|
)}
|
|
741
690
|
</VStack>
|
|
742
691
|
</Section>
|
|
@@ -756,5 +705,31 @@ function ComponentDetailView({activeNav}: {activeNav: string}) {
|
|
|
756
705
|
// ---------------------------------------------------------------------------
|
|
757
706
|
|
|
758
707
|
export default function DesignDocumentationPage() {
|
|
759
|
-
|
|
708
|
+
const [activePage, setActivePage] = useState<string>('button');
|
|
709
|
+
|
|
710
|
+
return (
|
|
711
|
+
<ComponentDetailView
|
|
712
|
+
activeNav={activePage}
|
|
713
|
+
nav={
|
|
714
|
+
<SideNav header={<SideNavHeading heading="Product Name" />}>
|
|
715
|
+
{COMPONENT_CATEGORIES.map(category => (
|
|
716
|
+
<SideNavSection key={category.label} title={category.label}>
|
|
717
|
+
{category.items.map(item => (
|
|
718
|
+
<SideNavItem
|
|
719
|
+
key={item.key}
|
|
720
|
+
label={item.name}
|
|
721
|
+
isSelected={activePage === item.key}
|
|
722
|
+
onClick={
|
|
723
|
+
item.key === 'button'
|
|
724
|
+
? () => setActivePage(item.key)
|
|
725
|
+
: undefined
|
|
726
|
+
}
|
|
727
|
+
/>
|
|
728
|
+
))}
|
|
729
|
+
</SideNavSection>
|
|
730
|
+
))}
|
|
731
|
+
</SideNav>
|
|
732
|
+
}
|
|
733
|
+
/>
|
|
734
|
+
);
|
|
760
735
|
}
|
|
@@ -2,21 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
'use client';
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import {
|
|
6
|
+
SideNav,
|
|
7
|
+
SideNavHeading,
|
|
8
|
+
SideNavItem,
|
|
9
|
+
SideNavSection,
|
|
10
|
+
} from '@astryxdesign/core/SideNav';
|
|
7
11
|
import {Heading, Text} from '@astryxdesign/core/Text';
|
|
8
12
|
import {Button} from '@astryxdesign/core/Button';
|
|
9
13
|
import {Card} from '@astryxdesign/core/Card';
|
|
10
14
|
import {DropdownMenu} from '@astryxdesign/core/DropdownMenu';
|
|
11
15
|
import {List, ListItem} from '@astryxdesign/core/List';
|
|
12
16
|
import {CodeBlock} from '@astryxdesign/core/CodeBlock';
|
|
13
|
-
import {Selector} from '@astryxdesign/core/Selector';
|
|
14
17
|
import {HStack, VStack, StackItem} from '@astryxdesign/core/Stack';
|
|
15
18
|
import {Layout, LayoutContent, LayoutPanel} from '@astryxdesign/core/Layout';
|
|
16
19
|
import {Divider} from '@astryxdesign/core/Divider';
|
|
17
20
|
import {Icon} from '@astryxdesign/core/Icon';
|
|
18
|
-
import {Outline, type OutlineItem} from '@astryxdesign/core/Outline';
|
|
19
|
-
import {useMediaQuery} from '@astryxdesign/core/hooks';
|
|
20
21
|
import {
|
|
21
22
|
SparklesIcon,
|
|
22
23
|
ClipboardDocumentIcon,
|
|
@@ -27,75 +28,35 @@ import {
|
|
|
27
28
|
// Main component
|
|
28
29
|
// ---------------------------------------------------------------------------
|
|
29
30
|
|
|
30
|
-
const OUTLINE_ITEMS: OutlineItem[] = [
|
|
31
|
-
{id: 'prerequisites', label: 'Prerequisites', level: 2},
|
|
32
|
-
{id: 'install-package', label: 'Install the package', level: 2},
|
|
33
|
-
{id: 'configure-theming', label: 'Configure theming', level: 2},
|
|
34
|
-
{id: 'next-steps', label: 'Next steps', level: 2},
|
|
35
|
-
];
|
|
36
|
-
|
|
37
|
-
const OUTLINE_OPTIONS = OUTLINE_ITEMS.map(item => ({
|
|
38
|
-
value: item.id,
|
|
39
|
-
label: item.label,
|
|
40
|
-
}));
|
|
41
|
-
|
|
42
|
-
const styles = stylex.create({
|
|
43
|
-
outlinePanel: {
|
|
44
|
-
position: 'sticky',
|
|
45
|
-
top: 24,
|
|
46
|
-
alignSelf: 'start',
|
|
47
|
-
paddingBlockStart: 120,
|
|
48
|
-
},
|
|
49
|
-
});
|
|
50
|
-
|
|
51
31
|
export default function TechnicalDocumentationPage() {
|
|
52
|
-
const [activeId, setActiveId] = useState<string | undefined>(
|
|
53
|
-
OUTLINE_ITEMS[0]?.id,
|
|
54
|
-
);
|
|
55
|
-
const isMobile = useMediaQuery('(max-width: 768px)');
|
|
56
|
-
|
|
57
|
-
const scrollToId = useCallback((id: string) => {
|
|
58
|
-
setActiveId(id);
|
|
59
|
-
const target = document.getElementById(id);
|
|
60
|
-
if (target != null) {
|
|
61
|
-
target.scrollIntoView({behavior: 'smooth', block: 'start'});
|
|
62
|
-
window.history.pushState(null, '', `#${id}`);
|
|
63
|
-
}
|
|
64
|
-
}, []);
|
|
65
|
-
|
|
66
32
|
return (
|
|
67
33
|
<Layout
|
|
68
|
-
height="
|
|
34
|
+
height="fill"
|
|
69
35
|
contentWidth={960}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
<
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
)
|
|
36
|
+
start={
|
|
37
|
+
<LayoutPanel hasDivider padding={0}>
|
|
38
|
+
<SideNav header={<SideNavHeading heading="Product Name" />}>
|
|
39
|
+
<SideNavSection title="Navigation" isHeaderHidden>
|
|
40
|
+
<SideNavItem label="Home" />
|
|
41
|
+
<SideNavItem label="Getting started" isSelected />
|
|
42
|
+
</SideNavSection>
|
|
43
|
+
</SideNav>
|
|
44
|
+
</LayoutPanel>
|
|
80
45
|
}
|
|
81
46
|
content={
|
|
82
|
-
<LayoutContent
|
|
47
|
+
<LayoutContent padding={8}>
|
|
83
48
|
<VStack gap={8}>
|
|
84
49
|
<VStack gap={2}>
|
|
85
|
-
<Text type="display-1">
|
|
50
|
+
<Text type="display-1">
|
|
51
|
+
Getting started with Product Name
|
|
52
|
+
</Text>
|
|
86
53
|
<Text type="supporting" color="secondary">
|
|
87
54
|
Last updated March 30, 2026
|
|
88
55
|
</Text>
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
options={OUTLINE_OPTIONS}
|
|
94
|
-
value={activeId}
|
|
95
|
-
onChange={scrollToId}
|
|
96
|
-
width="100%"
|
|
97
|
-
/>
|
|
98
|
-
)}
|
|
56
|
+
<Text type="body">
|
|
57
|
+
Install the package, configure your theme, and build your first
|
|
58
|
+
component in three steps.
|
|
59
|
+
</Text>
|
|
99
60
|
</VStack>
|
|
100
61
|
|
|
101
62
|
<Card>
|
|
@@ -103,7 +64,11 @@ export default function TechnicalDocumentationPage() {
|
|
|
103
64
|
<HStack gap={2} vAlign="center">
|
|
104
65
|
<StackItem size="fill">
|
|
105
66
|
<HStack gap={2} vAlign="center">
|
|
106
|
-
<Icon
|
|
67
|
+
<Icon
|
|
68
|
+
icon={SparklesIcon}
|
|
69
|
+
size="sm"
|
|
70
|
+
color="secondary"
|
|
71
|
+
/>
|
|
107
72
|
<Text type="body" weight="semibold">
|
|
108
73
|
AI Assistance
|
|
109
74
|
</Text>
|
|
@@ -146,9 +111,7 @@ export default function TechnicalDocumentationPage() {
|
|
|
146
111
|
</Card>
|
|
147
112
|
|
|
148
113
|
<VStack gap={4}>
|
|
149
|
-
<Heading
|
|
150
|
-
Prerequisites
|
|
151
|
-
</Heading>
|
|
114
|
+
<Heading level={2}>Prerequisites</Heading>
|
|
152
115
|
<List density="compact" listStyle="disc">
|
|
153
116
|
<ListItem label="Node.js 18+" />
|
|
154
117
|
<ListItem label="React 18 or 19" />
|
|
@@ -159,9 +122,7 @@ export default function TechnicalDocumentationPage() {
|
|
|
159
122
|
<Divider />
|
|
160
123
|
|
|
161
124
|
<VStack gap={4}>
|
|
162
|
-
<Heading
|
|
163
|
-
Install the package
|
|
164
|
-
</Heading>
|
|
125
|
+
<Heading level={2}>Install the package</Heading>
|
|
165
126
|
<Text type="body">
|
|
166
127
|
Every project starts with installing the core package. This
|
|
167
128
|
gives you access to all components, tokens, and utilities.
|
|
@@ -170,11 +131,9 @@ export default function TechnicalDocumentationPage() {
|
|
|
170
131
|
<Text type="body" weight="bold">
|
|
171
132
|
Step 1: Install the core package
|
|
172
133
|
</Text>
|
|
173
|
-
<
|
|
174
|
-
code="npm install @astryxdesign/core"
|
|
175
|
-
|
|
176
|
-
width="100%"
|
|
177
|
-
/>
|
|
134
|
+
<Card padding={0}>
|
|
135
|
+
<CodeBlock code="npm install @astryxdesign/core" language="bash" />
|
|
136
|
+
</Card>
|
|
178
137
|
</VStack>
|
|
179
138
|
<VStack gap={2}>
|
|
180
139
|
<Text type="body" weight="bold">
|
|
@@ -184,41 +143,42 @@ export default function TechnicalDocumentationPage() {
|
|
|
184
143
|
Astryx uses StyleX for styling. Add the compiler plugin to your
|
|
185
144
|
build configuration.
|
|
186
145
|
</Text>
|
|
187
|
-
<
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
146
|
+
<Card padding={0}>
|
|
147
|
+
<CodeBlock
|
|
148
|
+
code="npm install @stylexjs/babel-plugin"
|
|
149
|
+
language="bash"
|
|
150
|
+
/>
|
|
151
|
+
</Card>
|
|
192
152
|
</VStack>
|
|
193
153
|
<VStack gap={2}>
|
|
194
154
|
<Text type="body" weight="bold">
|
|
195
155
|
Step 3: Import your first component
|
|
196
156
|
</Text>
|
|
197
|
-
<
|
|
198
|
-
|
|
157
|
+
<Card padding={0}>
|
|
158
|
+
<CodeBlock
|
|
159
|
+
code={`import { Button } from '@astryxdesign/core/Button';
|
|
199
160
|
|
|
200
161
|
export default function App() {
|
|
201
162
|
return <Button label="Hello Astryx" variant="primary" />;
|
|
202
163
|
}`}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
164
|
+
language="tsx"
|
|
165
|
+
/>
|
|
166
|
+
</Card>
|
|
206
167
|
</VStack>
|
|
207
168
|
</VStack>
|
|
208
169
|
|
|
209
170
|
<Divider />
|
|
210
171
|
|
|
211
172
|
<VStack gap={4}>
|
|
212
|
-
<Heading
|
|
213
|
-
Configure theming
|
|
214
|
-
</Heading>
|
|
173
|
+
<Heading level={2}>Configure theming</Heading>
|
|
215
174
|
<Text type="body">
|
|
216
175
|
Astryx ships with a default theme that works out of the box. To
|
|
217
176
|
customize colors, typography, and spacing, wrap your app in a
|
|
218
177
|
theme provider.
|
|
219
178
|
</Text>
|
|
220
|
-
<
|
|
221
|
-
|
|
179
|
+
<Card padding={0}>
|
|
180
|
+
<CodeBlock
|
|
181
|
+
code={`import { ThemeProvider } from '@astryxdesign/core/Theme';
|
|
222
182
|
|
|
223
183
|
export default function App({ children }) {
|
|
224
184
|
return (
|
|
@@ -227,9 +187,9 @@ export default function App({ children }) {
|
|
|
227
187
|
</ThemeProvider>
|
|
228
188
|
);
|
|
229
189
|
}`}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
190
|
+
language="tsx"
|
|
191
|
+
/>
|
|
192
|
+
</Card>
|
|
233
193
|
<Text type="body" color="secondary">
|
|
234
194
|
See the theming guide for the full list of customizable tokens.
|
|
235
195
|
</Text>
|
|
@@ -238,9 +198,7 @@ export default function App({ children }) {
|
|
|
238
198
|
<Divider />
|
|
239
199
|
|
|
240
200
|
<VStack gap={4}>
|
|
241
|
-
<Heading
|
|
242
|
-
Next steps
|
|
243
|
-
</Heading>
|
|
201
|
+
<Heading level={2}>Next steps</Heading>
|
|
244
202
|
<List density="compact" listStyle="disc">
|
|
245
203
|
<ListItem label="Fundamental concepts — How theming, layout, and composition work" />
|
|
246
204
|
<ListItem label="Component API reference — Props, variants, and examples for every component" />
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
import {useState, useMemo} from 'react';
|
|
6
6
|
import * as stylex from '@stylexjs/stylex';
|
|
7
|
+
import {SideNav, SideNavItem, SideNavSection} from '@astryxdesign/core/SideNav';
|
|
7
8
|
|
|
8
9
|
import {Layout, LayoutContent, LayoutPanel} from '@astryxdesign/core/Layout';
|
|
9
10
|
import {ResizeHandle, useResizable} from '@astryxdesign/core/Resizable';
|
|
10
11
|
import {Text, Heading} from '@astryxdesign/core/Text';
|
|
11
12
|
import {CodeBlock} from '@astryxdesign/core/CodeBlock';
|
|
12
13
|
import {colorVars, spacingVars} from '@astryxdesign/core/theme/tokens.stylex';
|
|
13
|
-
import {Stack
|
|
14
|
-
import {useMediaQuery} from '@astryxdesign/core/hooks';
|
|
14
|
+
import {Stack} from '@astryxdesign/core/Layout';
|
|
15
15
|
import {TabList, Tab} from '@astryxdesign/core/TabList';
|
|
16
16
|
import {
|
|
17
17
|
SegmentedControl,
|
|
@@ -27,14 +27,29 @@ import type {TreeListItemData} from '@astryxdesign/core/TreeList';
|
|
|
27
27
|
import {
|
|
28
28
|
FolderIcon,
|
|
29
29
|
DocumentTextIcon,
|
|
30
|
+
CodeBracketIcon,
|
|
30
31
|
MagnifyingGlassIcon,
|
|
32
|
+
CommandLineIcon,
|
|
33
|
+
ExclamationTriangleIcon,
|
|
34
|
+
InformationCircleIcon,
|
|
35
|
+
BugAntIcon,
|
|
36
|
+
HomeIcon,
|
|
37
|
+
FolderOpenIcon,
|
|
38
|
+
PuzzlePieceIcon,
|
|
31
39
|
} from '@heroicons/react/24/outline';
|
|
40
|
+
import {
|
|
41
|
+
HomeIcon as HomeIconSolid,
|
|
42
|
+
FolderOpenIcon as FolderOpenSolid,
|
|
43
|
+
MagnifyingGlassIcon as MagnifyingGlassSolid,
|
|
44
|
+
PuzzlePieceIcon as PuzzlePieceSolid,
|
|
45
|
+
} from '@heroicons/react/24/solid';
|
|
32
46
|
|
|
33
47
|
const styles = stylex.create({
|
|
34
48
|
contentFill: {
|
|
35
49
|
height: '100%',
|
|
36
50
|
},
|
|
37
51
|
terminalWrapper: {
|
|
52
|
+
flex: 1,
|
|
38
53
|
minHeight: 0,
|
|
39
54
|
overflow: 'hidden',
|
|
40
55
|
display: 'grid',
|
|
@@ -54,27 +69,28 @@ const styles = stylex.create({
|
|
|
54
69
|
flexShrink: 0,
|
|
55
70
|
},
|
|
56
71
|
editorArea: {
|
|
72
|
+
flex: 1,
|
|
57
73
|
overflow: 'auto',
|
|
58
|
-
minHeight: 0,
|
|
59
74
|
},
|
|
60
75
|
fileExplorer: {
|
|
61
76
|
padding: 16,
|
|
62
|
-
minWidth: 0,
|
|
63
|
-
},
|
|
64
|
-
propertiesPanel: {
|
|
65
|
-
height: '100%',
|
|
66
|
-
},
|
|
67
|
-
propertiesContent: {
|
|
68
|
-
flex: 1,
|
|
69
|
-
minHeight: 0,
|
|
70
|
-
},
|
|
71
|
-
propertyActions: {
|
|
72
|
-
marginTop: 'auto',
|
|
73
77
|
},
|
|
74
78
|
terminalArea: {
|
|
75
79
|
height: '100%',
|
|
76
80
|
overflow: 'hidden',
|
|
77
81
|
},
|
|
82
|
+
hideOnMobile: {
|
|
83
|
+
display: {
|
|
84
|
+
default: 'contents',
|
|
85
|
+
'@media (max-width: 768px)': 'none',
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
hideSideNav: {
|
|
89
|
+
display: {
|
|
90
|
+
default: 'flex',
|
|
91
|
+
'@media (max-width: 768px)': 'none',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
78
94
|
});
|
|
79
95
|
|
|
80
96
|
const EDITOR_CODE = `import {useState, useCallback} from 'react';
|
|
@@ -135,23 +151,22 @@ $ `;
|
|
|
135
151
|
function buildFileTree(
|
|
136
152
|
onFileClick: (name: string) => void,
|
|
137
153
|
): TreeListItemData[] {
|
|
138
|
-
const label = (text: string) => <Text maxLines={1}>{text}</Text>;
|
|
139
154
|
const file = (id: string): TreeListItemData => ({
|
|
140
155
|
id,
|
|
141
|
-
label:
|
|
156
|
+
label: id,
|
|
142
157
|
startContent: <Icon icon={DocumentTextIcon} size="xsm" />,
|
|
143
158
|
onClick: () => onFileClick(id),
|
|
144
159
|
});
|
|
145
160
|
return [
|
|
146
161
|
{
|
|
147
162
|
id: 'src',
|
|
148
|
-
label:
|
|
163
|
+
label: 'src',
|
|
149
164
|
startContent: <Icon icon={FolderIcon} size="xsm" />,
|
|
150
165
|
isExpanded: true,
|
|
151
166
|
children: [
|
|
152
167
|
{
|
|
153
168
|
id: 'components',
|
|
154
|
-
label:
|
|
169
|
+
label: 'components',
|
|
155
170
|
startContent: <Icon icon={FolderIcon} size="xsm" />,
|
|
156
171
|
isExpanded: true,
|
|
157
172
|
children: [
|
|
@@ -162,14 +177,14 @@ function buildFileTree(
|
|
|
162
177
|
},
|
|
163
178
|
{
|
|
164
179
|
id: 'pages',
|
|
165
|
-
label:
|
|
180
|
+
label: 'pages',
|
|
166
181
|
startContent: <Icon icon={FolderIcon} size="xsm" />,
|
|
167
182
|
isExpanded: true,
|
|
168
183
|
children: [file('index.tsx'), file('about.tsx')],
|
|
169
184
|
},
|
|
170
185
|
{
|
|
171
186
|
id: 'styles',
|
|
172
|
-
label:
|
|
187
|
+
label: 'styles',
|
|
173
188
|
startContent: <Icon icon={FolderIcon} size="xsm" />,
|
|
174
189
|
isExpanded: true,
|
|
175
190
|
children: [file('tokens.stylex.ts'), file('theme.ts')],
|
|
@@ -201,6 +216,7 @@ const HISTORY_ITEMS = [
|
|
|
201
216
|
|
|
202
217
|
export default function ResizableWorkspacePage() {
|
|
203
218
|
const [activeFile, setActiveFile] = useState('Counter.tsx');
|
|
219
|
+
const [activeNavItem, setActiveNavItem] = useState('Explorer');
|
|
204
220
|
const [activeTermTab, setActiveTermTab] = useState('terminal');
|
|
205
221
|
const [activePropertiesTab, setActivePropertiesTab] = useState('properties');
|
|
206
222
|
const fileTree = useMemo(() => buildFileTree(setActiveFile), []);
|
|
@@ -229,48 +245,89 @@ export default function ResizableWorkspacePage() {
|
|
|
229
245
|
collapsedSize: 40,
|
|
230
246
|
});
|
|
231
247
|
|
|
232
|
-
const isMobile = useMediaQuery('(max-width: 768px)');
|
|
233
|
-
|
|
234
248
|
return (
|
|
235
249
|
<Layout
|
|
236
250
|
height="fill"
|
|
251
|
+
start={
|
|
252
|
+
<LayoutPanel hasDivider={false} padding={0}>
|
|
253
|
+
<SideNav
|
|
254
|
+
collapsible={{defaultIsCollapsed: true}}
|
|
255
|
+
resizable
|
|
256
|
+
xstyle={styles.hideSideNav}>
|
|
257
|
+
<SideNavSection title="Navigation" isHeaderHidden>
|
|
258
|
+
<SideNavItem
|
|
259
|
+
label="Home"
|
|
260
|
+
icon={HomeIcon}
|
|
261
|
+
selectedIcon={HomeIconSolid}
|
|
262
|
+
isSelected={activeNavItem === 'Home'}
|
|
263
|
+
onClick={() => setActiveNavItem('Home')}
|
|
264
|
+
/>
|
|
265
|
+
<SideNavItem
|
|
266
|
+
label="Explorer"
|
|
267
|
+
icon={FolderOpenIcon}
|
|
268
|
+
selectedIcon={FolderOpenSolid}
|
|
269
|
+
isSelected={activeNavItem === 'Explorer'}
|
|
270
|
+
onClick={() => setActiveNavItem('Explorer')}
|
|
271
|
+
/>
|
|
272
|
+
<SideNavItem
|
|
273
|
+
label="Search"
|
|
274
|
+
icon={MagnifyingGlassIcon}
|
|
275
|
+
selectedIcon={MagnifyingGlassSolid}
|
|
276
|
+
isSelected={activeNavItem === 'Search'}
|
|
277
|
+
onClick={() => setActiveNavItem('Search')}
|
|
278
|
+
/>
|
|
279
|
+
<SideNavItem
|
|
280
|
+
label="Source Control"
|
|
281
|
+
icon={CodeBracketIcon}
|
|
282
|
+
isSelected={activeNavItem === 'Source Control'}
|
|
283
|
+
onClick={() => setActiveNavItem('Source Control')}
|
|
284
|
+
/>
|
|
285
|
+
<SideNavItem
|
|
286
|
+
label="Extensions"
|
|
287
|
+
icon={PuzzlePieceIcon}
|
|
288
|
+
selectedIcon={PuzzlePieceSolid}
|
|
289
|
+
isSelected={activeNavItem === 'Extensions'}
|
|
290
|
+
onClick={() => setActiveNavItem('Extensions')}
|
|
291
|
+
/>
|
|
292
|
+
</SideNavSection>
|
|
293
|
+
</SideNav>
|
|
294
|
+
</LayoutPanel>
|
|
295
|
+
}
|
|
237
296
|
content={
|
|
238
297
|
<LayoutContent padding={0}>
|
|
239
298
|
<Layout
|
|
240
299
|
height="fill"
|
|
241
300
|
start={
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
</>
|
|
273
|
-
)
|
|
301
|
+
<div {...stylex.props(styles.hideOnMobile)}>
|
|
302
|
+
{!startPanel.isCollapsed && (
|
|
303
|
+
<LayoutPanel
|
|
304
|
+
width={startPanel.size}
|
|
305
|
+
hasDivider={false}
|
|
306
|
+
padding={0}>
|
|
307
|
+
<Stack
|
|
308
|
+
direction="vertical"
|
|
309
|
+
xstyle={styles.fileExplorer}
|
|
310
|
+
gap={2}>
|
|
311
|
+
<TextInput
|
|
312
|
+
label="Search files"
|
|
313
|
+
isLabelHidden
|
|
314
|
+
value=""
|
|
315
|
+
placeholder="Search"
|
|
316
|
+
size="md"
|
|
317
|
+
startIcon={MagnifyingGlassIcon}
|
|
318
|
+
/>
|
|
319
|
+
<TreeList items={fileTree} density="compact" />
|
|
320
|
+
</Stack>
|
|
321
|
+
</LayoutPanel>
|
|
322
|
+
)}
|
|
323
|
+
<ResizeHandle
|
|
324
|
+
direction="horizontal"
|
|
325
|
+
hasDivider
|
|
326
|
+
isAlwaysVisible={false}
|
|
327
|
+
resizable={startPanel.props}
|
|
328
|
+
label="Resize file explorer"
|
|
329
|
+
/>
|
|
330
|
+
</div>
|
|
274
331
|
}
|
|
275
332
|
content={
|
|
276
333
|
<LayoutContent padding={0}>
|
|
@@ -278,13 +335,13 @@ export default function ResizableWorkspacePage() {
|
|
|
278
335
|
height="fill"
|
|
279
336
|
content={
|
|
280
337
|
<LayoutContent padding={0}>
|
|
281
|
-
<Stack
|
|
282
|
-
|
|
338
|
+
<Stack
|
|
339
|
+
direction="vertical"
|
|
340
|
+
xstyle={styles.contentFill}>
|
|
341
|
+
<div {...stylex.props(styles.editorArea)}>
|
|
283
342
|
<CodeBlock
|
|
284
343
|
code={EDITOR_CODE}
|
|
285
344
|
language="typescript"
|
|
286
|
-
container="section"
|
|
287
|
-
hasLanguageLabel={false}
|
|
288
345
|
hasLineNumbers
|
|
289
346
|
highlightLines={[21]}
|
|
290
347
|
hasCopyButton={false}
|
|
@@ -296,7 +353,7 @@ export default function ResizableWorkspacePage() {
|
|
|
296
353
|
borderRadius: 0,
|
|
297
354
|
}}
|
|
298
355
|
/>
|
|
299
|
-
</
|
|
356
|
+
</div>
|
|
300
357
|
<ResizeHandle
|
|
301
358
|
direction="vertical"
|
|
302
359
|
hasDivider
|
|
@@ -321,19 +378,43 @@ export default function ResizableWorkspacePage() {
|
|
|
321
378
|
size="sm"
|
|
322
379
|
hasDivider={false}
|
|
323
380
|
xstyle={styles.tabListPadding}>
|
|
324
|
-
<Tab
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
381
|
+
<Tab
|
|
382
|
+
label="Terminal"
|
|
383
|
+
value="terminal"
|
|
384
|
+
icon={
|
|
385
|
+
<Icon icon={CommandLineIcon} size="sm" />
|
|
386
|
+
}
|
|
387
|
+
/>
|
|
388
|
+
<Tab
|
|
389
|
+
label="Problems"
|
|
390
|
+
value="problems"
|
|
391
|
+
icon={
|
|
392
|
+
<Icon
|
|
393
|
+
icon={ExclamationTriangleIcon}
|
|
394
|
+
size="sm"
|
|
395
|
+
/>
|
|
396
|
+
}
|
|
397
|
+
/>
|
|
398
|
+
<Tab
|
|
399
|
+
label="Output"
|
|
400
|
+
value="output"
|
|
401
|
+
icon={
|
|
402
|
+
<Icon
|
|
403
|
+
icon={InformationCircleIcon}
|
|
404
|
+
size="sm"
|
|
405
|
+
/>
|
|
406
|
+
}
|
|
407
|
+
/>
|
|
408
|
+
<Tab
|
|
409
|
+
label="Debug"
|
|
410
|
+
value="debug"
|
|
411
|
+
icon={<Icon icon={BugAntIcon} size="sm" />}
|
|
412
|
+
/>
|
|
328
413
|
</TabList>
|
|
329
|
-
<
|
|
330
|
-
size="fill"
|
|
331
|
-
xstyle={styles.terminalWrapper}>
|
|
414
|
+
<div {...stylex.props(styles.terminalWrapper)}>
|
|
332
415
|
<CodeBlock
|
|
333
416
|
code={TERMINAL_OUTPUT}
|
|
334
417
|
language="bash"
|
|
335
|
-
container="section"
|
|
336
|
-
hasLanguageLabel={false}
|
|
337
418
|
hasCopyButton={false}
|
|
338
419
|
size="sm"
|
|
339
420
|
style={{
|
|
@@ -343,7 +424,7 @@ export default function ResizableWorkspacePage() {
|
|
|
343
424
|
borderRadius: 0,
|
|
344
425
|
}}
|
|
345
426
|
/>
|
|
346
|
-
</
|
|
427
|
+
</div>
|
|
347
428
|
</Stack>
|
|
348
429
|
</div>
|
|
349
430
|
)}
|
|
@@ -351,118 +432,106 @@ export default function ResizableWorkspacePage() {
|
|
|
351
432
|
</LayoutContent>
|
|
352
433
|
}
|
|
353
434
|
end={
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
<
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
<
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
<MetadataListItem
|
|
407
|
-
key={prop.label}
|
|
408
|
-
label={prop.label}>
|
|
409
|
-
{prop.value}
|
|
410
|
-
</MetadataListItem>
|
|
411
|
-
))}
|
|
412
|
-
</MetadataList>
|
|
413
|
-
<Stack
|
|
414
|
-
direction="vertical"
|
|
415
|
-
gap={2}
|
|
416
|
-
xstyle={styles.propertyActions}>
|
|
435
|
+
<div {...stylex.props(styles.hideOnMobile)}>
|
|
436
|
+
<ResizeHandle
|
|
437
|
+
direction="horizontal"
|
|
438
|
+
hasDivider
|
|
439
|
+
isReversed
|
|
440
|
+
isAlwaysVisible={false}
|
|
441
|
+
resizable={endPanel.props}
|
|
442
|
+
label="Resize properties panel"
|
|
443
|
+
/>
|
|
444
|
+
{!endPanel.isCollapsed && (
|
|
445
|
+
<LayoutPanel
|
|
446
|
+
width={endPanel.size}
|
|
447
|
+
hasDivider={false}
|
|
448
|
+
padding={4}>
|
|
449
|
+
<Stack direction="vertical" gap={3}>
|
|
450
|
+
<SegmentedControl
|
|
451
|
+
label="Properties panel sections"
|
|
452
|
+
value={activePropertiesTab}
|
|
453
|
+
onChange={setActivePropertiesTab}
|
|
454
|
+
size="sm"
|
|
455
|
+
layout="fill">
|
|
456
|
+
<SegmentedControlItem
|
|
457
|
+
label="Properties"
|
|
458
|
+
value="properties"
|
|
459
|
+
/>
|
|
460
|
+
<SegmentedControlItem
|
|
461
|
+
label="History"
|
|
462
|
+
value="history"
|
|
463
|
+
/>
|
|
464
|
+
</SegmentedControl>
|
|
465
|
+
{activePropertiesTab === 'properties' ? (
|
|
466
|
+
<>
|
|
467
|
+
<Stack direction="vertical" gap={1}>
|
|
468
|
+
<Heading level={3}>
|
|
469
|
+
{activeFile}
|
|
470
|
+
</Heading>
|
|
471
|
+
<Text color="secondary" type="supporting">
|
|
472
|
+
src/components/{activeFile}
|
|
473
|
+
</Text>
|
|
474
|
+
</Stack>
|
|
475
|
+
<MetadataList
|
|
476
|
+
xstyle={styles.metadataCompact}>
|
|
477
|
+
{PROPERTIES.map(prop => (
|
|
478
|
+
<MetadataListItem
|
|
479
|
+
key={prop.label}
|
|
480
|
+
label={prop.label}>
|
|
481
|
+
{prop.value}
|
|
482
|
+
</MetadataListItem>
|
|
483
|
+
))}
|
|
484
|
+
</MetadataList>
|
|
485
|
+
<Stack direction="vertical" gap={2}>
|
|
486
|
+
<Stack direction="vertical" gap={2}>
|
|
417
487
|
<Button
|
|
418
488
|
label="Format Document"
|
|
419
|
-
size="
|
|
489
|
+
size="md"
|
|
420
490
|
variant="secondary"
|
|
421
491
|
/>
|
|
422
492
|
<Button
|
|
423
493
|
label="Go to Definition"
|
|
424
|
-
size="
|
|
494
|
+
size="md"
|
|
425
495
|
variant="secondary"
|
|
426
496
|
/>
|
|
427
497
|
<Button
|
|
428
498
|
label="Find References"
|
|
429
|
-
size="
|
|
499
|
+
size="md"
|
|
430
500
|
variant="secondary"
|
|
431
501
|
/>
|
|
432
502
|
</Stack>
|
|
433
503
|
</Stack>
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
)
|
|
504
|
+
</>
|
|
505
|
+
) : (
|
|
506
|
+
<Stack direction="vertical" gap={1}>
|
|
507
|
+
<List>
|
|
508
|
+
{HISTORY_ITEMS.map(item => (
|
|
509
|
+
<ListItem
|
|
510
|
+
key={item.label}
|
|
511
|
+
label={item.label}
|
|
512
|
+
endContent={
|
|
513
|
+
<Text
|
|
514
|
+
type="supporting"
|
|
515
|
+
color="secondary">
|
|
516
|
+
{item.time}
|
|
517
|
+
</Text>
|
|
518
|
+
}
|
|
519
|
+
startContent={
|
|
520
|
+
<span
|
|
521
|
+
{...stylex.props(
|
|
522
|
+
styles.historyTimelineDot,
|
|
523
|
+
)}
|
|
524
|
+
/>
|
|
525
|
+
}
|
|
526
|
+
/>
|
|
527
|
+
))}
|
|
528
|
+
</List>
|
|
529
|
+
</Stack>
|
|
530
|
+
)}
|
|
531
|
+
</Stack>
|
|
532
|
+
</LayoutPanel>
|
|
533
|
+
)}
|
|
534
|
+
</div>
|
|
466
535
|
}
|
|
467
536
|
/>
|
|
468
537
|
</LayoutContent>
|