/** * surface — the shared surface-container class helper. * * A surface container is any panel whose fill, float shadow and corner radius * should move together: cards, menus, modals, sheets, drawers. This combines * the two halves those containers currently spell by hand: * * - the corner-radius token (`rounded-card` / `rounded-menu` / `rounded-modal`, * from {@link ROUNDED_CARD} et al. in radius.ts), and * - the elevation ladder (`bg-surface-N` + `shadow-elevated-N`, from * {@link elevated}). * * Callers whose radius is *not* one of the three tokens (a `rounded-2xl` card, a * `rounded-t-modal` sheet) pass no `radius` and keep that class beside the * result — the elevation half is still shared. `0` is the flat resting surface: * a `surface-3` fill with no shadow or border. * * Every class is spelled as a static literal so the uniwind/Tailwind scanner * registers `rounded-*` / `bg-surface-N` / `shadow-elevated-N` — never build * these by string concatenation from a bare number. */ import { cn } from './cn'; import { elevatedShadow, elevated as elevatedSurface, FLOATING_SHADOW_CLASSNAME, type SurfaceElevation } from './elevated'; import { ROUNDED_CARD, ROUNDED_MENU, ROUNDED_MODAL } from './radius'; // Static literal map — the scanner reads the class names from these values. const SURFACE_RADIUS_CLASS: Record = { card: ROUNDED_CARD, menu: ROUNDED_MENU, modal: ROUNDED_MODAL, }; /** Corner-radius token for a surface container — maps to the radius utility class. */ export type SurfaceRadius = 'card' | 'menu' | 'modal'; /** * Surface classes for an elevation: the radius token (when given) plus the * ladder `bg-surface-N shadow-elevated-N`. At `0` the surface is flat — * `bg-surface-3` alone, no shadow or border. Omit `radius` to keep the caller's * own corner class (a non-token radius like `rounded-2xl`). * * Pass `floating` to swap the ladder shadow for the input field's diffuse halo * (`shadow-floating`). The background tint still follows `elevation` — only the * shadow recipe changes. */ export function surface(elevation: SurfaceElevation, radius?: SurfaceRadius, floating = false): string { return cn(radius ? SURFACE_RADIUS_CLASS[radius] : undefined, elevatedSurface(elevation, elevation, floating)); } /** * Surface classes for a frosted-glass surface: the radius token plus the * elevation shadow, WITHOUT the `bg-surface-N` fill. The `Surface` primitive's * glass mode replaces the opaque ladder fill with the translucent `glass` tint * (thinned by `opacity`) so the backdrop blur shows through — a `bg-surface-N` * fill would composite an opaque wash over the frost and hide it. * * The shadow half is kept: a glass surface still floats at its `elevation` * (the `shadow-elevated-N` rim + drop), it just trades the opaque fill for the * tint. Omit `radius` to keep the caller's own corner class. */ export function glassSurface(elevation: SurfaceElevation, radius?: SurfaceRadius, floating = false): string { return cn(radius ? SURFACE_RADIUS_CLASS[radius] : undefined, floating ? FLOATING_SHADOW_CLASSNAME : elevatedShadow(elevation)); }