Faceted background
Signature surface: the one canonical faceted field (no controls)
One codified look, composed from the shipped NockerlFacetedBackground primitive (the same field as the app-shell, the sidebar, and empty-state): a canvas per-facet tone-wave, the mesh built once per size and re-tinted every frame. Color is token-only, so it themes; changing the signature is a one-place design-system change that propagates to every app.
// Web: React, consuming @dizyx/nockerl-tokens. (Web is the laggard platform;// this is the canonical API the published @dizyx/nockerl-react package exposes.// It re-implements the native field on a token-colored <canvas>.)import { NockerlFacetedBackground } from '@dizyx/nockerl-react';
export function SessionStage() { return ( <NockerlFacetedBackground> <h1>Faceted background</h1> <p>Content renders on the field and stays fully legible.</p> </NockerlFacetedBackground> );}// Android: Jetpack Compose (CANONICAL source). com.nockerl.app.chat.ui.ChatFeedBackground// Internal composable: fills its parent and draws the faceted field behind content.// Geometry (cell 128.dp, 18s wave, ±0.05 amplitude) is private to the file; it reads// chatBg + canvasEdge from LocalNockerlColors, so it tracks the active palette.import com.nockerl.app.chat.ui.ChatFeedBackground
Box { ChatFeedBackground(modifier = Modifier.matchParentSize()) ChatFeed(/* messages render on the field */)}// macOS: SwiftUI (canonical port). NockerlVoice/UI/FacetBackground.swift// A TimelineView(.animation) + Canvas. Takes NO parameters: it reads the window// colorScheme and uses the same static field constants as the Compose original.ZStack { FacetBackground() // fills behind content DashboardContent() // renders on the field}Parameters
Section titled “Parameters”| Prop | Type | Default | Description |
|---|---|---|---|
reduced | boolean | false | When true, freezes to a single composed static frame (prefers-reduced-motion). Resolved by the consumer; not a user-facing control. |
bare | boolean | false | BARE mode: render just the full-bleed facet field with NO surface chrome (no border, radius, shadow, or 16:9 aspect). Use it for a full-bleed app-shell / stage background. The default is the bordered card-radius signature surface. The MESH + tone-wave are identical either way (one implementation); bare only drops the chrome. Positioned absolute inset:0, so the parent must be positioned. |
children | React.ReactNode | Children render ON the surface (proving legibility over the live mesh). |
Also accepts the native <div> attributes (e.g. onClick, disabled, id, aria-*, data-*), forwarded straight through, plus a forwarded ref.
ChatFeedBackground takes only a layout modifier; the field is configured by
file-private constants and reads its colors from LocalNockerlColors. The pure
geometry / tone helpers (buildFacetField, facetLuminanceDelta, shiftLuminance)
are internal for testing, not a public API.
| Parameter | Type | Default | Description |
|---|---|---|---|
modifier | Modifier | Modifier | Layout modifier, typically Modifier.matchParentSize() so the field fills the content behind it. |
FACET_CELL_SIZE | Dp (const) | 128.dp | Nominal facet cell edge, kept large so the mesh reads as a few big facets. |
WAVE_PERIOD_MILLIS | Int (const) | 18_000 | One full diagonal tone-wave cycle. LinearEasing + RepeatMode.Restart (a full sine wraps seamlessly). |
WAVE_AMPLITUDE | Float (const) | 0.05f | Peak luminance swing the wave adds to a facet. Small by design (low-contrast, calm). |
STATIC_FACET_JITTER | Float (const) | 0.022f | Baked per-facet luminance grain (± this fraction), deterministic so the field never shimmers. |
FacetBackground is a parameterless View. It reads @Environment(\.colorScheme)
and uses the same static field constants as the Compose original; the base tone comes
from NockerlTheme.facetBaseDark / facetBaseLight.
| Style | Type | Default | Description |
|---|---|---|---|
cell | CGFloat (static) | 130 | Nominal facet cell edge (Compose uses 128.dp). |
jitterFraction | CGFloat (static) | 0.34 | How far an interior grid point may stray from its lattice slot. Edge points are not jittered, so the field meets the bounds cleanly. |
amplitude | Double (static) | 0.05 | Peak tone-wave luminance swing, matching the Compose WAVE_AMPLITUDE. |
staticJitter | Double (static) | 0.022 | Baked per-facet tonal grain. |
periodSeconds | Double (static) | 18.0 | One full diagonal wave cycle, driven by TimelineView(.animation). |