omverse-ui

Menu

ComponentsExamplesGitHub

Getting started

IntroductionInstallationThemingDesign tokensDark mode

Form

ButtonInputSelectCheckboxRadioSwitchSlidernewDatePickernew

Display

AvatarBadgeCardChipAccordionProgressDivider

Navigation

NavbarBreadcrumbTabsPaginationStepper

Overlay

DialogTooltipToast

Other

IconIconButtonSpinner
ComponentsDisplayCard

Card

A surface for grouping related content. 6 variants with support for media, interactive states, selected state, and composable header/body/footer.

6 variantsInteractiveMediaSelected stateOverlay

Variants

Live preview

elevated (default), filled, outlined, ghost, gradient — all support hover states

Elevated

Shadow + hover lift

Filled

Tonal background

Outlined

Border highlight

Ghost

Dashed border

Gradient

Brand colors

App.tsx
tsx
1import { Card, CardBody } from 'omverse-ui'
2 
3<Card variant="elevated" style={{ width: 176 }}>
4 <CardBody>
5 <p>Elevated</p>
6 <p style={{ opacity: 0.6, marginTop: 4 }}>Shadow + hover lift</p>
7 </CardBody>
8</Card>
9 
10<Card variant="filled" style={{ width: 176 }}>
11 <CardBody>
12 <p>Filled</p>
13 <p style={{ opacity: 0.6, marginTop: 4 }}>Tonal background</p>
14 </CardBody>
15</Card>
16 
17<Card variant="outlined" style={{ width: 176 }}>
18 <CardBody>
19 <p>Outlined</p>
20 <p style={{ opacity: 0.6, marginTop: 4 }}>Border highlight</p>
21 </CardBody>
22</Card>
23 
24<Card variant="ghost" style={{ width: 176 }}>
25 <CardBody>
26 <p>Ghost</p>
27 <p style={{ opacity: 0.6, marginTop: 4 }}>Dashed border</p>
28 </CardBody>
29</Card>
30 
31<Card variant="gradient" style={{ width: 176 }}>
32 <CardBody>
33 <p>Gradient</p>
34 <p style={{ opacity: 0.8, marginTop: 4 }}>Brand colors</p>
35 </CardBody>
36</Card>

Glass variant

Live preview

Use on colored backgrounds to reveal the frosted-glass blur

Glass card

Frosted glass effect

Another glass

Works on any background

App.tsx
tsx
1import { Card, CardBody } from 'omverse-ui'
2 
3{/* Glass needs a colored backdrop to show the frosted effect */}
4<div style={{
5 background: 'linear-gradient(135deg, #6366F1, #A855F7)',
6 padding: 32,
7 borderRadius: 16,
8 display: 'flex',
9 gap: 16,
10}}>
11 <Card variant="glass" style={{ width: 208 }}>
12 <CardBody>
13 <p>Glass card</p>
14 <p style={{ opacity: 0.8, marginTop: 4 }}>Frosted glass effect</p>
15 </CardBody>
16 </Card>
17 
18 <Card variant="glass" style={{ width: 208 }}>
19 <CardBody>
20 <p>Another glass</p>
21 <p style={{ opacity: 0.8, marginTop: 4 }}>Works on any background</p>
22 </CardBody>
23 </Card>
24</div>

With media + header + footer

Live preview

CardMedia, CardHeader (with action), CardBody and CardFooter compose the full card

Mountain Trek

Mountain Trek

Himalayas · 5 days

A 5-day guided trek through the Himalayas with expert guides.

Available
Campaign

Launch campaign

Marketing · 3 days left

Active

Drive awareness for the new product launch across all channels.

App.tsx
tsx
1import { Avatar, Badge, Button, Card, CardBody, CardFooter, CardHeader, CardMedia } from 'omverse-ui'
2 
3{/* Card with image overlay content */}
4<Card variant="elevated" style={{ width: 208 }} interactive>
5 <CardMedia
6 src="https://picsum.photos/seed/mountain/400/200"
7 alt="Mountain Trek"
8 height={160}
9 overlay
10 overlayContent={
11 <>
12 <p style={{ fontWeight: 600 }}>Mountain Trek</p>
13 <p style={{ opacity: 0.8, fontSize: 12 }}>Himalayas · 5 days</p>
14 </>
15 }
16 />
17 <CardBody>
18 <p style={{ fontSize: 13, color: 'var(--color-text-secondary)' }}>
19 A 5-day guided trek through the Himalayas with expert guides.
20 </p>
21 </CardBody>
22 <CardFooter divider style={{ justifyContent: 'space-between' }}>
23 <Badge color="success" variant="tonal">Available</Badge>
24 <Button size="sm" variant="filled">Book now</Button>
25 </CardFooter>
26</Card>
27 
28{/* Card with header action */}
29<Card variant="elevated" style={{ width: 256 }} interactive>
30 <CardMedia
31 src="https://picsum.photos/seed/launch/400/140"
32 alt="Campaign"
33 height={140}
34 />
35 <CardHeader
36 title="Launch campaign"
37 subtitle="Marketing · 3 days left"
38 action={<Badge color="success" variant="tonal">Active</Badge>}
39 />
40 <CardBody>
41 <p style={{ fontSize: 13, color: 'var(--color-text-secondary)' }}>
42 Drive awareness for the new product launch across all channels.
43 </p>
44 </CardBody>
45 <CardFooter divider style={{ justifyContent: 'space-between' }}>
46 <div style={{ display: 'flex' }}>
47 <Avatar name="John Doe" size="xs" style={{ boxShadow: '0 0 0 2px var(--color-background)' }} />
48 <Avatar name="Alice Wang" size="xs" color="secondary" style={{ boxShadow: '0 0 0 2px var(--color-background)', marginLeft: -8 }} />
49 </div>
50 <div style={{ display: 'flex', gap: 8 }}>
51 <Button size="sm" variant="text">View</Button>
52 <Button size="sm" variant="filled">Edit</Button>
53 </div>
54 </CardFooter>
55</Card>

Horizontal layout

Live preview

Set the card to flex-row and give CardMedia a fixed width for side-by-side layouts

Midnight Rain

Midnight Rain

Taylor Swift · 3:54

App.tsx
tsx
1import { Button, Card, CardBody, CardHeader, CardMedia } from 'omverse-ui'
2 
3<Card variant="elevated" style={{ width: 320, display: 'flex', flexDirection: 'row', overflow: 'hidden' }} interactive>
4 <CardMedia
5 src="https://picsum.photos/seed/music/200/200"
6 alt="Midnight Rain"
7 style={{ width: 96, flexShrink: 0, borderRadius: '12px 0 0 12px', height: 'auto', alignSelf: 'stretch' }}
8 />
9 <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
10 <CardHeader title="Midnight Rain" subtitle="Taylor Swift · 3:54" />
11 <CardBody>
12 <Button size="sm" variant="filled" leadingIcon="play">Play</Button>
13 </CardBody>
14 </div>
15</Card>

Selected state — action cards

Live preview

Combine interactive + selected + asButton to create fully-clickable selectable cards

App.tsx
tsx
1import { useState } from 'react'
2import { Badge, Card, CardBody } from 'omverse-ui'
3 
4const [selected, setSelected] = useState('template')
5 
6const ICONS = { scratch: 'file-text', template: 'bookmark', import: 'upload' } as const
7 
8const options = [
9 { id: 'scratch', label: 'From scratch', desc: 'Start fresh' },
10 { id: 'template', label: 'Template', desc: 'Use a preset' },
11 { id: 'import', label: 'Import', desc: 'Upload file' },
12]
13 
14<div style={{ display: 'flex', gap: 16 }}>
15 {options.map(opt => (
16 <Card
17 key={opt.id}
18 variant="outlined"
19 interactive
20 selected={selected === opt.id}
21 onClick={() => setSelected(opt.id)}
22 asButton
23 style={{ width: 176, textAlign: 'center' }}
24 >
25 <CardBody style={{ paddingTop: 20, paddingBottom: 20 }}>
26 <i className={`ti ti-${ICONS[opt.id]}`} style={{ fontSize: 24 }} aria-hidden="true" />
27 <p style={{ fontSize: 14, fontWeight: 500, marginTop: 8 }}>{opt.label}</p>
28 <p style={{ fontSize: 12, color: 'var(--color-text-secondary)', marginTop: 4 }}>{opt.desc}</p>
29 {selected === opt.id && (
30 <Badge color="default" variant="tonal" style={{ marginTop: 8 }}>Selected</Badge>
31 )}
32 </CardBody>
33 </Card>
34 ))}
35</div>

Stat cards

Live preview

Cards as data containers — no CardBody needed when using padding directly on Card

Total revenue

$48.2k

+12.5%

Active users

2,841

+8.2%

Bounce rate

24.1%

-3.1%

App.tsx
tsx
1import { Card } from 'omverse-ui'
2 
3<div style={{ display: 'flex', gap: 16 }}>
4 <Card variant="outlined" style={{ width: 176, padding: 16 }}>
5 <p style={{ fontSize: 12, color: 'var(--color-text-secondary)' }}>Total revenue</p>
6 <p style={{ fontSize: 22, fontWeight: 500, color: 'var(--color-text-primary)', marginTop: 4 }}>$48.2k</p>
7 <p style={{ fontSize: 12, fontWeight: 500, marginTop: 8, color: '#10B981' }}>+12.5%</p>
8 </Card>
9 
10 <Card variant="outlined" style={{ width: 176, padding: 16 }}>
11 <p style={{ fontSize: 12, color: 'var(--color-text-secondary)' }}>Active users</p>
12 <p style={{ fontSize: 22, fontWeight: 500, color: 'var(--color-text-primary)', marginTop: 4 }}>2,841</p>
13 <p style={{ fontSize: 12, fontWeight: 500, marginTop: 8, color: '#10B981' }}>+8.2%</p>
14 </Card>
15 
16 <Card variant="outlined" style={{ width: 176, padding: 16 }}>
17 <p style={{ fontSize: 12, color: 'var(--color-text-secondary)' }}>Bounce rate</p>
18 <p style={{ fontSize: 22, fontWeight: 500, color: 'var(--color-text-primary)', marginTop: 4 }}>24.1%</p>
19 <p style={{ fontSize: 12, fontWeight: 500, marginTop: 8, color: '#EF4444' }}>-3.1%</p>
20 </Card>
21</div>

Profile card

Live preview

CardMedia + Avatar with negative margin creates a cover-photo-to-avatar overlap

Cover

John Doe

Product Designer

128

Projects

4.2k

Followers

98%

Rating

App.tsx
tsx
1import { Avatar, Card, CardBody, CardFooter, CardMedia } from 'omverse-ui'
2 
3<Card variant="outlined" style={{ width: 208, overflow: 'hidden' }}>
4 <CardMedia src="https://picsum.photos/seed/profile/400/120" alt="Cover" height={120} />
5 <div style={{ display: 'flex', justifyContent: 'center', marginTop: -28 }}>
6 <Avatar name="John Doe" size="lg" style={{ boxShadow: '0 0 0 4px var(--color-background)' }} />
7 </div>
8 <CardBody style={{ textAlign: 'center', paddingTop: 8, paddingBottom: 0 }}>
9 <p style={{ fontSize: 14, fontWeight: 600 }}>John Doe</p>
10 <p style={{ fontSize: 12, color: 'var(--color-text-secondary)', marginTop: 2 }}>Product Designer</p>
11 </CardBody>
12 <CardFooter divider style={{ justifyContent: 'space-around', padding: 0, marginTop: 12 }}>
13 {[['128', 'Projects'], ['4.2k', 'Followers'], ['98%', 'Rating']].map(([val, lbl]) => (
14 <div key={lbl} style={{ flex: 1, textAlign: 'center', padding: '12px 0' }}>
15 <p style={{ fontSize: 13, fontWeight: 600 }}>{val}</p>
16 <p style={{ fontSize: 12, color: 'var(--color-text-disabled)' }}>{lbl}</p>
17 </div>
18 ))}
19 </CardFooter>
20</Card>

Props

PropTypeDefaultDescription
variant'elevated' | 'filled' | 'outlined' | 'ghost' | 'gradient' | 'glass''elevated'Visual style of the card
interactivebooleanfalseAdds hover / focus / active states
selectedbooleanfalseShows a selected ring or border
asButtonbooleanfalseRenders as a <button> for fully-clickable cards
radius'none' | 'sm' | 'md' | 'lg' | 'full''md'Border radius