Figure
A figure with its caption: the media, then a label ("Fig. 3"), a caption that says what to notice, and a credit in the same run. Text never sits on the image.
import { Figure, FigureCaption, FigureMedia } from '@fairgarden-private/design/components/Figure'
The label is set in the mono data face, the caption in caption type and the credit ("Photo: Name / Program") in small type, all in the muted ink. Number figures only where the text refers to them, but give every figure a caption or a credit, because print needs one.
Photo, technical figure and plate
Photo, technical figure and plate
photo is the default: an editorial photo with an 8 px radius (squared when it runs full-bleed) and its caption right-flush below it. technical is for charts, diagrams and drawings: square, never scaled up, with the caption left-aligned below and the label on its own line; framed adds a 1 px rule frame. plate is a specimen plate: the media becomes a nested white face over a fine dot grid, framed in that face's own edge color. It is a light island inside a field or the night band, so a two-ink chart can sit on it on any ground. number generates "Fig. 3", numbering="catalog" gives "Figure 001", and detail marks a crop.
import { Figure, FigureCaption, FigureMedia } from '@fairgarden-private/design/components/Figure'
import styles from './kinds.module.css'
/** Stands in for a photo: a flat drawing of a marsh at dusk. */
function MarshPhoto() {
return (
<svg className={styles.photo} viewBox="0 0 480 320" role="img" aria-label="A marsh at dusk">
<rect className={styles.sky} width="480" height="320" />
<path className={styles.hills} d="M0 190 120 140l110 40 90-50 160 60v130H0z" />
<path className={styles.water} d="M0 230h480v90H0z" />
<path className={styles.reeds} d="M40 320v-80M52 320v-96M64 320v-70M410 320v-88M424 320v-104M436 320v-76" />
</svg>
)
}
/** Stands in for a technical drawing: a leaf in outline with its dimension line. */
function LeafDrawing() {
return (
<svg className={styles.drawing} viewBox="0 0 320 200" role="img" aria-label="Leaf outline, 18 cm long">
<path className={styles.line} d="M40 100C90 30 230 30 280 100 230 170 90 170 40 100Z" />
<path className={styles.line} d="M40 100h240M110 100l40-40M170 100l40-40M110 100l40 40M170 100l40 40" />
<path className={styles.line} d="M40 186h240M40 180v12M280 180v12" />
</svg>
)
}
/** The three kinds: an editorial photo, a framed technical figure and a specimen plate. */
export function FigureKinds() {
return (
<div className={styles.stack}>
<Figure>
<FigureMedia>
<MarshPhoto />
</FigureMedia>
<FigureCaption credit="Photo: Ada Reyes / Marsh Program">
The reed line marks the high-water mark of the spring flood.
</FigureCaption>
</Figure>
<Figure kind="technical" framed>
<FigureMedia>
<LeafDrawing />
</FigureMedia>
<FigureCaption number={3}>Leaf of the swamp white oak, lobes shallow and rounded.</FigureCaption>
</Figure>
<Figure kind="plate">
<FigureMedia>
<LeafDrawing />
</FigureMedia>
<FigureCaption number={1} numbering="catalog" detail>
Specimen from the north meadow collection.
</FigureCaption>
</Figure>
</div>
)
}
Side caption
Side caption
With sideCaption, the caption moves into the adjacent column once the figure itself is at least 768 px wide, top-aligned beside the media. Narrower, it stays below.
import { Figure, FigureCaption, FigureMedia } from '@fairgarden-private/design/components/Figure'
import styles from './side-caption.module.css'
/** From 768 px of the figure's own width, the caption moves beside the media. */
export function FigureSideCaption() {
return (
<Figure kind="technical" sideCaption className={styles.figure}>
<FigureMedia>
<svg className={styles.chart} viewBox="0 0 480 200" role="img" aria-label="Water level by month, highest in April">
<path className={styles.axis} d="M40 20v160h420" />
<path className={styles.series} d="M40 150 110 120l70-70 70 20 70 40 70 10 70 20" />
</svg>
</FigureMedia>
<FigureCaption number={4} credit="Source: County water survey">
Water level peaks in April, a month earlier than in 2020.
</FigureCaption>
</Figure>
)
}
In print
A figure never separates from its caption. Content photos print in grayscale inside a 0.75 pt frame, no taller than 100 mm; decorative photos (empty alt) are left out. The plate's dot grid drops, and its frame prints black.
API Reference
Figure
The figure. Put a FigureMedia and a FigureCaption inside. Every
figure gets a caption or a credit, for print; figure and caption never
separate across printed pages.
| Prop | Type | Description |
|---|---|---|
framed | | Technical figures: a |
kind | |
|
primary | | Primary Radix scale: caption, label, credit and frames. Never defaulted; omitted, it inherits the scope [D133]. |
secondary | | Secondary Radix scale: unused by the figure itself. Never defaulted. |
sideCaption | | From 768 px of the figure’s width, the caption sits in the adjacent
column, top-aligned, beside the media. Default |
FigureMedia
The media box: an img, svg or chart. Photos fill the column;
technical figures keep their native width and never scale up [D78]. A
decorative photo (empty alt) is left out of print. On a plate it is the
nested white face, which takes the figure’s primary and secondary.
FigureCaption
The caption: the label in type-data, the caption text (the children)
in type-caption and the credit in type-small, all --role-muted.
Number figures only where the text refers to them.
| Prop | Type | Description |
|---|---|---|
label | | Replaces the generated label entirely. |
credit | | The credit, in the same run: “Photo: Name / Program” ( |
detail | | Adds “(DETAIL)” to the label, for a crop. |
number | | The figure number; renders “Fig. 3″ (or “Figure 003″ with |
numbering | |
|
Additional types
FigureCaptionProps
Props for FigureCaption: figcaption props plus the numbering and the credit.
type FigureCaptionProps = React.ClassAttributes<HTMLElement> &
React.HTMLAttributes<HTMLElement> & {
number?: number | string;
numbering?: 'short' | 'catalog';
label?: React.ReactNode;
detail?: boolean;
credit?: React.ReactNode;
}FigureMediaProps
Props for FigureMedia: div props.
type FigureMediaProps = React.ComponentPropsWithRef<'div'>FigureProps
Props for Figure: figure props and the kind, frame, caption-placement and color axes.
type FigureProps = React.ClassAttributes<HTMLElement> &
React.HTMLAttributes<HTMLElement> & {
kind?: 'photo' | 'technical' | 'plate' | null;
framed?: boolean;
sideCaption?: boolean;
primary?:
| 'ruby'
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'crimson'
| 'tomato'
| 'pink'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple'
| null;
secondary?:
| 'ruby'
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'crimson'
| 'tomato'
| 'pink'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple'
| 'amber'
| 'blue'
| 'cyan'
| 'grass'
| 'green'
| 'jade'
| 'lime'
| 'mint'
| 'orange'
| 'sky'
| 'teal'
| 'yellow'
| null;
}Specification: DESIGN-SYSTEM.md §8.5 (figures and captions).