BaseSurface
A background layer with switchable materials and motion fallback.
Usage
Modes
mode picks the material: refraction (the default), glass, acrylic, blur backdrop blur, mask translucent overlay, mica, pure solid (flat is an alias), or plain, which paints no material. Each material's pipeline and cost are in Surface 8-Material Taxonomy & Gatekeepers.
Advanced Lab
filter* props tune the filter layer, refraction* props the refraction layer, and preset="card" applies the card tuning.
Fake Mode
fake paints the background on a pseudo-element, matching the existing .fake-background layering; slot content sits above it naturally. Under pure (flat) that base is opaque and under mask it follows the mask opacity; under blur, acrylic, glass and refraction it sits beneath the material at opacity, so the page behind still shows through to be blurred and refracted; mica paints its own opaque base and plain paints nothing, so neither takes it.
Motion Fallback
When a surface moves with its element, backdrop-filter samples lag behind the element's position, and the filter layers drag a misaligned patch of backdrop along. With moving set, blur, glass and acrylic degrade to fallbackMode and recover smoothly when it stops; refraction keeps its mode and fades its filter layers out, then back in once it stops.
Raw vs BaseSurface
When the motion state isn't available, turn on autoDetect and the surface senses motion itself (see the next section).
Environment sensing
With autoDetect on, the surface combines five runtime signals: transforms on itself and its ancestors, the speed of a pressed pointer (above 1.2px/ms), window moves and resizes, a frame-budget probe, and power saving. The first three trigger the motion fallback, which starts to recover 140ms after the signal stops; under power saving or a reduced frame budget, refraction, glass and acrylic become blur, and under minimal they and blur become flat, returning to the declared material once the condition clears. How each signal is read is in Adaptive Surface Deduction & 120Hz Fallback.
A page receives no event when its window moves, so the host forwards one; a host that knows the power state can override the battery API's reading:
import { notifySurfaceWindowMotion, setSurfacePowerSaving } from '@talex-touch/tuffex'
// Once per BrowserWindow move (and will-move) event the main process relays to the renderer
notifySurfaceWindowMotion()
// From Electron's powerMonitor, say; null hands it back to the Battery Status API
setSurfacePowerSaving(true)
Flow light
flowLight lays a fixed brand-colour light (FlowLight) over the veil and under the edge, in any mode.
System backdrop
A transparent Electron window lets the desktop show through its own system material (vibrancy on macOS, Mica on Windows), and a page's backdrop-filter cannot reach that material: the filter samples only the surface's own veil and lays the copy over that veil, so a 75% veil stacked twice is all but opaque and the desktop no longer shows through. systemBackdrop runs no backdrop-filter on the surface: the glass layer doesn't render and the filter layer keeps only its tint, leaving the blur to the system; the veil, mask, flow light and rim draw as usual. With nothing sampled from the page, moving and autoDetect have no effect either.
<!-- core-app's CoreBox: a transparent window, its surface over the system material -->
<TxBaseSurface system-backdrop fake color="var(--tx-fill-color)" :opacity="0.75" />
Best Practices
- Prefer
TxCardfor product containers, since it owns container semantics and interaction; useTxBaseSurfaceonly to tune material, fallback, or refraction directly. - Pass
movingwhen the parent owns the animation state; useautoDetectonly for motion whose state you can't reach, or to switch to a lighter material under power saving and dropped frames. - Keep
fallbackMode="mask"soblur/glass/acryliccontent stays readable in motion; usepureonly when a flat color is acceptable. - Tune refraction through
refractionStrength,refractionProfile, andrefractionTone; keep RGB channel offsets for visual experiments. - Use
refractionRenderer="css"only where its lower optical fidelity is acceptable.
API Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
mode | 'pure' | 'mask' | 'blur' | 'glass' | 'refraction' | 'acrylic' | 'mica' | 'flat' | 'plain' | 'refraction' | Material: refraction, glass, acrylic, backdrop blur, mask, mica, solid (flat is the same as pure), or no material. |
radius | string | number | - | Corner radius; inherits from the parent when unset. |
color | string | - | Base color for the solid and mask layers, the acrylic tint and the mica base. |
opacity | number | 0.75 | Opacity in mask mode (0–1); acrylic's tint takes 0.8 of it; in fake mode, also the opacity of the base colour under the blur / acrylic / glass / refraction material. |
fallbackMaskOpacity | number | - | Opacity when degraded to mask (0–1). |
blur | number | 10 | Filter-layer blur radius in px; acrylic takes three times it. |
filterSaturation | number | 1.5 | Filter-layer saturation. |
filterContrast | number | 1 | Filter-layer contrast. |
filterBrightness | number | 1 | Filter-layer brightness. |
saturation | number | 1.8 | Glass-layer saturation for glass and refraction. |
brightness | number | 70 | Glass-layer brightness for glass and refraction; <= 3 is read as a multiplier. |
backgroundOpacity | number | 0 | Background opacity of the glass layer. |
borderWidth | number | 0.07 | Edge width factor of the glass layer. |
displace | number | 0.5 | Refraction displacement amount. |
distortionScale | number | -180 | Refraction distortion scale. |
redOffset / greenOffset / blueOffset | number | 0 / 10 / 20 | RGB channel offsets that control dispersion. |
xChannel / yChannel | 'R' | 'G' | 'B' | 'R' / 'G' | Channels sampled by the displacement map. |
mixBlendMode | string | 'difference' | Refraction blend mode. |
refractionStrength | number | 62 | Refraction strength, 0–100. |
refractionProfile | 'soft' | 'filmic' | 'cinematic' | 'filmic' | Refraction style preset. |
refractionTone | 'mist' | 'balanced' | 'vivid' | 'balanced' | Refraction tone: vivid is clearer, mist softer. |
refractionAngle | number | -24 | Main dispersion angle in degrees. |
refractionLightX / refractionLightY | number | - | Light anchor (0–1). |
refractionHaloOpacity | number | - | Halo opacity (0–1); the built-in filmic model applies when unset. |
overlayOpacity | number | 0 | Extra mask opacity for non-mask modes. |
flowLight | 'corners' | 'rim' | 'aurora' | false | - | The flow light's variant; absent or false is off, any mode can have it. |
flowLightIntensity | number | 1 | Flow light strength, multiplying the theme opacity. |
preset | 'default' | 'card' | 'default' | Visual preset; card applies the card tuning. |
refractionRenderer | 'svg' | 'css' | 'svg' | Refraction renderer. |
systemBackdrop | boolean | false | The surface sits on the window's own system material (vibrancy or Mica in a transparent Electron window): it runs no backdrop-filter and leaves the blur to the system; moving and autoDetect have no effect. |
moving | boolean | false | Marks the surface as moving, which triggers the fallback. |
fallbackMode | 'pure' | 'mask' | 'flat' | 'mask' | Mode used while moving; flat is the same as pure. |
settleDelay | number | 150 | Delay in ms before recovery after motion ends; never shorter than transitionDuration. |
autoDetect | boolean | false | Degrades by environment: falls back in motion when the surface or an ancestor transforms, a pressed pointer moves fast, or the window moves or resizes; switches to a lighter material under power saving or dropped frames. |
transitionDuration | number | 299 | Recovery transition duration in ms. |
fake | boolean | false | Renders the background on a pseudo-element. |
fakeIndex | number | 0 | z-index of the pseudo-element layer. |
tag | string | 'div' | Root element tag. |
Slots
| Slot | Props | Description |
|---|---|---|
default | - | Surface content, rendered in .tx-base-surface__content above every material layer. |
CSS Variables
| Variable | Source | Description |
|---|---|---|
--tx-surface-color | color prop or theme fallback | Solid, mask, acrylic tint and mica base color; defaults to var(--tx-fill-color-lighter, #fafafa). |
--tx-surface-radius | radius prop | Radius of the root and every layer; numbers become px. |
--tx-surface-transition | transitionDuration prop | Duration of layer fades, background, and backdrop-filter transitions. |
--tx-surface-filter-blur | blur prop | Blur radius of the filter and refraction filter layers. |
--tx-surface-filter-saturation | filterSaturation prop | Filter-layer saturation multiplier. |
--tx-surface-filter-contrast | filterContrast prop | Filter-layer contrast multiplier. |
--tx-surface-filter-brightness | filterBrightness prop | Filter-layer brightness multiplier. |
--tx-surface-mask-opacity | opacity, fallbackMaskOpacity, or overlayOpacity | Current mask opacity, clamped to 0..1. |
--tx-surface-refraction-light-x / --tx-surface-refraction-light-y | refractionLightX / refractionLightY or angle model | Refraction light anchor in percent. |
--tx-surface-refraction-strength | refractionStrength model | Optical strength blended across rest, motion, and recovery. |
--tx-surface-fake-index | fakeIndex prop | z-index of the pseudo-element layer. |
--tx-surface-fake-bg | color prop or theme fallback | Background color of the pseudo-element. |
--tx-surface-fake-opacity | 1 under pure and flat, 0 under mica and plain, the mask opacity under mask, opacity otherwise | Opacity of the pseudo-element. |
--tx-surface-mask-opacity-percent | mask opacity model | Mask opacity as a percentage (internal; do not override). |
--tx-surface-motion-cover-opacity | motion state model | Opacity of the refraction motion cover (internal). |
--tx-surface-refraction-edge-opacity | optics model | Opacity of the refraction edge highlight (internal). |
--tx-surface-refraction-streak-angle | refractionAngle model | Refraction streak angle, the angle plus 92deg (internal). |
--tx-surface-refraction-{filter,mask}-{base,primary,secondary,veil}-weight / --tx-surface-refraction-streak-weight | profile/tone weight model | Blend weights of the optical layers (internal). |
--tx-surface-refraction-*-gain / -boost / -base, --tx-surface-refraction-halo-opacity, --tx-surface-refraction-mask-effective-opacity | profile/tone derived values | Derived outputs of the optical interpolation (internal). |
--tx-surface-refraction-mask-color | theming hook (consumed) | Base color of the refraction gradients; override it in themes (defaults to #fff shades). |
--tx-surface-mica-primary-weight / --tx-surface-mica-harmonic-weight | theming hook (consumed) | Strength of mica's brand glow at the top left and its neighbouring-hue glow at the bottom right; 12% / 8% by default. |
--tx-surface-mica-harmonic | the brand hue +40° | The neighbouring hue of mica's bottom-right glow; the brand itself where relative colour syntax is unsupported (internal). |
Environment API
Import from @talex-touch/tuffex.
| Export | Signature | When to use |
|---|---|---|
notifySurfaceWindowMotion() | () => void | Call it as the host forwards window moves; the window counts as still once 140ms pass without a call. |
setSurfacePowerSaving(value) | (value: boolean | null) => void | Overrides the power-saving reading from the host; null hands it back to the Battery Status API (not charging, at or below 20%). |
getSurfaceEnvironment() | () => { pointerMoving, windowMoving, powerSaving, frameTier } | Reads the page's current environment as read-only refs; frameTier is 'ok' | 'reduced' | 'minimal'. |
useSurfaceMotionGuard(emitFallback, options?) | (emitFallback: (isFallback: boolean) => void, { settleMs? }) => { onMotionStart, onMotionEnd, dispose } | For hosts that know when they move: drives moving with the asymmetric clock, calling back true at once on start and false after settleMs (140ms by default) of quiet. |
SURFACE_POINTER_SPEED_THRESHOLD / SURFACE_MOTION_SETTLE_MS / SURFACE_LOW_BATTERY_LEVEL | 1.2 / 140 / 0.2 | The pointer speed threshold (px/ms), how long a motion signal stays quiet before it ends (ms), and the low-battery level. |
Overview
pureandflatrender only the root background;maskrenders a mask layer with opacity clamped to0..1;acrylicis a filter layer blurring three times as wide under a tint whose alpha carries fractal noise;micapaints the root with an opaque base and two glows anchored to the viewport (background-attachment: fixed), reading no backdrop but repainting with every scroll of its container, so keep it off bases that scroll;plainkeeps only the radius and the overflow clip.blur,glassandacrylicdegrade whilemovingis set orautoDetectsenses motion:fallbackMode="mask"prefersfallbackMaskOpacity, andpureandflatrender no mask layer.refractionkeeps its mode in motion: the glass / blur layers that lose their sampling fade out, a translucent motion cover holds the weight, and both cross-fade back on settle.- Passing any of
refractionStrength,refractionAngle, orrefractionProfileswitches to the derived refraction model; unset ones fall back to62/-24/'filmic'. autoDetectlistens on the root and every ancestor for their owntransform/translatetransitions (transitionstart/transitionend/transitioncancel) and watches their inlinestylewith aMutationObserver; the pointer, window, frame-probe and battery listeners are page-wide, shared by every surface withautoDetect, and removed when the last one unmounts.- With
systemBackdrop, the glass layer doesn't render and the filter layer'sbackdrop-filterisnone, keeping its tint; neither the motion fallback nor environment sensing runs. The veil, mask, flow light and rim are unaffected. - Under high contrast (triggers in Theming), every mode but
plainpaints only the opaque root background, likepure: the glass, blur, mask, motion-cover and refraction-edge layers don't render, and thefakebase shows at full opacity;plaingets no fill even then.
Technologies
- Glass and refraction render through
TxGlassSurface; fallback timing lives inbase-surface-motion.ts, and the page-wide environment sensing and material degradation insurface-environment.ts. - Source:
packages/tuffex/packages/components/src/base-surface/.