원문: https://github.com/facebook/astryx/wiki/Component-Authoring-Guide · 번역 기준: 2026-09-03
새 컴포넌트를 end-to-end로 만드시나요? 전체 lifecycle은 Component Lifecycle을 보세요. 구현과 아키텍처 리뷰는 Architecture Cheat Sheet로 시작하고, 상세한 컨벤션은 이 페이지를 활용하세요.
새로운 Astryx 컴포넌트를 만들기 위한 실용 레퍼런스입니다. 파일 구조, StyleX 패턴, token 사용법, 컨벤션을 다룹니다.
모든 컴포넌트는 /packages/core/src/ 아래 자신만의 디렉토리에 존재합니다:
/packages/core/src/Button/
├── Button.tsx # Main component implementation
├── index.ts # Exports
├── Button.doc.mjs # Typed documentation (JSDoc + ComponentDoc type)
└── Button.test.tsx # Tests
story는 컴포넌트와 함께 두지 않습니다. story는 Storybook 앱에 컴포넌트당 하나의 파일로 존재합니다:
/apps/storybook/stories/Button.stories.tsx
디렉토리, 파일, export되는 컴포넌트는 모두 컴포넌트의 이름을 공유합니다 — prefix 없이:
| Component | Directory | File | Export |
|---|---|---|---|
| Button | Button/ |
Button.tsx |
Button |
| Text Input | TextInput/ |
TextInput.tsx |
TextInput |
| Stack | Stack/ |
Stack.tsx |
Stack |
{Name}.doc.mjs)모든 컴포넌트 디렉토리에는 typed 문서를 export하는 {Name}.doc.mjs 파일이 있습니다. 이는 예전의 README.md 방식을 대체합니다 — 이제 문서는 CLI가 직접 import하는 구조화된 데이터입니다 (markdown 파싱 없음).
/** @type {import('@astryxdesign/cli/authoring').ComponentDoc} */
export const docs = {
name: 'Button',
description: 'Primary interactive element for user actions.',
features: [
"Variants: 'primary', 'secondary', 'ghost', 'destructive'",
'Sizes: sm (28px), md (32px), lg (36px)',
'Loading state: Shows spinner, disables interaction',
],
props: [
{
name: 'label',
type: 'string',
description: 'Accessible label; used as aria-label for icon-only buttons.',
required: true,
},
{
name: 'variant',
type: "'primary' | 'secondary' | 'ghost' | 'destructive'",
description: 'Visual style variant.',
default: "'secondary'",
},
// ... more props
],
examples: [
{
label: 'Basic',
code: '<Button variant="primary">Save</Button>',
},
{
label: 'With icon',
code: '<Button icon={PlusIcon} variant="secondary">Add</Button>',
},
],
theming: {
targets: [
{className: 'astryx-button', visualProps: ['variant', 'size']},
],
vars: [
{name: '--button-radius', description: 'Border radius', default: 'var(--radius-element)'},
],
},
accessibility: [
'Uses native <button> element for correct ARIA semantics.',
'Icon-only buttons use label prop as aria-label.',
],
keyboard: 'Enter/Space activates the button; Tab/Shift+Tab moves focus',
notes: [
'Hover states use backgroundImage overlay pattern for consistent layering.',
],
};
ComponentDoc 타입은 @astryxdesign/cli/authoring에서 옵니다 — 상대 경로가 아니라 패키지 이름으로 import하세요. 타입 체크는 다음으로 실행합니다:
pnpm --filter @astryxdesign/core typecheck:docs
이는 tsc --checkJs를 사용해 모든 .doc.mjs 파일을 ComponentDoc 타입에 대해 검증합니다. CI가 이를 자동으로 실행합니다.