Surface
Liquid Glass passive visual surface with consumer-owned semantic and interaction facts.
liquid-glass-surface-root is a draft workspace Surface atom. It preserves one content slot and consumes visual inputs without becoming a Button, link, code panel, preview panel, or page-specific component. Liquid Glass inherits the Base Surface contract through asSurfaceRoot() and realizes it with family feedback rules.
This is a conventional, non-refractive Surface projection. The default outline is opaque; transparent and scrim are explicit ordinary-paint variants. It establishes neither full family coverage nor an upstream component API compatibility claim. In particular, the Liquid Glass Surface adds no blur, refraction or experimental material consumer; ordinary transparent/scrim paint and opacity fades are not optical Liquid Glass.
The demo passes explicit passive states into real package prototypes. The focus and press samples are visual facts, not clickable or focusable controls. Outer spacing and the inner content padding belong to the example. No event handler is added to make a Surface pretend to be a Button.
Use Surface
Section titled “Use Surface”import * as React from 'react';import { createReactAdapter } from '@proto.ui/adapter-react';import { surfaceRoot } from '@proto.ui/prototypes-liquid-glass/surface';
const Surface = createReactAdapter(React)(surfaceRoot);
export function Summary() { return ( <Surface variant="muted" radius="md" border="none"> <div style={{ padding: '1rem' }}>Saved locally</div> </Surface> );}The /surface subpath and package root export surfaceRoot; SurfaceRootProps and SurfaceRootExposes describe the shared contract. Base additionally exports asSurfaceRoot and SurfaceRootAsHookContract for family authoring. Do not put a Surface inside an interactive owner and give it another role, tab stop or activation handler. When using a native anchor, retain navigation, keyboard behavior, target and download on that anchor.
Inputs
Section titled “Inputs”| Prop | Values | Default |
|---|---|---|
variant | transparent, outline, secondary, muted, accent, solid, scrim | outline |
radius | default, none, sm, md, lg, xl, full | default |
border | all, bottom, none | all |
elevation | none, raised | none |
transitionState | closed, entering, entered, leaving | entered |
fade | boolean | false |
hovered | boolean | false |
focusVisible | boolean | false |
pressed | boolean | false |
current | boolean | false |
hovered, focusVisible, pressed and current are facts supplied by the existing semantic owner. Surface does not detect pointer, focus, keyboard, selection or navigation state itself. It owns no exposed state, event, method, accessible role or native property. current is a presentation input, not an aria-current implementation. A caller that needs a real Button should compose the governed Button protocol.
Removing an input restores its default. secondary selects the family secondary foreground/background rather than deriving a variant from elevation. Default radius and paint are family-specific; a shared prop vocabulary does not imply identical appearance. Content and layout remain consumer-owned. Use Text with tone="inherit" when a styled Text child must retain the enclosing Surface foreground.
Observe an existing Transition
Section titled “Observe an existing Transition”fade opts into family-owned opacity presentation. In a styled projection, fade=true makes closed and leaving map to opacity zero, while entering and entered map to opacity one. The transitionState is a fact from the existing Transition owner; Surface creates no second clock, scheduling policy, phase events or completion signal. With fade=false, phase input does not enable this opacity mapping.
The Web surface-fade token consumes --pui-surface-transition-duration, defaulting to 0ms. A Web composition can forward the existing owner’s resolved duration through this variable; it must validate finite, non-negative milliseconds. There is no universal 220ms default and no Surface duration prop. Reduced-motion handling and starting opacity are bounded Web style behavior, not proof that native targets support dynamic CSS variables.
scrim selects the family’s conventional dimming paint. It adds no material sampling, blur or refraction. Opacity zero is not an instruction to disable, make inert, unmount or remove semantic ownership: the existing Dialog/Transition or other semantic owner still gates interaction, presence and focus. Surface does not manage any of those responsibilities.
Host and Compiler boundary
Section titled “Host and Compiler boundary”Surface uses the ordinary public Prototype, Props and Feedback paths. The bounded conformance slice exercises Web Components, React, Vue 3 and Vue 2. The source-built CLI registers <family>-surface for those four facade targets, and the Web style compiler consumes the actual family tokens; gpui facade generation is explicitly unsupported. Its supported Web adapter and compiler evidence must be read separately: successfully displaying a Web projection is not proof of complete native support or arbitrary Prototype AOT. No host-specific material backend, screenshot capture, navigation service or code renderer is hidden in Surface. Unsupported target or style diagnostics must remain explicit instead of being treated as equivalent output.
Authority
Section titled “Authority”P-LIQUID-GLASS-SURFACE and T-SURFACE-0001 govern this draft slice. Source: packages/prototypes/liquid-glass/src/surface/.