Surface Inversion
Surface lets a container declare what kind of surface it's on
(positive or negative) and, with that, makes children resolve
Foundation aliases automatically inverted — without any child knowing
what context it's in.
The problem
Without Surface, a button on a dark background must explicitly swap its text color / border / hover. Every use becomes duplicated code prone to visual drift.
The primitive
Containers that accept surface:
<Flex surface="negative"><Base surface="negative">- (any container inheriting from that base — Card, Paper, etc.)
surface="positive" is the implicit default (no need to declare it).
import { Flex } from '@apollion-dsi/core/containers/flex';
import { Button } from '@apollion-dsi/core/elements/button';
import { Text } from '@apollion-dsi/core/elements/text';
// light background, "normal" text/button
<Flex surface="positive" p="large" bgColor="baseLight">
<Text>Light header</Text>
<Button text="OK" />
</Flex>
// dark background, text/button automatically inverted
<Flex surface="negative" p="large" bgColor="baseDark">
<Text>Dark header</Text>
<Button text="OK" />
</Flex>The children don't change. The ThemeProvider resolves the inversion.
Live demo
The same <Text> and <Button> rendered in positive (default, light
background) and negative (dark background) containers, with no explicit
color prop on the children. Note the automatic contrast.
When to use it
- Yes: Hero sections, dark footers, modals with inverted chrome, toolbars over images.
- No: For individual components. Surface is a container property, not an element one. If you need to invert a single button, use Foundation/Semantic with a variant.
Surface respects the current mode
Surface inversion respects the theme's active light/dark mode: the
negative surface carries the opposite polarity's surface ladder — in
light mode surface="negative" gets the dark ladder (dark paper, light ink),
in dark mode the light one — derived by the same engine from the same seeds,
never a hand-swapped palette. Structural tokens (theme.colors.*) stay
untouched. See Dark Mode Engine.