figma-to-spirit
npx skills add https://github.com/alma-oss/spirit-design-system --skill figma-to-spirit
Agent 安装分布
Skill 文档
Figma to Spirit Component Conversion
Component Documentation
For detailed API references, examples, and common mistakes:
- Layout Components – Flex, Grid, Stack, Box, Section, Container
- Typography Components – Heading, Text
- Card Components – Card, CardLink, CardTitle, CardDescription
Core Principles
- ALWAYS use Spirit Web React components – Never create custom components or use raw HTML/CSS when a Spirit component exists
- NEVER use inline CSS – Use component props and styling props instead. Only use
UNSAFE_styleorUNSAFE_classNameas a last resort - Use this skill’s documentation as the primary reference:
- Check Layout Components for Flex, Grid, Stack, Box, Section, Container
- Check Typography Components for Heading, Text
- These docs contain API references, common mistakes, and correct prop values
- Read props from Figma CodeConnect EXACTLY:
- Call
get_code_connect_mapto get CodeConnect snippets from Figma - Use all props from CodeConnect exactly as shown – never override or change them
- If CodeConnect shows
Card, useCard(notFlexorBox) - CRITICAL – Icon names: If CodeConnect shows
iconName="placeholder", use EXACTLY"placeholder"– NEVER substitute with your own icon choices
- Call
- NEVER substitute icon names:
- Use the EXACT
iconNamevalue from Figma/CodeConnect (even if it’s"placeholder") - Do NOT choose “semantically appropriate” icons – that is the designer’s decision, not yours
- Placeholder icons are intentional – they indicate the final icon hasn’t been decided yet
- Wrong: Seeing
iconName="placeholder"and changing it to"shield-dualtone"or"folder" - Correct: Using
iconName="placeholder"exactly as shown
- Use the EXACT
- Use https://picsum.photos/ for all image placeholders – Format:
https://picsum.photos/seed/{identifier}/{width}/{height} - DO NOT set props to default values – Only set props when they differ from component defaults (check API Reference tables in component docs)
- Context7 MCP is a LAST RESORT – Only use for components not documented in this skill:
- Call
resolve-library-idwith@alma-oss/spirit-design-system - Call
query-docswith/alma-oss/spirit-design-systemand the component name
- Call
- ASK when uncertain – If you encounter a layout, pattern, or problem you don’t know how to implement with Spirit components:
- DO NOT guess or improvise – Stop and ask the user for guidance
- Describe what you’re trying to achieve and what’s unclear
- Ask if there’s a specific Spirit component or pattern to use
- Wait for the user’s response before proceeding
- This prevents incorrect implementations and teaches you new patterns for future use
Workflow
Step 1: Analyze Figma Structure
CRITICAL: Match Figma layer hierarchy exactly. Each Figma autolayout layer should have a corresponding Spirit layout component.
Extract from Figma:
- Component names – If Figma shows “Card Media NEW”, “Button”, etc., use the corresponding Spirit component
- Layer names for props – “Section XLarge” â
size="xlarge", “Button Large” âsize="large" - Icon names EXACTLY – If CodeConnect shows
iconName="placeholder", use"placeholder"– NEVER substitute your own icon choices - Spacing values – Read
gapfrom autolayout properties:gap-[var(--global/spacing/space-1400,64px)]âspacing="space-1400" - Color tokens – Read exact tokens from layer properties:
accent-01-subtle,accent-02-subtle, etc. - All wrapper layers – Each Figma layer with autolayout MUST have a corresponding Spirit component
- Alignment – Check
align-itemsandjustify-contentproperties - Fill width/height – Figma uses
align-self: stretchfor “fill” dimensions - Max-width constraints – Check which specific layer has max-width, apply only to that layer
- Padding values – Check for
pr,pl,pt,pb,px,pyon layers; apply using Box padding props - Link colors – Check for
themed/link/...tokens; these indicate clickable elements (use CardLink for Card titles)
Layer Structure Matching Example:
Figma Layers: Spirit Components:
âââ Section XLarge <Section size="xlarge">
â âââ Container XLarge (included in Section)
â âââ Content (gap: 32px) <Flex spacing="space-1000">
â âââ Heading (max-w: 800px) <Box UNSAFE_style={{ maxWidth }}>
â â âââ Tag <Flex spacing="space-700">
â â âââ Composition <Tag />
â â âââ Title <Flex spacing="space-900">
â â âââ Description <Heading />
â â âââ ActionGroup <Text />
â â <ActionGroup />
â âââ Column (4 items) </Flex></Box>
â âââ number <Grid cols={4}>
â âââ number <StatCard />
â âââ number ...
â âââ number </Grid>
Step 2: Choose Container Type
| Figma Pattern | Spirit Component |
|---|---|
| “Design Block” or main page section | Section |
| Need to constrain content width | Section containerProps={{ size: "..." }} |
| Full-width section content | Section hasContainer={false} |
Important: Section includes Container by default – don’t nest another Container inside.
Step 3: Choose Layout Pattern
| Figma Pattern | Spirit Component | Notes |
|---|---|---|
| Uniform repeatable items (cards, stats) | Grid |
Set cols prop, Grid handles row wrapping |
| Max-width centered content | Section containerProps={{ size: "..." }} |
NOT Grid |
| Single row or column | Flex |
direction="horizontal" or "vertical" |
| Columns with different structures | Multiple Flex columns |
Horizontal Flex wrapping vertical Flex children |
| Vertical list with dividers | Stack |
Use hasIntermediateDividers |
| Only styling (background, border) | Box |
No layout capabilities |
| Styling + layout combined | Box elementType={Flex} |
Combines styling and layout |
IMPORTANT: Check Layout Components for API reference, prop values, and common mistakes before implementing.
Step 4: Set Alignment Props
Check Figma Children for W-Full Before Setting Alignment
When analyzing Figma, check if children have w-full (full width) or shrink-0 w-full:
- If children have
w-fullâ Parent should usealignmentX="stretch"so children fill the container width - If children do NOT have
w-fullâ Parent should usealignmentX="left"to prevent unwanted width expansion - Children with both
w-fullANDmax-widthâ Parent usesalignmentX="stretch", child stretches UP TO its max-width constraint
// WRONG - alignmentX="left" prevents children from filling width even when Figma shows w-full
<Flex direction="vertical" spacing="space-1000" alignmentX="left">
<Box UNSAFE_style={{ maxWidth: "800px" }}>...</Box> {/* Won't stretch to 800px */}
<Grid cols={4}>...</Grid> {/* Won't fill container width */}
</Flex>
// CORRECT - alignmentX="stretch" lets children fill width (respecting their max-width if set)
<Flex direction="vertical" spacing="space-1000" alignmentX="stretch">
<Box UNSAFE_style={{ maxWidth: "800px" }}>...</Box> {/* Stretches up to 800px */}
<Grid cols={4}>...</Grid> {/* Fills container width */}
</Flex>
Value Mapping (CSS â Spirit)
| CSS Value | alignmentX | alignmentY |
|---|---|---|
flex-start |
left |
top |
center |
center |
center |
flex-end |
right |
bottom |
stretch |
stretch |
stretch |
Direction-based mapping:
- Vertical Flex:
align-itemsâalignmentX,justify-contentâalignmentY - Horizontal Flex:
justify-contentâalignmentX,align-itemsâalignmentY
Important: Always set alignmentX explicitly on vertical Flex. Choose stretch when Figma children have w-full, otherwise use left.
Step 5: Set Typography
| Figma Text Style | Spirit Component | Key Props |
|---|---|---|
| Heading styles | Heading |
elementType (REQUIRED), size, emphasis |
| Body text | Text |
elementType, size, emphasis |
Accessibility rules:
- Use
h1-h6only for actual semantic headings - For styled text that isn’t a heading (stats, labels):
elementType="div"or"span" - Maintain heading hierarchy (h1 â h2 â h3, don’t skip levels)
- Add
marginBottom="space-0"to typography elements that have siblings AFTER them in Flex/Grid/Stack (last-child elements don’t need it)
Use Full Accent Color Token Names
Heading and Text accept accent colors, but you must use the full token name (not short form).
// WRONG - short form "accent-02" causes TypeScript lint error
<Heading elementType="div" size="xlarge" textColor="accent-02">300K+</Heading>
// CORRECT - use full token name "accent-02-basic"
<Heading elementType="div" size="xlarge" textColor="accent-02-basic" marginBottom="space-0">300K+</Heading>
Valid accent tokens: accent-01-basic, accent-01-subtle, accent-02-basic, accent-02-subtle, etc.
IMPORTANT: Check Typography Components for API reference, prop values, and common mistakes before implementing.
Step 6: Responsive Design
When only one breakpoint is provided in Figma:
- Identify the breakpoint – Check Figma frame width (mobile < 768px, tablet 768-1024px, desktop > 1024px)
- Add responsive props for other breakpoints:
// Grid: reduce columns on smaller screens
<Grid cols={{ mobile: 1, tablet: 2, desktop: 4 }} />
// Flex: change direction on mobile
<Flex direction={{ mobile: 'vertical', tablet: 'horizontal' }} />
// Spacing: reduce on smaller screens
<Flex spacing={{ mobile: 'space-400', tablet: 'space-800', desktop: 'space-1200' }} />
- Design must match exactly on the provided breakpoint
Step 7: Crosscheck Design
Before finalizing, re-fetch Figma data and verify:
- CodeConnect snippets match code exactly – Every prop from CodeConnect is present
- Component names match – Spirit components used match Figma component names
- Icon names match EXACTLY – If CodeConnect shows
iconName="placeholder", code must use"placeholder"(NOT a substituted icon) - Spacing values match – Read from Figma autolayout properties
- Color tokens match – Exact tokens from Figma layer properties
- Layer structure matches – All wrapper layers represented
- Alignment matches – Explicit alignment props matching Figma
Quick Reference
Space Tokens
| Token Range | Typical Use |
|---|---|
space-100 – space-300 |
Tight spacing (icons, inline) |
space-400 – space-600 |
Small (within components) |
space-700 – space-900 |
Medium (between components) |
space-1000 – space-1200 |
Large (section padding) |
space-1300 – space-1600 |
Extra large (page sections) |
Color Token Examples
| Type | Examples |
|---|---|
| Background | primary, secondary, tertiary, accent-01-subtle, accent-02-subtle, neutral-subtle |
| Text | primary, secondary, tertiary, inverted, disabled, accent-01-basic, accent-02-basic |
| Border | basic, focus, accent colors |
Note: Always use full token names for accent colors (accent-02-basic, not accent-02). See Typography Components.
Link Color Tokens (CRITICAL for Card Detection)
When Figma shows these color tokens on text, it indicates the element should be a link:
| Figma Token | Meaning |
|---|---|
themed/link/primary/state-default |
Primary link color – use CardLink for Card titles |
themed/link/primary/state-hover |
Link hover state – CardLink handles automatically |
themed/link/secondary/... |
Secondary link – use CardLink or Link component |
If CardTitle has a link color token, use CardLink inside CardTitle, NOT Heading with textColor.
See Card Components for full documentation.
Implementation Checklist
Before finalizing code:
Figma Data Extraction:
- [ ] CodeConnect snippets used exactly as provided
- [ ] Component names verified (Figma â Spirit mapping)
- [ ] Icon names used EXACTLY as shown (if
iconName="placeholder", use"placeholder"– NEVER substitute) - [ ] Layer names checked for size/color/variant props
- [ ] Spacing values read from Figma autolayout properties
- [ ] Color tokens read exactly from Figma layer properties
Layout:
- [ ] Layout components have explicit alignment props
- [ ] Vertical Flex has
alignmentXset explicitly - [ ] Grid has both
alignmentXandalignmentYset - [ ] Figma “fill” width uses parent
alignmentX="stretch" - [ ] All Figma wrapper layers represented in code (match hierarchy)
- [ ] Uniform items use Grid, different structures use Flex columns
- [ ] Max-width constraints applied to correct innermost wrapper only
Typography:
- [ ] Heading
elementTypeset appropriately (h1-h6 for headings, div/span for styled text) - [ ] Heading hierarchy maintained (no skipped levels)
- [ ]
marginBottom="space-0"added to typography with siblings after them (not needed on last-child elements) - [ ] Accent text colors use full token names (
accent-02-basic, NOTaccent-02)
Styling:
- [ ] No inline CSS (except
UNSAFE_styleas last resort) - [ ]
UNSAFE_style maxWidthonly on innermost wrapper containing constrained content - [ ] Box + Flex pattern used when both styling and layout needed
- [ ] Box colors/borders match Figma exactly
- [ ] Padding values (
pr,pl,pt,pb,px,py) from Figma applied using Box props orFlex elementType={Box}
Cards & Links:
- [ ] CardTitle with
themed/link/...color tokens usesCardLink(not Heading with textColor) - [ ] CardLink used inside CardTitle for clickable cards
- [ ]
isHeadingset on CardTitle when appropriate - [ ] Horizontal Card with IconBox in CardArtwork uses Flex wrapper for vertical centering (see Card Components)
Responsive:
- [ ] Responsive props added for other breakpoints
- [ ] Design matches exactly on provided breakpoint
Images:
- [ ] Placeholders use picsum.photos format
Uncertainty:
- [ ] Asked user for guidance on any layouts/patterns you weren’t sure how to implement (don’t guess!)
Common Mistakes
1. Substituting Icon Names
CRITICAL: Never substitute icon names with your own choices.
// WRONG - Developer substituted "semantically appropriate" icons
<Icon name="shield-dualtone" /> // Was "placeholder" in Figma
<Icon name="folder" /> // Was "placeholder" in Figma
<Icon name="reload" /> // Was "placeholder" in Figma
// CORRECT - Use EXACTLY what Figma/CodeConnect specifies
<Icon name="placeholder" /> // Matches Figma exactly
<Icon name="placeholder" /> // Matches Figma exactly
<Icon name="placeholder" /> // Matches Figma exactly
Why this is wrong:
- Placeholder icons indicate the designer hasn’t finalized the icon choice yet
- Choosing icons is a design decision, not a developer decision
- Your “semantically appropriate” choice may conflict with the design system’s icon usage patterns
- This violates the core principle: “Use all props from CodeConnect exactly as shown”
The rule: If CodeConnect shows iconName="placeholder", your code MUST use iconName="placeholder". Period.