Skip to main content

Box

🌓Dark Mode Compatible

A flexible, polymorphic container component that serves as the foundation for layout and spacing in the Lufa Design System.

Overview​

Use Box when you need…

  • A universal layout primitive with utility-based spacing props (padding, margin)
  • Semantic HTML elements via the polymorphic as prop (section, article, header, etc.)
  • Quick prototyping with background colors, borders, and border radius
  • A performance-optimized container (uses CSS classes, not inline styles)
  • Token-based design values that automatically adapt to light and dark themes
Live demoInteractive
Basic Box

Anatomy​

The Box component is a single container element with configurable spacing and visual properties.

  • Container: Single element (default div, customizable via as prop)
  • Padding: Inner spacing between border and content (supports all directions)
  • Margin: Outer spacing between Box and adjacent elements (supports all directions)
  • Border: Optional border with customizable width, color, and radius
  • Background: Optional semantic background color from design tokens
  • Display: CSS display property (block, flex, grid, and more)

Usage​

import { Box } from '@grasdouble/lufa_design-system';

export function BasicBox() {
return (
<>
<Box padding="default">Content</Box>
<Box padding="comfortable" background="surface" borderRadius="medium" borderWidth="thin" borderColor="default">
Card content
</Box>
</>
);
}
import { Box } from '@grasdouble/lufa_design-system';

export function SemanticSection() {
return (
<Box as="section" padding="spacious" aria-labelledby="section-title">
<h2 id="section-title">Section title</h2>
<Box display="flex" style={{ gap: '16px' }}>
<Box>Item 1</Box>
<Box>Item 2</Box>
</Box>
</Box>
);
}

Props​

PropTypeDefaultDescription
as'div' | 'section' | 'article' | 'header' | 'footer' | 'main' | 'nav' | 'aside''div'HTML element to render
padding'none' | 'tight' | 'compact' | 'default' | 'comfortable' | 'spacious'undefinedPadding on all sides
paddingX'none' | 'tight' | 'compact' | 'default' | 'comfortable' | 'spacious'undefinedHorizontal padding (left + right)
paddingY'none' | 'tight' | 'compact' | 'default' | 'comfortable' | 'spacious'undefinedVertical padding (top + bottom)
paddingTop'none' | 'tight' | 'compact' | 'default' | 'comfortable' | 'spacious'undefinedPadding top only
paddingRight'none' | 'tight' | 'compact' | 'default' | 'comfortable' | 'spacious'undefinedPadding right only
paddingBottom'none' | 'tight' | 'compact' | 'default' | 'comfortable' | 'spacious'undefinedPadding bottom only
paddingLeft'none' | 'tight' | 'compact' | 'default' | 'comfortable' | 'spacious'undefinedPadding left only
margin'none' | 'tight' | 'compact' | 'default' | 'comfortable' | 'spacious'undefinedMargin on all sides
marginX'none' | 'tight' | 'compact' | 'default' | 'comfortable' | 'spacious'undefinedHorizontal margin (left + right)
marginY'none' | 'tight' | 'compact' | 'default' | 'comfortable' | 'spacious'undefinedVertical margin (top + bottom)
marginTop'none' | 'tight' | 'compact' | 'default' | 'comfortable' | 'spacious'undefinedMargin top only
marginRight'none' | 'tight' | 'compact' | 'default' | 'comfortable' | 'spacious'undefinedMargin right only
marginBottom'none' | 'tight' | 'compact' | 'default' | 'comfortable' | 'spacious'undefinedMargin bottom only
marginLeft'none' | 'tight' | 'compact' | 'default' | 'comfortable' | 'spacious'undefinedMargin left only
background'page' | 'surface' | 'success' | 'error' | 'warning' | 'info' | 'overlay' | 'on-primary' | 'on-secondary' | 'on-success' | 'on-error' | 'on-warning' | 'on-info'undefinedBackground color using semantic tokens
borderRadius'none' | 'small' | 'default' | 'medium' | 'large' | 'full'undefinedBorder radius (rounded corners)
borderWidth'none' | 'thin' | 'medium' | 'thick'undefinedBorder width on all sides
borderColor'default' | 'strong' | 'success' | 'error' | 'warning' | 'info'undefinedBorder color using semantic tokens
display'block' | 'inline-block' | 'flex' | 'inline-flex' | 'grid' | 'none'undefinedCSS display property
classNamestringundefinedAdditional CSS classes
childrenReactNodeundefinedChild elements to render inside the Box

Also supports all standard HTML attributes for the underlying element (for example id, role, aria-*, data-*, style, and event handlers).

Spacing prop priority: individual sides override axis props, which override all-sides props.

import { Box } from '@grasdouble/lufa_design-system';

export function SpacingPriority() {
return (
<Box padding="default" paddingX="spacious" paddingTop="tight">
Content
</Box>
);
}

Accessibility​

Box is a non-interactive container by default. Use semantic elements and ARIA attributes when they add meaning, and avoid making containers focusable unless required.

import { Box } from '@grasdouble/lufa_design-system';

export function LandmarkExample() {
return (
<Box as="nav" aria-label="Primary">
<a href="/">Home</a>
<a href="/about">About</a>
</Box>
);
}

Theming & Tokens​

Box props map to design tokens that stay consistent across themes.

  • Spacing tokens: none (0px), tight (4px), compact (8px), default (16px), comfortable (24px), spacious (32px)
  • Background tokens: page, surface, success, error, warning, info, overlay, on-primary, on-secondary, on-success, on-error, on-warning, on-info
  • Border tokens: radius none, small, default, medium, large, full; width none, thin, medium, thick; color default, strong, success, error, warning, info

All semantic background tokens are tested in light and dark themes to meet WCAG 2.1 AA contrast requirements for text.

Do / Don’t​

Do
  • Use semantic HTML via the as prop for landmarks and sections
  • Pair borderWidth with borderColor when you want a visible border
  • Use spacing tokens consistently to keep visual rhythm
  • Prefer Box over custom divs for consistent token usage
Don't
  • Use Box for everything when plain semantic HTML is enough
  • Set borderWidth without borderColor
  • Hardcode spacing values in style when tokens are available
  • Make non-interactive Boxes focusable without a reason
  • Stack - Vertical or horizontal spacing layout (builds on Box with display="flex" and gap)
  • Grid - Grid layout primitive (builds on Box with display="grid")
  • Flex - Flexbox layout primitive (builds on Box with display="flex")
  • Container - Max-width centered container (builds on Box with responsive widths)
  • Text - Typography component (can be composed with Box for styled text blocks)
  • Divider - Visual separator (can be used within Box for content sections)