This document provides practical examples of implementing the new UI primitives in existing components.
Before:
<Box css={panelStyles(theme)} className="setup-panel-container">
<div className="scrollable-content">
<Box className="setup-container">
<Typography variant="h6" sx={{ mb: 1.5 }}>Title</Typography>
<Typography variant="subtitle2" className="setup-list-title">
Subtitle
</Typography>
<Box><ol>...</ol></Box>
</Box>
</div>
</Box>
// CSS
const panelStyles = css({
display: "flex",
flexDirection: "column",
padding: "0.75em",
".setup-container": {
padding: "1em",
borderRadius: "12px"
}
});After:
import { FlexColumn, Card } from "../ui_primitives";
<FlexColumn gap={0} padding={3} fullHeight>
<div className="scrollable-content">
<Card padding="comfortable">
<FlexColumn gap={2}>
<Typography variant="h6">Title</Typography>
<FlexColumn gap={1}>
<Typography variant="subtitle2">Subtitle</Typography>
<ol>...</ol>
</FlexColumn>
</FlexColumn>
</Card>
</div>
</FlexColumn>
// Simplified CSS (no container styles needed)
const panelStyles = css({
height: "100%"
});Benefits:
- 40% less CSS code
- Self-documenting layout structure
- Type-safe padding/gap values
- Consistent spacing across theme
Before:
<Box className="panel-header">
<RocketLaunchIcon />
<Box>
<Typography sx={{ fontWeight: 600, fontSize: "1.1rem" }}>
Getting Started
</Typography>
<Typography sx={{ color: "text.secondary", fontSize: "0.85rem" }}>
Complete these steps
</Typography>
</Box>
</Box>
// CSS
".panel-header": {
display: "flex",
alignItems: "center",
gap: "0.75em",
marginBottom: "1em"
}After:
import { FlexRow, FlexColumn, Text, Caption } from "../ui_primitives";
<FlexRow gap={3} align="center" className="panel-header">
<RocketLaunchIcon />
<FlexColumn gap={0.5}>
<Text size="big" weight={600}>Getting Started</Text>
<Caption size="small">Complete these steps</Caption>
</FlexColumn>
</FlexRow>
// No CSS needed for layout!Benefits:
- No CSS required for layout
- Typography scales with theme
- Consistent size/color variants
- Easier to maintain
Before:
<Box sx={{ display: "flex", flexDirection: "column", gap: theme.spacing(2) }}>
<Item1 />
<Item2 />
<Item3 />
</Box>After:
<FlexColumn gap={2}>
<Item1 />
<Item2 />
<Item3 />
</FlexColumn>Before:
<Box sx={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
gap: theme.spacing(1.5)
}}>
<LeftContent />
<RightContent />
</Box>After:
<FlexRow gap={1.5} align="center" justify="space-between">
<LeftContent />
<RightContent />
</FlexRow>Before:
<Typography sx={{
fontSize: theme.fontSizeBig,
fontWeight: 600,
color: theme.vars.palette.primary.main
}}>
Important Text
</Typography>
<Typography sx={{
fontSize: theme.fontSizeSmall,
color: theme.vars.palette.text.secondary
}}>
Helper text
</Typography>After:
<Text size="big" weight={600} color="primary">
Important Text
</Text>
<Caption size="small" color="secondary">
Helper text
</Caption>Before:
<Box sx={{
padding: theme.spacing(2.5),
borderRadius: "8px",
border: `1px solid ${theme.vars.palette.divider}`,
backgroundColor: theme.vars.palette.background.paper
}}>
<Content />
</Box>After:
<Card variant="outlined" padding="normal">
<Content />
</Card>When refactoring a component:
-
Identify Patterns
- Find all
display: "flex"withflexDirection: "column"→ useFlexColumn - Find all
display: "flex"(horizontal) → useFlexRow - Find Typography with manual sizing/coloring → use
Text/Caption - Find Box with manual padding → use
Card/Container
- Find all
-
Import Primitives
import { FlexColumn, FlexRow, Card, Text, Caption } from "../ui_primitives";
-
Replace Patterns
- Use semantic names:
gap,padding,align,justify - Use theme-based values:
gap={2}instead ofgap: theme.spacing(2) - Use size variants:
size="big"instead offontSize: theme.fontSizeBig
- Use semantic names:
-
Clean Up CSS
- Remove redundant layout CSS
- Keep only custom styling (colors, borders, animations)
- Remove hardcoded spacing values
-
Test
- Visual inspection (does it look the same?)
- Unit tests (add if not exists)
- Typecheck passes
- Lint passes
- Use primitives for layout structure
- Use semantic padding variants:
"compact","normal","comfortable" - Use consistent gap values:
0.5,1,1.5,2,3,4 - Combine primitives:
<FlexColumn><FlexRow>...</FlexRow></FlexColumn>
- Don't nest too many primitives (keep it flat where possible)
- Don't mix primitives with manual flex CSS (pick one approach)
- Don't use hardcoded pixel values (use theme spacing)
- Don't override primitive styles with
sx(use props instead)
| Metric | Before | After | Improvement |
|---|---|---|---|
| Lines of code | 858 | 753 | -105 lines (12%) |
| CSS lines | 254 | 126 | -128 lines (50%) |
| Manual flex patterns | 23 | 0 | -23 patterns |
| Typography manual styling | 18 | 0 | -18 instances |
| Tests | 0 | 3 | +3 tests |
High Priority (similar patterns to examples):
- ActivityPanel
- TemplatesPanel
- ProviderSetupPanel
- WelcomePanel
Medium Priority (moderate complexity): 5. Node inspector panels 6. Settings dialogs 7. Modal components
Low Priority (already well-structured): 8. Header components 9. Button groups 10. Icon wrappers
See:
README.md- Complete primitive documentationEXAMPLES.md- More usage examplesSUMMARY.md- Overview and benefitsSetupPanel.tsx- Real refactored exampleGettingStartedPanel.tsx- Complex refactored example