Theme UI provides a variety of UI components for building complete interfaces.
The Button component is a primitive button with theme-aware variants.
import { Button } from '@theme-ui/components'
<Button>Click me</Button>
variant
string
default:"'primary'"
Button variant from theme.buttons
Button accepts all standard HTML button attributes and Box props.
Default Styles
{
appearance: 'none',
display: 'inline-block',
textAlign: 'center',
lineHeight: 'inherit',
textDecoration: 'none',
fontSize: 'inherit',
px: 3,
py: 2,
color: 'white',
bg: 'primary',
border: 0,
borderRadius: 4
}
Examples
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button disabled>Disabled</Button>
The Link component is an anchor element with theme integration.
import { Link } from '@theme-ui/components'
<Link href="/about">About</Link>
variant
string
default:"'styles.a'"
Link variant from theme.links
Link accepts all standard HTML anchor attributes and Box props.
Examples
<Link href="https://theme-ui.com">External Link</Link>
<Link href="/docs" sx={{ color: 'primary' }}>Docs</Link>
NavLink
The NavLink component is designed for navigation links with active states.
import { NavLink } from '@theme-ui/components'
<NavLink href="/" className="active">Home</NavLink>
Link variant from theme.links
Default Styles
{
color: 'inherit',
textDecoration: 'none',
fontWeight: 'bold',
display: 'inline-block',
'&:hover, &:focus, &.active': {
color: 'primary'
}
}
Examples
<Flex as="nav" sx={{ gap: 3 }}>
<NavLink href="/">Home</NavLink>
<NavLink href="/about">About</NavLink>
<NavLink href="/contact">Contact</NavLink>
</Flex>
The Card component is a flexible container for content.
import { Card } from '@theme-ui/components'
<Card>
<Heading>Card Title</Heading>
<Text>Card content</Text>
</Card>
variant
string
default:"'primary'"
Card variant from theme.cards
Card accepts all Box props.
Examples
<Card p={4} bg="muted">
<Heading mb={2}>Feature Card</Heading>
<Paragraph>Description of the feature</Paragraph>
<Button mt={3}>Learn More</Button>
</Card>
The Badge component displays small labels or tags.
import { Badge } from '@theme-ui/components'
variant
string
default:"'primary'"
Badge variant from theme.badges
Default Styles
{
display: 'inline-block',
verticalAlign: 'baseline',
fontSize: 0,
fontWeight: 'bold',
whiteSpace: 'nowrap',
px: 1,
borderRadius: 2,
color: 'white',
bg: 'primary'
}
Examples
<Badge>New</Badge>
<Badge variant="secondary">Beta</Badge>
<Badge sx={{ bg: 'accent' }}>Hot</Badge>
The Alert component displays messages and notifications.
import { Alert } from '@theme-ui/components'
<Alert>This is an alert message</Alert>
variant
string
default:"'primary'"
Alert variant from theme.alerts
Default Styles
{
display: 'flex',
alignItems: 'center',
px: 3,
py: 2,
fontWeight: 'bold',
color: 'white',
bg: 'primary',
borderRadius: 4
}
Examples
<Alert variant="primary">Info message</Alert>
<Alert variant="success">Success message</Alert>
<Alert variant="error">Error message</Alert>
The Avatar component displays user profile images.
import { Avatar } from '@theme-ui/components'
<Avatar src="/avatar.jpg" />
size
number | string
default:"48"
Width and height of the avatar
Image variant from theme.images
Avatar accepts all standard HTML img attributes and Box props.
Default Styles
Examples
<Avatar src="/user.jpg" size={64} />
<Avatar src="/profile.jpg" size={32} />
Spinner
The Spinner component displays a loading indicator.
import { Spinner } from '@theme-ui/components'
Size of the spinner in pixels
Width of the spinner stroke
title
string
default:"'Loading'"
Accessible title for the spinner
Duration of the animation in milliseconds
Default Styles
{
color: 'primary',
overflow: 'visible'
}
Examples
<Spinner />
<Spinner size={64} />
<Spinner size={32} strokeWidth={2} />
<Spinner title="Loading content" duration={1000} />
Progress
The Progress component displays a horizontal progress bar.
import { Progress } from '@theme-ui/components'
<Progress max={100} value={75} />
Default Styles
{
display: 'block',
width: '100%',
height: '4px',
margin: 0,
padding: 0,
overflow: 'hidden',
appearance: 'none',
color: 'primary',
bg: 'gray',
borderRadius: 9999,
border: 'none'
}
Examples
<Progress max={100} value={50} />
<Progress max={100} value={75} sx={{ color: 'success' }} />
The Donut component displays a circular progress chart.
import { Donut } from '@theme-ui/components'
size
string | number
default:"128"
Size of the donut chart
Width of the donut stroke
Accessible title for the chart
Default Styles
Examples
<Donut value={0.75} title="75% complete" />
<Donut value={60} min={0} max={100} size={96} />
<Donut value={0.5} sx={{ color: 'success' }} />
IconButton
The IconButton component is a transparent button for SVG icons.
import { IconButton } from '@theme-ui/components'
<IconButton aria-label="Menu">
<MenuIcon />
</IconButton>
size
number | string
default:"32"
Width and height of the button
Button variant from theme.buttons
Default Styles
{
appearance: 'none',
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
padding: 1,
width: 32,
height: 32,
color: 'inherit',
bg: 'transparent',
border: 'none',
borderRadius: 4
}
Examples
<IconButton aria-label="Settings">
<SettingsIcon />
</IconButton>
<IconButton size={48} aria-label="Close">
<CloseIcon />
</IconButton>
The Close component is a button with a close (×) icon.
import { Close } from '@theme-ui/components'
Button variant from theme.buttons
Examples
<Close onClick={handleClose} />
<Close size={24} />
Message
The Message component is a styled box for callouts and inline messages.
import { Message } from '@theme-ui/components'
<Message>This is an informational message</Message>
Message variant from theme.messages
Default Styles
{
padding: 3,
paddingLeft: (t) => t.space[3] - t.space[1],
borderLeftWidth: (t) => t.space[1],
borderLeftStyle: 'solid',
borderLeftColor: 'primary',
borderRadius: 4,
bg: 'highlight'
}
Examples
<Message>Info message with left border</Message>
<Message variant="warning">Warning message</Message>
Divider
The Divider component creates a horizontal rule.
import { Divider } from '@theme-ui/components'
Divider accepts all Box props and uses theme.styles.hr by default.
Default Styles
{
color: 'gray',
m: 0,
my: 2,
border: 0,
borderBottom: '1px solid'
}
Examples
<Divider />
<Divider my={4} />
<Divider sx={{ borderColor: 'primary' }} />
The Image component is a responsive image element.
import { Image } from '@theme-ui/components'
<Image src="/photo.jpg" alt="Description" />
Image variant from theme.images
Image accepts all standard HTML img attributes and Box props.
Default Styles
{
maxWidth: '100%',
height: 'auto'
}
Examples
<Image src="/photo.jpg" alt="Photo" />
<Image src="/banner.jpg" sx={{ borderRadius: 4 }} />
The Embed component creates a responsive iframe container.
import { Embed } from '@theme-ui/components'
<Embed src="https://www.youtube.com/embed/..." />
URL of the embedded content
Aspect ratio of the embed
Examples
<Embed src="https://www.youtube.com/embed/dQw4w9WgXcQ" />
<Embed src="https://player.vimeo.com/video/..." ratio={4/3} />
Complete UI Example
<Container py={4}>
<Flex sx={{ justifyContent: 'space-between', alignItems: 'center', mb: 4 }}>
<Heading>Dashboard</Heading>
<Button>New Item</Button>
</Flex>
<Alert mb={3}>Welcome back! You have 3 new notifications.</Alert>
<Grid columns={[1, 2, 3]} gap={4}>
<Card p={4}>
<Flex sx={{ alignItems: 'center', mb: 3 }}>
<Avatar src="/user.jpg" size={48} />
<Box ml={3}>
<Heading as="h3">John Doe</Heading>
<Badge>Admin</Badge>
</Box>
</Flex>
<Divider />
<Progress max={100} value={75} my={3} />
<Text>Profile completion: 75%</Text>
</Card>
<Card p={4}>
<Heading as="h3" mb={3}>Activity</Heading>
<Donut value={0.65} size={96} />
</Card>
<Card p={4}>
<Flex sx={{ justifyContent: 'space-between', mb: 3 }}>
<Heading as="h3">Status</Heading>
<IconButton aria-label="Refresh">
<RefreshIcon />
</IconButton>
</Flex>
<Spinner />
</Card>
</Grid>
</Container>