Skip to content

AtmosphericLayout

  • Layer: Layout primitive
  • Base: Custom — no Ark UI dependency
PlaneLayerRole
Plane 2z-index: 0, position: absoluteEnvironment — radial gradient, breathing animation. Never carries information.
Plane 1z-index: 1, position: relativeAll UI — flat, static. Children provide their own layout.
import { AtmosphericLayout } from "@risingswamp/design-system";
// Typically the outermost wrapper in Layout.tsx
<AtmosphericLayout>
<Flex flex="1" overflow="hidden">
<AppSidebar />
<Box flex="1">{children}</Box>
</Flex>
</AtmosphericLayout>;
PropTypeDefaultDescription
childrenJSX.ElementrequiredPlane 1 content — your entire UI

The gradient’s position and colors are driven by --atm-* CSS vars scoped to html[data-theme]:

Theme--atm-x--atm-yColorEffect
delight50%100%Cyan rgba(0,245,255,…)Light from below — submarine
relight65%0%Amber rgba(255,200,100,…)Light from above — dawn
gilt100%72%Gold rgba(232,120,20,…)Light from the side — golden hour

Adding a new theme requires only a new html[data-theme="vesper"] { --atm-x: …; --atm-y: …; … } block in global.css — zero component changes.

Plane 2 uses the breathe keyframe (opacity: 0.65 → 1, 9s, infinite alternate). This is Plane 2-only — no Plane 1 elements animate on idle.

@keyframes breathe {
0% {
opacity: 0.65;
}
100% {
opacity: 1;
}
}
  • Plane 2 is pointer-events: none and aria-hidden="true" — it is purely decorative and fully inert.
  • Plane 1 overflow: hidden prevents children from escaping the container. Children must manage their own scrolling.
  • Do not place information in Plane 2. Do not animate Plane 1 elements on idle. These are the two invariants of the two-plane model.
  • The gradient uses in oklab color interpolation to eliminate banding. Correct syntax: radial-gradient(ellipse at <pos> in oklab, ...)in oklab goes after the shape/position, with no comma before it. Putting in oklab as the first argument (before the shape) causes WebKit/Tauri to strip it entirely, breaking the gradient.
  • The transparent stop uses oklab(from var(--atm-2) l a b / 0) — this fades to a zero-opacity version of --atm-2 rather than to black, eliminating the dark fringe at the gradient edge in oklab space.
  • Noise texture is generated once at mount via canvas (200×200, uniform grey, full alpha) and applied as a repeating soft-light overlay at 0.09 opacity. This must be an inline style — Panda CSS does not generate mix-blend-mode from the mixBlendMode token in this context.
  • Gradient only — no text, no borders, no interactive elements
  • pointer-events: none always
  • aria-hidden="true" always
  • Animation is breathe only — no other motion on Plane 2