Spacing
VibeUI uses a 4px base grid. All spacing values are multiples of 4. Space tokens are defined as CSS custom properties.
Space Scale
Token Value Name Use cases
--space-1 4px xs Icon-to-label gap, tight inline spacing
--space-2 8px sm Between related elements (label + input gap, button gap)
--space-3 12px md Card internal padding, row gaps, section gaps
--space-4 16px lg Large card padding, section padding
--space-5 20px xl Panel padding (when generous), between sections
--space-6 24px 2xl Content blocks, large section separation
--space-8 32px 3xl Empty-state vertical padding
Anatomy of a Panel — Space Allocation
┌─────────────────────────────────────────────┐
│ panel-header (padding: 8px 12px) │ ← --space-2 vertical, --space-3 horizontal
│─────────────────────────────────────────────│ border: 1px solid --border-color
│ panel-body (padding: 8px 12px) │ ← same as header
│ │
│ ┌─────────────────────────────────────┐ │
│ │ panel-card (padding: 12px) │ │ ← --space-3 all sides
│ │ │ │
│ │ card-row (gap: 8px) │ │ ← --space-2 between elements
│ │ card-row (margin-bottom: 8px) │ │ ← --space-2 between rows
│ └─────────────────────────────────────┘ │
│ (gap between cards: 8px) │ ← --space-2
│ ┌─────────────────────────────────────┐ │
│ │ panel-card │ │
│ └─────────────────────────────────────┘ │
│─────────────────────────────────────────────│ border: 1px solid --border-color
│ panel-footer (padding: 8px 12px) │ ← --space-2 vertical, --space-3 horizontal
└─────────────────────────────────────────────┘
Component-Level Spacing Guide
Buttons
panel-btn-xs: padding 2px 8px gap 4px
panel-btn-sm: padding 4px 10px gap 6px
panel-btn: padding 5px 12px gap 6px (default)
panel-btn-lg: padding 8px 18px gap 8px
Button groups
// Inline button row — 6px gap
<div style={{ display: "flex", gap: 6 }}>
<button className="panel-btn panel-btn-secondary">Cancel</button>
<button className="panel-btn panel-btn-primary">Save</button>
</div>
Cards in body
// Cards stacked vertically — 8px margin-bottom
<div className="panel-card" style={{ marginBottom: 8 }}>...</div>
<div className="panel-card" style={{ marginBottom: 8 }}>...</div>
// Or use gap in a flex column
<div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
<div className="panel-card">...</div>
<div className="panel-card">...</div>
</div>
Label → Input → Button stack
<div className="panel-card" style={{ marginBottom: 10 }}>
<div className="panel-label">Field Name</div> {/* label */}
<input className="panel-input panel-input-full" {/* input — 8px below label via margin-bottom: 4px from .panel-label */}
style={{ marginBottom: 8 }} />
<button className="panel-btn panel-btn-primary">Submit</button>
</div>
Inline row items
// Tight: icon next to label
<span style={{ display: "flex", alignItems: "center", gap: "var(--space-1)" }}>
<Icon name="check" size={12} />
<span>Verified</span>
</span>
// Normal: label + value pairs
<div style={{ display: "flex", alignItems: "center", gap: "var(--space-2)" }}>
<span className="panel-label">Status</span>
<span className="panel-tag panel-tag-success">Active</span>
</div>
Stats Grid Spacing
// panel-stats uses gap: 8px by default
<div className="panel-stats">
<div className="panel-stat"> ... </div> {/* flex: 1 each */}
<div className="panel-stat"> ... </div>
</div>
// 3-column grid
<div className="panel-stats-grid-3">
<div className="panel-stat"> ... </div>
<div className="panel-stat"> ... </div>
<div className="panel-stat"> ... </div>
</div>
Empty State Spacing
// panel-empty: padding 40px 20px
<div className="panel-empty">No items found.</div>
// Custom empty state — stick to 32px top/bottom
<div style={{ textAlign: "center", padding: "32px 20px", color: "var(--text-muted)" }}>
...
</div>
Margin vs Padding
| Situation | Use | Why |
|---|---|---|
| Inside a card/section | padding |
Owns the space |
| Between stacked cards | marginBottom on card |
Separation between siblings |
| Inside flex/grid gap | gap |
Cleaner than margins |
| Around a progress bar | marginTop: 6 |
Sub-element internal spacing |
| Before a button in a card | marginTop: 8 |
Separates from above content |
Rules
Do
gap: 8 // 2×4 grid
padding: 12 // 3×4 grid
marginBottom: 8
style={{ gap: "var(--space-2)" }} // explicit token
Don’t
padding: 10 // not on the 4px grid
marginBottom: 6 // ok sometimes but prefer 8
padding: "3px 7px" // off-grid
gap: 14 // off-grid; use 12 or 16