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 or as 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 to get CodeConnect snippets from Figma
- Use all props from CodeConnect exactly as shown - never override or change them
- If CodeConnect shows , use (not or )
- CRITICAL - Icon names: If CodeConnect shows , use EXACTLY - NEVER substitute with your own icon choices
- NEVER substitute icon names:
- Use the EXACT value from Figma/CodeConnect (even if it's )
- 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 and changing it to or
- Correct: Using exactly as shown
- 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 with
@alma-oss/spirit-design-system
- Call with
/alma-oss/spirit-design-system
and the component name
- 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" → , "Button Large" →
- Icon names EXACTLY - If CodeConnect shows , use - NEVER substitute your own icon choices
- Spacing values - Read from autolayout properties:
gap-[var(--global/spacing/space-1400,64px)]
→
- Color tokens - Read exact tokens from layer properties: , , etc.
- All wrapper layers - Each Figma layer with autolayout MUST have a corresponding Spirit component
- Alignment - Check and properties
- Fill width/height - Figma uses for "fill" dimensions
- Max-width constraints - Check which specific layer has max-width, apply only to that layer
- Padding values - Check for , , , , , on layers; apply using Box padding props
- Link colors - Check for tokens; these indicate clickable elements (use CardLink for Card titles)
Layer Structure Matching Example:
text
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 | |
| 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) | | Set prop, Grid handles row wrapping |
| Max-width centered content | Section containerProps={{ size: "..." }}
| NOT Grid |
| Single row or column | | or |
| Columns with different structures | Multiple columns | Horizontal Flex wrapping vertical Flex children |
| Vertical list with dividers | | Use |
| Only styling (background, border) | | No layout capabilities |
| Styling + layout combined | | 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
(full width) or
:
- If children have → Parent should use so children fill the container width
- If children do NOT have → Parent should use to prevent unwanted width expansion
- Children with both AND → Parent uses , child stretches UP TO its max-width constraint
jsx
// 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 |
|---|
| | |
| | |
| | |
| | |
Direction-based mapping:
- Vertical Flex: → , →
- Horizontal Flex: → , →
Important: Always set
explicitly on vertical Flex. Choose
when Figma children have
, otherwise use
.
Step 5: Set Typography
| Figma Text Style | Spirit Component | Key Props |
|---|
| Heading styles | | (REQUIRED), , |
| Body text | | , , |
Accessibility rules:
- Use only for actual semantic headings
- For styled text that isn't a heading (stats, labels): or
- Maintain heading hierarchy (h1 → h2 → h3, don't skip levels)
- Add 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).
jsx
// 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:
,
,
,
, 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:
jsx
// 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 , code must use (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 |
|---|
| - | Tight spacing (icons, inline) |
| - | Small (within components) |
| - | Medium (between components) |
| - | Large (section padding) |
| - | Extra large (page sections) |
Color Token Examples
| Type | Examples |
|---|
| Background | , , , , , |
| Text | , , , , , , |
| Border | , , accent colors |
Note: Always use full token names for accent colors (
, not
). 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
inside
, 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 , use - 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 set explicitly
- [ ] Grid has both and set
- [ ] Figma "fill" width uses parent
- [ ] 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 set appropriately (h1-h6 for headings, div/span for styled text)
- [ ] Heading hierarchy maintained (no skipped levels)
- [ ] added to typography with siblings after them (not needed on last-child elements)
- [ ] Accent text colors use full token names (, NOT )
Styling:
- [ ] No inline CSS (except as last resort)
- [ ] only on innermost wrapper containing constrained content
- [ ] Box + Flex pattern used when both styling and layout needed
- [ ] Box colors/borders match Figma exactly
- [ ] Padding values (, , , , , ) from Figma applied using Box props or
Cards & Links:
- [ ] CardTitle with color tokens uses (not Heading with textColor)
- [ ] CardLink used inside CardTitle for clickable cards
- [ ] set 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.
jsx
// 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
, your code MUST use
. Period.