Skip to main content

Cover

Every example on this page is live, drawn by the library's Storybook, where you can also change its props and see the result.

A picture in a fixed frame: a film's poster, a podcast's artwork, a dish's photo. The picture is cropped to fill the frame, never squashed, and shown in greys with a little extra contrast, which is how an e-ink frame shows it, so its shapes stay clear on the display.

When there is no picture, or it fails to load, the frame is outlined with a glyph in the middle instead, so a missing picture looks the same in every widget.

Import​

import { Cover } from "~lib/data-display/cover";

Props​

NameTypeRequiredDefaultDescription
srcstring | nullNoN/AThe picture's address. Leave it out, or pass null, when there is none
altstringNo""What the picture shows, for screen readers. Leave it out when text beside it says it
widthnumber | stringNoN/AWidth in pixels, or any CSS width such as "100%"
heightnumber | string | "fill"NoN/AHeight in pixels, any CSS height, or "fill" for the room its column leaves
aspectnumberNo1Width over height, used for the edge you leave out, such as 2 / 3 for a poster
radius"none" | "sm" | "md" | "lg" | "full"No"md"How rounded the corners are; "full" makes a circle of a square frame
fallbackIconNameNo"image"The Icon shown when there is no picture
fit"cover" | "contain"No"cover"Crop the picture to fill the frame, or show all of it at its own proportion
markIconNameNoN/AAn Icon in the corner saying what the picture is
tone"picture" | "ink"No"picture"Show the picture as it is, or "ink" to draw only its shape in ink
invertboolean | "light" | "dark"NofalseDraw the picture as its negative: on every frame, or only on a light or only on a dark one
rotate0 | 90 | 180 | 270No0Turn the picture, its placeholder and its mark clockwise inside the frame

Give width and height for an exact box, or one of them and aspect. With only one edge and no aspect the frame is square. With neither edge it is as wide as its parent. To let the picture take whatever height is left, see Filling the Room Left.

Examples​

Default​

Open Default in Storybook

Aspects​

The same picture in a poster, a square and a wide frame. Each one is cropped to fill its frame.

Open Aspects in Storybook

Radius​

Open Radius in Storybook

Fallback​

With no picture, or one that fails to load, the frame shows its fallback glyph. Pick one that says what is missing, such as "utensils" for a recipe, "film" for a film or "book" for a book.

Open Fallback in Storybook

Marks​

mark puts a small glyph in the top right corner saying what the picture is, the way a social app marks a post: "film" for a video, "clone" for an album of several pictures. It sits on a disc so it stays clear over any picture, and grows and shrinks with the frame.

Open Marks in Storybook
<Cover
src={post.thumbnailUrl}
width={96}
mark={post.isVideo ? "film" : post.isAlbum ? "clone" : undefined}
/>

Screen readers skip the mark, so if it matters, say it in alt too.

In Ink​

Some pictures are drawn in one color with see-through parts, such as an emblem, a logo or a silhouette. Shown as they are, a dark one disappears on a dark frame. Set tone="ink" and the cover draws only the picture's shape, in the ink of whichever theme the frame uses, so it reads on a light frame and a dark one alike. fit, radius, mark and the fallback glyph work the same as for any picture.

Open In Ink in Storybook
<Cover
src={sign.emblemUrl}
alt={sign.name}
width={72}
radius="full"
tone="ink"
/>

Inverted​

Some pictures have the opposite ground to the frame's: a chart of the night sky is light stars on a dark sky, which on a light frame is a dark block. invert draws the picture as its negative. invert="light" inverts it on a light frame only, so the sky takes the frame's paper and the stars read as ink, and leaves it as it is on a dark frame, where it already reads that way. invert="dark" does the same the other way round, for a dark drawing on a light ground shown on a dark frame, and invert alone inverts it on both. The cover follows the frame's theme by itself, in a saved preview as much as on the frame. A picture with tone="ink" already follows the theme, so invert leaves it alone.

Open Inverted in Storybook
<Cover src={skyChart.imageUrl} fit="contain" height="fill" invert="light" />

Turned​

rotate turns the picture inside its frame by a quarter, a half or three quarters clockwise, with its placeholder and its mark, the way a reversed tarot card lies upside down. The frame keeps the size and proportion you give it, so a quarter turn crops the picture to the frame on its side, and a whole picture (fit="contain") takes the proportion of the picture once turned.

Open Turned in Storybook
<Cover
src={card.imageUrl}
alt={card.name}
width={84}
aspect={7 / 12}
rotate={card.reversed ? 180 : 0}
/>

The Whole Picture​

A painting's edges are part of it, so don't crop it: set fit="contain". width and height then name the box the picture has to fit in, such as "100%" of the room your layout leaves, and the frame takes the picture's own proportion inside it, as large as fits, centered. You never need the picture's size from the API.

Open Whole Picture in Storybook
<div className="min-h-0 flex-1">
<Cover src={artwork.imageUrl} fit="contain" width="100%" height="100%" />
</div>

Filling the Room Left​

In a flex column, height="fill" lets the picture take the height the rest of the column leaves. It grows until it spans the column at its aspect, and in a shorter box it shrinks before the text does, staying centered, so your title and footer always fit. You don't need to pick a size for each box.

Open Fill The Column in Storybook
<div className="flex h-full flex-col gap-2">
<Cover src={post.imageUrl} height="fill" aspect={4 / 3} />
<Paragraph size="sm" weight="semibold" lines={2}>
{post.title}
</Paragraph>
<div className="mt-auto">
<Paragraph size="xs">{post.date}</Paragraph>
</div>
</div>

Give width too and the picture never grows wider than that; the column's own alignment, such as items-center, places it. With fit="contain" the whole picture grows the same way at its own proportion, and the placeholder and mark fill the same room.

Open Fill With A Width in Storybook

In a row with a height of its own, such as one with min-h-0 flex-1 in its column, the picture takes the row's height instead and is as wide as its aspect makes it.

Open Fill The Row in Storybook
<div className="flex min-h-0 flex-1 items-center gap-3">
<Cover src={film.posterUrl} height="fill" aspect={2 / 3} fallback="film" />
<div className="min-w-0 flex-1">
<Heading level={3}>{film.title}</Heading>
</div>
</div>

In a List​

A row as tall as its cover, with the title and the show beside it. An episode without artwork gets the placeholder, so the rows still line up.

Open In A List in Storybook
import { Cover } from "~lib/data-display/cover";
import { Paragraph } from "~lib/typography";

const Episode = ({
title,
show,
artwork,
}: {
title: string;
show: string;
artwork?: string;
}) => (
<div className="flex items-center gap-3">
<Cover src={artwork} width={56} fallback="film" />
<div className="min-w-0 flex-1">
<Paragraph size="sm" weight="semibold" lines={1}>
{title}
</Paragraph>
<Paragraph size="xs">{show}</Paragraph>
</div>
</div>
);

See Also​

  • Avatar - A person or a short code in a circle
  • CoverGrid - A gallery of covers filling its box
  • Icon - The glyphs a cover can fall back to
  • QRCode - A code to scan beside a cover