OS Shell design language
Parent entry: [DESIGN.md](./DESIGN.md) (product posture, tokens map, anti-pattern summary).
Parent entry: DESIGN.md (product posture, tokens map, anti-pattern summary).
This document is shell-only: desktop scene, top bar, dock, window system, and embed boundaries. Sub-app content rules live in app-design-language.md.
Visual language (shell)
The shell should feel precise, calm, and hardware-ordered: clear stacking, readable controls, thin borders and light shadow before heavy elevation, subtle glass that supports depth (not decoration). Neutral surfaces with restrained accent; accent signals action or system emphasis, not decoration.
Do not clone macOS/Windows/iOS metaphors (traffic lights, Start menu, home grid). Take inspiration from real OS ergonomics without copying trademark UI.
Shell composition
Desktop scene
Spatial host for work: wallpaper / gradient field (--os-desktop-background), optional atmospheric overlay, and normalized window stacking. The scene should imply stable space — edges, safe margins, and max width (--os-desktop-max-width) where the layout demands it.
Top bar (ShellBar)
Global band for identity, shell status, primary navigation anchors, and future command entry. Stays visually lighter than window titlebars; uses compact control height tied to --os-shellbar-height and density.
Dock
Launcher strip: pins, running affordance, and app identity at a glance. Uses dock-radius (--os-radius-dock) and bottom-safe offsets so it floats above the workspace without fighting window corners.
Window grammar
- Frame: rounded outer shell (
--os-radius-window), titlebar height (--os-titlebar-height), window shadow (--os-shadow-window) for elevation over desktop. - Body:
WebsiteAppHostand similar use--os-window-body-backgroundand--os-window-body-paddingso content is inset consistently across density. - Chrome: custom macOS-adjacent traffic-light controls and drag targets live in
@prox-os/os-ui(WindowFrame,Titlebar,WindowControls). The controls are Próx shell components, not browser or host OS widgets.
Active / inactive states
Active window: stronger border/contrast, title readability, shadow read as “foreground”. Inactive: toned ink, softer border, no loss of structure — user must still identify the app and recover focus quickly.
Focus, layer, resize, drag
- Focus: keyboard and pointer focus rings stay subtle (thin ring / high contrast on neutral), no neon halos.
- Layering: z-order follows window manager rules; menus and tooltips sit above frames; toast / system notices use panel/window shadow tokens.
- Drag / resize: interactions should be interruptible and low-latency (
react-rndetc.); ghosting or lag is a bug, not a feature.
Spaces And Mission Control
The shell supports multiple desktop Spaces and dedicated fullscreen Spaces. Mission Control should feel like a calm OS-level overview, not a marketing hero:
Control Shift Up: show the Spaces strip. The strip enters from the top, uses a restrained glass surface, and shows desktop/fullscreen thumbnails.Control Shift Down: show current desktop windows only. Windows scale with transform/opacity; do not reflow heavy app interiors.Control Shift Left/Right: slide between Spaces with a short horizontal transform.- Titlebar double-click zooms the window inside the current desktop Space.
- The green titlebar control enters or exits a fullscreen Space. Hovering it on the active window opens the window resize menu; inactive windows reveal traffic-light colors on hover without opening menus.
- Mission Control desktop thumbnails show a hover
Xaffordance when the desktop can be closed. Fullscreen Space thumbnails show a hover shrink affordance that returns the app to its origin desktop.
This intentionally splits two macOS-adjacent behaviors: Control Shift Up is the OS-level Space switcher, while Control Shift Down is the current-desktop window overview. If a future combined mode is added, it should still keep these two mental models visible instead of turning the shortcut handler into hidden state.
Mission Control thumbnails must reuse the active desktop background token (--os-desktop-background) so they read as miniature desktops, not generic white cards. The Space strip layout centers the list when there are only a few Spaces, keeps the list scrollable when many Spaces exist, and reserves the far-right edge for Space creation. Hovering the + affordance previews a new desktop thumbnail that slides in from the right edge toward the button; clicking creates and switches to the new desktop Space. Normal desktop Spaces are capped at 17.
Dragging a window to the top edge and holding there can open Mission Control as a drop target. Existing desktop thumbnails use a selected state when hovered as a drop target; insertion positions show a translucent temporary desktop with a + between or outside the current Space queue. Fullscreen Space thumbnails stay visible for context but are not normal window drop targets.
Window edge snap should remain readable and predictable: corners produce quarter layouts, left/right edges produce half layouts, and the top edge toggles desktop zoom. The resize menu also exposes top-half and bottom-half placement for deliberate keyboard-free arrangement. Dragging an already desktop-zoomed window restores the previous layout before the drag continues.
The resize menu uses compact icon tiles instead of text-heavy directional rows. Its sections are Move & Resize, Fill & Arrange, and a Full Screen submenu so common window placement, desktop zoom, centering, and fullscreen Space entry remain in one active-window affordance.
Use lightweight blur only on the top strip, avoid stacking blur over every window, and respect prefers-reduced-motion.
Website Mode
Website mode is a single-app browsing surface using /website route suffixes. True fullscreen app Spaces use /spaces/:spaceId; they are separate OS Spaces rather than website-mode routes.
Local vs iframe / micro apps
The shell hosts local modules and iframe (or remote) surfaces. Boundary: shell owns frame, drag stack, and manifest; hosted app owns interior pixels. Communication crosses app contract, embed URL, or postMessage patterns — not private shell imports.
Technology position
Bundler-agnostic language. Current stack: React, TypeScript, Tailwind CSS v4 (PostCSS), Rsbuild in apps/os-shell. Do not couple look-and-feel to Rsbuild.
UI library policy
Shell chrome is implemented with custom composition in packages/os-ui, backed by packages/design-tokens.
Later allowances: Radix-style primitives for accessibility, Floating UI for positioning, Motion for short functional transitions.
Avoid large visual kits for OS chrome. Sub-apps may adopt other UI libraries when appropriate; shell stays opinionated.
Animation
Motion is subtle, fast, interruptible, functional. Do not use motion to mask unclear state. Respect prefers-reduced-motion (global overrides exist in shell App.css).
Component Layering and UI Encapsulation
Define what belongs in packages/os-ui, what belongs in apps/shell orchestration, and how headless primitives should be sealed. Visual tokens are documented in [
Sub-app design language
This document applies to **applications** hosted inside or beside the OS Shell: