Frame
A box that holds its shape, for images, video and previews.
SourcePackage @weft-js/warpPlayground
Preview
tsx
import { Frame, Grid, Text } from '@weft-js/warp'export function Ratios() { return ( <Grid min="xs" cols={6} gap="related"> {RATIOS.map(ratio => ( <Frame key={ratio} ratio={ratio}> <Text role="caption" subtle>{ratio}</Text> </Frame> ))} </Grid> )}const min = 60_000const RATIOS = ['21:9', '16:9', '3:2', '4:3', 'square', '3:4'] as constInstallation
npm install @weft-js/warpUsage
tsx
import { Frame } from '@weft-js/warp'<Grid min="xs" cols={6} gap="related"> {RATIOS.map(ratio => ( <Frame key={ratio} ratio={ratio}> <Text role="caption" subtle>{ratio}</Text> </Frame> ))}</Grid>Media crops to fit
An image, video, canvas or SVG directly inside fills the frame and crops.
tsx
import { Frame, Grid } from '@weft-js/warp'export function Media() { return ( <Grid min="xs" cols={3} gap="related"> <Frame>{art('1', '3')}</Frame> <Frame ratio="square">{art('2', '5')}</Frame> <Frame ratio="3:4">{art('4', '7')}</Frame> </Grid> )}const min = 60_000const art = (a: string, b: string) => ( <svg viewBox="0 0 320 180" preserveAspectRatio="xMidYMid slice" aria-hidden="true"> <rect width="320" height="180" fill={`var(--warp-color-data-${a})`} /> <circle cx="96" cy="150" r="130" fill={`var(--warp-color-data-${b})`} /> <rect x="176" y="36" width="104" height="108" rx="8" fill="var(--warp-color-surface)" opacity="0.85" /> </svg>)Deploy previews
Use ratio to give each preview the same shape, here 16:9.
tsx
import { Card, Frame, Grid, Stack, Text } from '@weft-js/warp'export function Previews() { return ( <Grid min="sm" cols={3} gap="related"> {DEPLOYS.slice(0, 3).map((d, n) => ( <Card key={d.id}> <Stack gap="related"> <Frame ratio="16:9">{art(String(n + 1), String(n + 4))}</Frame> <Stack gap="hair"> <Text role="heading">{d.project}</Text> <Text role="caption" subtle>{d.message}</Text> </Stack> </Stack> </Card> ))} </Grid> )}const DEPLOYS = [ { id: 'd-4821', project: 'storefront', branch: 'main', commit: '9f3ac21', message: 'Cache product images at the edge', author: 'Priya Raman', status: 'Live', minutes: 2, at: '2026-10-31T16:42' }, { id: 'd-4820', project: 'search-api', branch: 'ranking-v2', commit: '1be07d4', message: 'Rank exact matches first', author: 'Lena Fischer', status: 'Building', minutes: 6, at: '2026-10-31T16:10' }, { id: 'd-4819', project: 'mobile-bff', branch: 'main', commit: 'c44e190', message: 'Retry timed out upstream calls', author: 'Sam Okafor', status: 'Failed', minutes: 4, at: '2026-10-31T15:27' }, { id: 'd-4818', project: 'checkout', branch: 'main', commit: '70d2fa8', message: 'Add Apple Pay to the last step', author: 'Tomás Oliveira', status: 'Live', minutes: 3, at: '2026-10-31T14:03' }, { id: 'd-4817', project: 'edge-cache', branch: 'main', commit: 'e81b6c2', message: 'Lower the stale window to 30s', author: 'Jun Tanaka', status: 'Live', minutes: 1, at: '2026-10-31T11:55' }, { id: 'd-4816', project: 'billing', branch: 'main', commit: '2ad9e03', message: 'Prorate seats on plan change', author: 'Mara Lindqvist', status: 'Live', minutes: 3, at: '2026-10-29T17:20' },]const min = 60_000const change = (a: number, b: number) => `${a >= b ? '+' : ''}${((a - b) / b * 100).toFixed(1)}%`const art = (a: string, b: string) => ( <svg viewBox="0 0 320 180" preserveAspectRatio="xMidYMid slice" aria-hidden="true"> <rect width="320" height="180" fill={`var(--warp-color-data-${a})`} /> <circle cx="96" cy="150" r="130" fill={`var(--warp-color-data-${b})`} /> <rect x="176" y="36" width="104" height="108" rx="8" fill="var(--warp-color-surface)" opacity="0.85" /> </svg>)When to use
Use it for
- Images and video that must not shift the page as they load
- Thumbnails of mixed sizes that should line up
Reach for something else
- Card, when it needs a surface and padding
Playground
import { Frame } from '@weft-js/warp'<Frame> <img src="/preview.png" alt="" /></Frame>Accessibility
- Frame draws nothing itself, so give an image its
altas usual.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
children | unknown | — | What it contains. |
as | "div" | "section" | "article" | "main" | "header" | "footer" | "nav" | "… | — | The element it renders as. |
gap | "section" | "none" | "hair" | "tight" | "related" | "group" | "page" | — | The space between children, from warp's space scale. |
ratio | "square" | "4:3" | "3:2" | "16:9" | "21:9" | "3:4" | "9:16" | '16:9' | Width to height. 16:9 by default. |