Signature surface: the one canonical faceted field (no controls)
Streaming
Nockerl · session
Faceted background
Content stays fully legible on the field. The facets are a low-contrast tonal grain, never a glow.
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.
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
n/a
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).
Cross-platform drift (this surface lives natively in Voice + Android)
The faceted field is canonical on Android (ChatFeedBackground.kt, behind the
chat feed) and a faithful Swift port in Voice (FacetBackground.swift). Web is
derived: the demo re-implements the exact same mesh on a token-colored <canvas>.
Honest divergences:
Configurability: all three surfaces are intentionally fixed. The field is a
single codified standard, not user-configurable (no intensity / density / speed /
tint knobs and no surface variants on any platform). Geometry is private; only Compose
exposes a modifier for placement.
Cell size: Compose 128.dp vs Swift 130, a small unreconciled constant.
Edge hairline: Compose canvasEdge @ 0.05, Swift white @ 0.06. Both should resolve
to one canvas-edge token at one alpha.
Base tone: both read the chat-bg token (#181B20 dark); the per-facet
shift is a neutral per-channel luminance add (no hue, no glow) on all three.