Ground
The ground scope: paints one of the 16 presets as a band, a field or a face, publishes its primary, secondary and action scales and its container edge, and tells every component inside it which role map to use.
import { Ground } from '@fairgarden-private/design/components/Ground'
Ground writes data-ground, data-tone and data-scheme (and data-theme where the scope fixes its mode) and provides the scope through React context. Components inside take their colors from it; nothing below a Ground chooses a mode. It also publishes --role-edge, the edge that cards, faces and panels inside it draw.
kind is its structural axis, and each preset belongs to one kind. The props type is a discriminated union, so a preset outside its kind is a type error.
kind | Presets | Mode | Geometry | --role-edge |
|---|---|---|---|---|
band (default) | The page grounds: paper, white, tide, meadow, pollen, apricot, rose, heather; and night, for the footer and the media hero only | Page grounds follow the page mode; night is always dark | Full-bleed section or the page root, with a seam rule that shows only on the night band in dark mode | --role-rule |
field | forest, royal, brick (always dark); leaf, amber, clay, pink (always light) | Fixed | Inset inside the content container, with padding, a radius and its own --primary12 edge; never full-bleed. framed makes it the page's one framed feature field | --primary12 |
face | The page grounds, as a card face, plate or panel; night only with onMedia, for the media Button | On a page ground it follows the mode; inside a field or the night band it is a light island | Set by the composing component | --primary10, or --primary12 as a light island |
Page grounds
The eight page grounds, in both modes
A page takes paper, white or one pastel as its page ground, with paper and white as its secondary bands; two pastels never meet. Each page ground paints the same step in both modes: the pastels are step 3 of their hue, a pastel in light mode and a rich near-black in dark mode. They share one ladder: rule step 10, hairline step 8 (7 in dark mode), and no soft fills, so components take their outline form. Amber is the action on all eight.
Light mode
Dark mode
import { Button } from '@fairgarden-private/design/components/Button'
import { Ground } from '@fairgarden-private/design/components/Ground'
import { Link } from '@fairgarden-private/design/components/Link'
import styles from './page-grounds.module.css'
const pageGrounds = [
'paper',
'white',
'tide',
'meadow',
'pollen',
'apricot',
'rose',
'heather',
] as const
const modes = ['light', 'dark'] as const
/**
* The eight page grounds follow the page mode, painting the same step in
* both: paper and white, and the six step-3 pastels (a pastel in light
* mode, a rich near-black in dark mode). Each shows its section head
* (--role-heading), a body link (--role-accent underline, --role-link-hover
* on hover) and the amber action.
*
* Preview only: each row forces its mode with `data-theme` on a wrapper,
* which a product sets only on `html`, from the app shell.
*/
export function GroundPageGrounds() {
return (
<div className={styles.modes}>
{modes.map((mode) => (
<div key={mode} data-theme={mode} className={styles.mode}>
<p className={styles.modeName}>{mode === 'light' ? 'Light mode' : 'Dark mode'}</p>
<div className={styles.grid}>
{pageGrounds.map((preset) => (
<Ground key={preset} kind="face" preset={preset} className={styles.face}>
<span className={styles.name}>{preset}</span>
<Link href="#page-grounds">Field notes</Link>
<div>
<Button variant="solid" size="sm">
Join
</Button>
</div>
</Ground>
))}
</div>
</div>
))}
</div>
)
}
Fields
The seven fields
Saturated color arrives only as a field: a card, a CTA or campaign panel, a brand or program panel. A field sits inside the content container with page ground around it, so two fields never touch. It keeps its mode in both page modes and draws its own --primary12 edge, which carries the boundary wherever tone does not. The solid fields carry one ink: the action becomes the ink pill, and every hover that would change only an ink also underlines.
import { Button } from '@fairgarden-private/design/components/Button'
import { Ground } from '@fairgarden-private/design/components/Ground'
import { Link } from '@fairgarden-private/design/components/Link'
import styles from './fields.module.css'
const fields = ['forest', 'royal', 'brick', 'leaf', 'amber', 'clay', 'pink'] as const
/**
* The seven fields: inset, fixed-mode surfaces with a radius and their own
* --primary12 edge, never full-bleed. Forest, royal and brick stay dark and
* leaf, amber, clay and pink stay light in both page modes. The solid
* fields carry one ink: the action becomes the ink pill and the link hover
* adds an underline.
*/
export function GroundFields() {
return (
<div className={styles.grid}>
{fields.map((preset) => (
<Ground key={preset} kind="field" preset={preset} className={styles.field}>
<span className={styles.name}>{preset}</span>
<Link href="#fields">Field notes</Link>
<div>
<Button variant="solid" size="sm">
Join
</Button>
</div>
</Ground>
))}
</div>
)
}
Kinds
Band, field and face
Each page ground has a companion field, which replaces the old inverse pairs. Use it for inverse placements and for the Dialog's solid cover (companionField(preset) returns it):
| Page ground | Companion field |
|---|---|
paper, white, meadow, pollen | forest |
tide, heather | royal |
apricot, rose | brick |
Band: tide
Face on the page ground
Field notesField: royal, tide's companion
Light island
Field notesBand: night
Footer and media hero onlyimport { Ground } from '@fairgarden-private/design/components/Ground'
import { Link } from '@fairgarden-private/design/components/Link'
import styles from './kinds.module.css'
/**
* The three kinds on one page. A `tide` band holds a white face, which
* follows the mode with the page and draws a --primary10 edge, and tide's
* companion field, royal, whose white face is a light island with a
* --primary12 edge in both modes. The night band, for the footer and the
* media hero only, draws its --primary12 seam in dark mode.
*/
export function GroundKinds() {
return (
<div className={styles.stack}>
<Ground kind="band" preset="tide" className={styles.band}>
<p className={styles.head}>Band: tide</p>
<div className={styles.row}>
<Ground kind="face" preset="white" className={styles.face}>
<p className={styles.label}>Face on the page ground</p>
<Link href="#kinds">Field notes</Link>
</Ground>
<Ground kind="field" preset="royal" className={styles.field}>
<p className={styles.label}>Field: royal, tide's companion</p>
<Ground kind="face" preset="white" className={styles.face}>
<p className={styles.label}>Light island</p>
<Link href="#kinds">Field notes</Link>
</Ground>
</Ground>
</div>
</Ground>
<Ground kind="band" preset="night" className={styles.band}>
<p className={styles.head}>Band: night</p>
<Link href="#kinds">Footer and media hero only</Link>
</Ground>
</div>
)
}
Overrides
Overriding the scales
primary, secondary and action override the preset's scales for the whole scope. Section heads, link underlines and rules re-resolve from the new scales. Inside tinted or solid scopes, use only pairings the §2 matrix verifies.
import { Ground } from '@fairgarden-private/design/components/Ground'
import { Link } from '@fairgarden-private/design/components/Link'
import { Separator } from '@fairgarden-private/design/components/Separator'
import styles from './overrides.module.css'
export function GroundOverrides() {
return (
<div className={styles.row}>
<Ground preset="paper" kind="face" className={styles.face}>
<span className={styles.head}>Defaults</span>
<Separator />
<Link href="#overrides">olive × green</Link>
</Ground>
<Ground preset="paper" secondary="indigo" kind="face" className={styles.face}>
<span className={styles.head}>secondary="indigo"</span>
<Separator />
<Link href="#overrides">olive × indigo</Link>
</Ground>
<Ground preset="paper" primary="slate" secondary="amber" kind="face" className={styles.face}>
<span className={styles.head}>primary="slate"</span>
<Separator />
<Link href="#overrides">slate × amber</Link>
</Ground>
</div>
)
}
API Reference
The ground scope component (§1.11.5). Writes data-ground, data-tone and
data-scheme (and data-theme where the scope fixes its mode or is a light
island [D149]), adds the scale classes for the preset’s defaults or the
overrides, paints --role-ground, publishes --role-edge, draws the
seam on bands and the edge on fields, and provides the scope to
descendants through React context [D148, D178].
| Prop | Type | Description |
|---|---|---|
action | | Override the scope’s action scale. |
density | | Written as |
framed | | |
kind | |
|
onMedia | | |
preset | | A page ground ( |
primary | | Override the preset’s primary. Inside tinted or solid scopes, only a pairing that §2’s matrix verifies [D128]. |
secondary | | Override the preset’s secondary. |
BandPreset
The presets a full-bleed band takes: the page grounds, and night for the footer and the media hero [D177].
type BandPreset =
'night' | 'paper' | 'white' | 'tide' | 'meadow' | 'pollen' | 'apricot' | 'rose' | 'heather'companionFields
Each page ground’s companion field [D177], which replaces the inverse pairs: the dark field for “inverse” placements and the Dialog’s solid cover.
type companionFields = Record<
'paper' | 'white' | 'tide' | 'meadow' | 'pollen' | 'apricot' | 'rose' | 'heather',
'forest' | 'leaf' | 'amber' | 'clay' | 'pink' | 'royal' | 'brick'
>Density
type Density = 'compact' | 'default' | 'spacious'FieldPreset
type FieldPreset = 'forest' | 'leaf' | 'amber' | 'clay' | 'pink' | 'royal' | 'brick'fieldPresets
The seven fields [D177]: inset, fixed-mode surfaces with a radius and a
--primary12 edge, never full-bleed. kind="field" only.
type fieldPresets = ['forest', 'leaf', 'amber', 'clay', 'pink', 'royal', 'brick']GroundKind
Ground’s structural axis [D178]: a full-bleed band (a page ground, or
the night band), an inset field, or a nested face (card face, plate,
panel).
type GroundKind = 'band' | 'field' | 'face'GroundPreset
Every v1 preset (§1.4.2) [D180].
type GroundPreset =
| 'night'
| 'paper'
| 'white'
| 'tide'
| 'meadow'
| 'pollen'
| 'apricot'
| 'rose'
| 'heather'
| 'forest'
| 'leaf'
| 'amber'
| 'clay'
| 'pink'
| 'royal'
| 'brick'GroundProps
Props for Ground: section props, render, the kind and its preset, the
scale overrides and the density. A discriminated union on kind [D178]:
a field preset outside kind="field", night as a field, night as a
face other than onMedia, and deferred or retired presets are type
errors. Page grounds always follow the mode, so a pastel can never be a
fixed-mode anchor.
type GroundProps =
| (React.ClassAttributes<HTMLElement> &
React.HTMLAttributes<HTMLElement> &
__type &
GroundCommonProps &
GroundBandProps)
| (React.ClassAttributes<HTMLElement> &
React.HTMLAttributes<HTMLElement> &
__type &
GroundCommonProps &
GroundFieldProps)
| (React.ClassAttributes<HTMLElement> &
React.HTMLAttributes<HTMLElement> &
__type &
GroundCommonProps &
GroundFaceProps)
| (React.ClassAttributes<HTMLElement> &
React.HTMLAttributes<HTMLElement> &
__type &
GroundCommonProps &
GroundMediaFaceProps)PageGroundPreset
type PageGroundPreset =
'paper' | 'white' | 'tide' | 'meadow' | 'pollen' | 'apricot' | 'rose' | 'heather'pageGroundPresets
The eight page grounds [D176]: follows-mode bands (or faces), painting the
same step in both modes. A page has at most one pastel, as its page
ground, with paper and white as its secondary bands [D179].
type pageGroundPresets = [
'paper',
'white',
'tide',
'meadow',
'pollen',
'apricot',
'rose',
'heather',
]PastelPreset
type PastelPreset = 'tide' | 'meadow' | 'pollen' | 'apricot' | 'rose' | 'heather'pastelPresets
The six step-3 pastel page grounds [D176].
type pastelPresets = ['tide', 'meadow', 'pollen', 'apricot', 'rose', 'heather']presetDefaults
§1.4.2: defaults primary × secondary; action. Amber is the action on every page ground [D176].
type presetDefaults = Record<GroundPreset, PresetDefaults>PresetDefaults
type PresetDefaults = {
primary:
| 'pink'
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'ruby'
| 'crimson'
| 'tomato'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple';
secondary:
| 'amber'
| 'pink'
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'ruby'
| 'crimson'
| 'tomato'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple'
| 'blue'
| 'cyan'
| 'grass'
| 'green'
| 'jade'
| 'lime'
| 'mint'
| 'orange'
| 'sky'
| 'teal'
| 'yellow';
/** `ink`: the scope publishes its primary as the action scale (the ink pill). */
action:
| 'ink'
| 'amber'
| 'pink'
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'ruby'
| 'crimson'
| 'tomato'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple'
| 'blue'
| 'cyan'
| 'grass'
| 'green'
| 'jade'
| 'lime'
| 'mint'
| 'orange'
| 'sky'
| 'teal'
| 'yellow';
}Specification: DESIGN-SYSTEM.md §1.4.2 (ground families and presets), §1.5.3 (role maps) and §1.11.5 (the ground scope component) [D176–D181].