FairGarden Design

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.

kindPresetsModeGeometry--role-edge
band (default)The page grounds: paper, white, tide, meadow, pollen, apricot, rose, heather; and night, for the footer and the media hero onlyPage grounds follow the page mode; night is always darkFull-bleed section or the page root, with a seam rule that shows only on the night band in dark mode--role-rule
fieldforest, royal, brick (always dark); leaf, amber, clay, pink (always light)FixedInset 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
faceThe page grounds, as a card face, plate or panel; night only with onMedia, for the media ButtonOn a page ground it follows the mode; inside a field or the night band it is a light islandSet 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

paperField notes
whiteField notes
tideField notes
meadowField notes
pollenField notes
apricotField notes
roseField notes
heatherField notes

Dark mode

paperField notes
whiteField notes
tideField notes
meadowField notes
pollenField notes
apricotField notes
roseField notes
heatherField notes
GroundPageGrounds.tsx
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.

forestField notes
royalField notes
brickField notes
leafField notes
amberField notes
clayField notes
pinkField notes
GroundFields.tsx
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 groundCompanion field
paper, white, meadow, pollenforest
tide, heatherroyal
apricot, rosebrick

Band: tide

Face on the page ground

Field notes

Field: royal, tide's companion

Light island

Field notes

Band: night

Footer and media hero only
GroundKinds.tsx
import { 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&apos;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.

Defaultsolive × green
secondary="indigo"olive × indigo
primary="slate"slate × amber
GroundOverrides.tsx
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=&quot;indigo&quot;</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=&quot;slate&quot;</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].

PropTypeDescription
action
| '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'
| undefined

Override the scope’s action scale.

density
Density | undefined

Written as data-density; inherited by the scope, so never defaulted.

framed
boolean | undefined
kind
'band' | 'field' | 'face' | undefined

band (default): a full-bleed section or the page root, drawing its --role-seam rule top and bottom (visible only on the night band in dark mode [D179]). field: an inset, fixed-mode surface with a radius and a --primary12 edge. face: a nested card face, plate or panel.

onMedia
true | undefined
preset
| BandPreset
| 'forest'
| 'leaf'
| 'amber'
| 'clay'
| 'pink'
| 'royal'
| 'brick'
| 'paper'
| 'white'
| 'tide'
| 'meadow'
| 'pollen'
| 'apricot'
| 'rose'
| 'heather'
| 'night'
| undefined

A page ground (paper default, white, or one pastel per page: tide, meadow, pollen, apricot, rose, heather), which follows the page mode; or night, always dark, for the footer and the media hero only [D176, D177].

primary
| 'pink'
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'ruby'
| 'crimson'
| 'tomato'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple'
| undefined

Override the preset’s primary. Inside tinted or solid scopes, only a pairing that §2’s matrix verifies [D128].

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'
| undefined

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']
ground
type ground = ground
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].