# Xenon Full Specification (llms-full.txt) > Complete technical specification, token geometry, accessibility contracts, and full prop tables for all Xenon components. ## Binding Design Rules # Xenon design philosophy Xenon is a quiet UI kit. It earns trust through geometry, restraint and negative space instead of decoration. ## Pillars 1. **Hairline clarity.** Edges are 1px, soft and crisp. Structure comes from borders and dividers. 2. **Flat depth.** No shadows. No gradients. Layers are separated by surface tone and hairlines. 3. **Negative space.** Space is a material. When in doubt, add space, not elements. 4. **Concentric geometry.** Shapes nest with mathematically related radii. Nothing looks alien inside its parent. 5. **Thin type.** Geist Sans at weights 200 to 400, sized larger when lighter (Apple HIG guidance for thin fonts). 6. **Pill-first controls.** Buttons and inputs are pills at the pill radius stop. Groups use pill outer edges and small inner joints. 7. **Apple-grade motion.** Fluid and seamless: no UI state change is ever snappy or abrupt. Brief, purposeful, cancelable, and always reduced-motion safe. 8. **One accent.** One acid accent at a time, chosen globally. Everything else is neutral. 9. **The Design of Everyday Things (Norman Invariant).** Grounded in cognitive ergonomics: affordances, signifiers (e.g. animated rotating chevrons on disclosure triggers), mapping, feedback, conceptual models, constraints, and discoverability. A human or AI must never guess whether an element is interactive or what state it controls. 10. **Apple-grade restraint & anti-bloat.** Ruthless reduction. Floating surfaces, popovers, and dialogs must never be overfilled with redundant widgets, duplicate controls, or decorative preview boxes. Quiet, focused, purposeful simplicity over complexity. ## Banned patterns | Banned | Use instead | | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | | `linear-gradient`, `radial-gradient`, `conic-gradient`, gradient text, mesh blobs | Flat surface tones | | `box-shadow`, `drop-shadow`, `text-shadow`, glow, ring-as-shadow | 1px hairline border, surface tone step | | Emoji and emoji-like glyphs | Phosphor Thin icons | | Card inside card | Divider, spacing, or a header row inside one surface | | Font weight 500 or higher | Size and color for hierarchy | | Raw hex, raw px, raw ms, raw easing in components | Tokens | | Hardcoded `border-radius: 9999px` on large surfaces | Radius tokens with surface cap | | Pure-white text on AMOLED black for body copy | `--x-text` (softened) | | Multiple accents on one screen for decoration | One accent, semantic colors only for status | | Heavy borders (2px+), dashed borders for decoration | 1px hairline | | Decorative animation, parallax, looping motion | Purposeful feedback only | | Instant or snappy UI transitions, uncoordinated `hidden` / `display: none` | Apple-grade fluid transitions (physics springs, easing) | | Mixed icon sets or icon weights | Phosphor `thin` via `Icon` | | Backdrop blur and glassmorphism in the static content layer (cards, inputs, page canvas) | Opaque surfaces (`--x-surface`) | | Overfilling popovers/surfaces with redundant widgets, duplicate controls, or preview boxes | Compact, quiet, single-purpose controls (Apple reduction) | | Interactive disclosure triggers without visual signifiers (e.g. naked text without chevron) | Animated Phosphor CaretDown indicator (0° closed, 180° open) | | Slicing sub-sections/chapters inside a single act with decorative dividers | Preserve Gestalt continuity: Dividers strictly separate macro Acts; use proximity & negative space inside an act | ## Liquid Glass: the floating layer exception Blur is allowed exclusively as **Liquid Glass** on floating and overlay elements `(Apple HIG: Materials)`. Liquid Glass forms a distinct functional layer that floats above scrollable content, letting background elements peek through to preserve spatial context without sacrificing foreground legibility. ### Permitted Floating Scope: - **Navigation & Structural Bars**: Top Navbar (`GlassBar`), Bottom TabBar, Floating Dock/Segmented Bar. - **Floating Action Controls**: Floating action buttons (`IconButton glass`, `Button glass`), floating media/filter controls. - **Floating Overlays**: `Popover`, `CommandPalette`, `Sheet` headers, `Dialog`. ### Strictly Banned in Content Layer: - Never apply glass to standard inline content cards, table rows, form input fields, static inline buttons, or page canvas backgrounds. Glass inside the content layer creates visual chaos and destroys information hierarchy. ### Two Variants: - **`regular`**: High legibility, structural blur for text-bearing chrome, navigation bars, and overlays. - **`clear`**: Ultra-translucent blur for minimal floating action icon pills over rich visual media. ## Overlay Architecture: Anchored Pop-Overs & Hero Kinematics Xenon departs from legacy desktop UI libraries by **abolishing disruptive, view-blocking centered modal dialogs** for common contextual actions. 1. **Anchored Pop-Overs on Web**: - Contextual actions, selectors, and disclosures open as **anchored pop-overs** physically tethered to their trigger element rather than blocking the entire screen. - **Hero / Container Transform Kinematics**: The pop-over smoothly expands directly from the trigger component's coordinates and morphs/collapses back into the trigger upon dismissal (inspired by iOS popover presentations and Android container transform / hero animations). - **Unobstructed Context**: The pop-over surface itself uses **Liquid Glass material** (`var(--x-glass-regular)` with 1px hairline border). **The rest of the UI is NOT blurred or obstructed**—background content remains crisp and legible so the user never loses their train of thought. 2. **Apple-Grade Bottom Sheets on Native**: - On React Native (Expo), anchored desktop floating cards are replaced with gesture-driven **Bottom Sheets** featuring an Apple HIG tactile pill grab handle and interactive drag-to-dismiss kinematics. 3. **Full-Canvas Liquid Glass Scrim**: - Reserved strictly for immersive global overlays: `CommandPalette` (`⌘K`) and full-screen `Sheet` flows, where deep focus on the search or workflow justifies blurring the background canvas. ## What "no AI look" means here Avoid the generic generated-UI look: purple-blue gradients, glowing cards, emoji bullets, oversized rounded cards stuffed with badges, and dense dashboards on landing pages. Xenon pages are sparse, aligned to a grid, and typographically led. ## Showcase tone The landing page is sparse. One idea per viewport. Show real components, not mock screenshots. Lead with the signature features: global radius scale, concentric nesting, grouped controls, accent and theme switching. # Tokens The only allowed values. Tags: `(Apple HIG)` verified against developer.apple.com/design/human-interface-guidelines, `(proposed)` awaiting maintainer sign-off. Tokens are **platform-neutral**. The single source lives in `packages/tokens` (TS). It compiles to CSS variables with the `--x-` prefix for web and to a typed object for React Native. Lengths are unitless numbers: px on web, dp on native. See [ARCHITECTURE.md](ARCHITECTURE.md) and [PLATFORMS.md](PLATFORMS.md). Token names below use the web CSS form; native uses the same name in camelCase (`xTextBody`). ## Global switches Set once on the provider. On web they surface as attributes on ``; on native they live in context. | Switch | Web attribute | Values | | -------- | --------------- | ------------------------------------------------------------------------- | | theme | `data-x-theme` | `dark` (default), `light`, `system` | | accent | `data-x-accent` | `lime` (default), `pink`, `blue`, `purple`, `green` | | radius | `data-x-radius` | `0` sharp, `1`, `2`, `3`, `4`, `5`, `6` pill (discrete only, default `4`) | | platform | n/a | `web` or `native`, set by the renderer package, not by the user | ## Type Font: Geist Sans. Weights 200, 300, 400. Mono (Geist Mono) in code only. Display face: TBD, wordmark and large headings only. Native must load static Geist files for ExtraLight (200), Light (300) and Regular (400), because React Native does not reliably support variable-font weights `(proposed)`. Each text style has a **native** value and a **web** value. - **Native** sizes and line heights are the Apple iOS Large (default) text styles `(Apple HIG: Typography, iOS Dynamic Type sizes)`. - **Web** sizes are Xenon's own, derived from the native scale on a 16px base `(proposed)`. They are in `rem` (px shown at 16px root). Apple's iOS numbers are not copied to web, because web body text runs at 16px and pointer UIs are denser than touch. - Weights are Xenon's own mapping `(proposed)`: Apple Regular maps to 300, Semibold and Bold map to 400, display sizes use 200. | Token | Native size / line | Web size / line (proposed) | Weight | Tracking native / web (em) | | ---------------------- | -------------------- | -------------------------- | ------ | -------------------------- | | `--x-text-display` | 56 / 60 `(proposed)` | 64 / 68 | 200 | +0.006 / +0.004 | | `--x-text-large-title` | 34 / 41 | 40 / 48 | 200 | +0.012 / +0.010 | | `--x-text-title-1` | 28 / 34 | 32 / 40 | 200 | +0.014 / +0.013 | | `--x-text-title-2` | 22 / 28 | 24 / 32 | 300 | -0.012 / +0.003 | | `--x-text-title-3` | 20 / 25 | 20 / 28 | 300 | -0.023 / -0.023 | | `--x-text-headline` | 17 / 22 | 16 / 24 | 400 | -0.026 / -0.020 | | `--x-text-body` | 17 / 22 | 16 / 24 | 300 | -0.026 / -0.020 | | `--x-text-callout` | 16 / 21 | 15 / 22 | 300 | -0.020 / -0.016 | | `--x-text-subhead` | 15 / 20 | 14 / 20 | 300 | -0.016 / -0.011 | | `--x-text-footnote` | 13 / 18 | 13 / 18 | 300 | -0.006 / -0.006 | | `--x-text-caption-1` | 12 / 16 | 12 / 16 | 400 | 0 / 0 | | `--x-text-caption-2` | 11 / 13 | 11 / 14 | 400 | +0.006 / +0.006 | Tracking values come from the SF Pro tracking table at the matching point size `(Apple HIG)`, with the web column using the value for the web size. Geist is not SF, so tune by eye `(proposed)`. Legibility floors `(proposed, derived from Apple's advice to go larger with thin custom fonts)`: weight 200 only at 28 and above. Weight 300 at 13 and above. Below 13 use weight 400. Never go under 11. Native text must scale with the user's font size setting (`allowFontScaling`), capped by `maxFontSizeMultiplier` of 1.4 on chrome (tabs, buttons) and 2.0 on content `(proposed, Apple HIG: do not scale everything)`. Web type uses `rem`. Default control label size: `--x-text-subhead` on web, `--x-text-callout` on native `(proposed)`. ## Space Base unit 4px `(proposed)`. Apple publishes control and padding guidance, not a numeric grid; see `guidelines/spacing-layout.md`. `--x-space-1` 4, `-2` 8, `-3` 12, `-4` 16, `-5` 24, `-6` 32, `-7` 48, `-8` 64, `-9` 96, `-10` 128 `(proposed)`. ## Control size | Token | Height | Notes | | ---------------- | ------------ | ------------------------------------------------------------------------------------------------------------------- | | `--x-control-sm` | 32 | | | `--x-control-md` | 40 (default) | | | `--x-control-lg` | 48 | | | `--x-hit-min` | 44 | Touch hit area minimum (web `pointer: coarse`, native `hitSlop`) `(Apple HIG: Accessibility, iOS 44x44 pt default)` | Heights are `(proposed)`. Apple: iOS default control 44x44 pt, minimum 28x28; macOS default 28x28, minimum 20x20 `(Apple HIG: Accessibility)`. ## Radius Seven stops: sharp, five intermediate, pill `(proposed)`. Controls clamp to half their height. Surfaces clamp to a cap so large areas never go circular. | Stop | Control radius | Surface radius | Group joint | | ------- | ------------------------ | -------------- | ----------- | | 0 sharp | 0 | 0 | 0 | | 1 | 4 | 6 | 2 | | 2 | 8 | 10 | 2 | | 3 | 12 | 16 | 3 | | 4 | 16 | 20 | 4 | | 5 | 20 | 24 | 5 | | 6 pill | 9999 clamped to height/2 | 28 (cap) | 6 | Nested rule: `inner = max(outer - padding, outer * 0.4)`, never above `outer`. See `guidelines/shape.md`. ## Border `--x-border-width` 1px on web. Native uses `StyleSheet.hairlineWidth` for dividers and 1dp for control borders `(proposed)`. Hairline color is a low-alpha neutral: dark `rgba(255,255,255,0.10)`, light `rgba(0,0,0,0.08)` `(proposed)`. Stronger line for focus and hover: 0.20 and 0.16. ## Color Neutrals `(proposed)`: | Token | Dark (AMOLED on) | Dark (AMOLED off / Claude Charcoal) | Light | | ---------------- | ---------------- | ----------------------------------- | ------- | | `--x-bg` | #000000 (AMOLED) | #181816 | #FFFFFF | | `--x-surface` | #0A0A0A | #22211F | #FAFAFA | | `--x-surface-2` | #111111 | #2C2B28 | #F4F4F4 | | `--x-text` | #EDEDED | #EDE8DF | #0A0A0A | | `--x-text-muted` | #A1A1A1 | #9E9B91 | #5C5C5C | Accents `(proposed, contrast to be verified in the tokens implementation step)`: | Accent | Dark | Light (slightly deeper) | | ------ | ------- | ----------------------- | | lime | #D4FF4F | #A8D900 | | orange | #FF7E47 | #D9532F | | pink | #FFB3D9 | #F08BBE | | blue | #9ED8FF | #5FB4F0 | | purple | #CDB4FF | #A78BFA | | green | #9BFFB8 | #4FD683 | `--x-on-accent` is `#0A0A0A` in both themes. Semantic: `--x-danger` #FF8A80 dark and #E5484D light, `--x-warning`, `--x-success`, `--x-info` `(proposed)`. Contrast `(Apple HIG: Accessibility)`: 4.5:1 for text up to 17pt, 3:1 at 18pt and above or bold. Xenon is stricter for thin weights: treat text under 24px as needing 4.5:1 `(proposed)`. ## Motion | Token | Value | | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | `--x-dur-instant` | 100ms | | `--x-dur-fast` | 160ms | | `--x-dur-base` | 240ms | | `--x-dur-slow` | 400ms | | `--x-ease-standard` | `cubic-bezier(0.2, 0, 0, 1)` | | `--x-spring-soft` | stiffness 300, damping 30, mass 1 `(proposed)`. Web compiles it to a `linear()` curve at build time. Native passes the parameters to Reanimated | All values `(proposed)`. Press scale 0.98. Native animates with Reanimated using the same durations and spring parameters. Everything respects `prefers-reduced-motion`. ## Icons Phosphor, weight `thin`: `@phosphor-icons/react` on web, `phosphor-react-native` on native, behind one `Icon` wrapper with the same props. Sizes: 16, 20, 24. Icon color inherits text color. Icons paired with visible text are `aria-hidden`; icon-only controls require an accessible label. ## Liquid Glass Blur is permitted exclusively as **Liquid Glass** on floating and overlay elements `(Apple HIG: Materials)`. Liquid Glass creates a functional floating layer above content, allowing underlying elements to peek through while preserving foreground contrast. Liquid Glass has two variants: - **`regular`** (default): Balanced blur + tint for structural chrome, popovers, dialogs, and text-bearing overlays. - **`clear`**: High-translucency blur for minimal floating icon action buttons, media controls, and floating pill toolbars over rich visual content. | Token | Regular Variant | Clear Variant | | --------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------- | | Blur intensity | 20px web `blur()` / Native `BlurView` intensity ~50 `(proposed)` | 10px web `blur()` / Native `BlurView` intensity ~25 `(proposed)` | | Tint dark (`--x-bg`) | 72% opacity (`rgba(0,0,0,0.72)`) `(proposed)` | 40% opacity (`rgba(0,0,0,0.40)`) `(proposed)` | | Tint light (`--x-bg`) | 80% opacity (`rgba(255,255,255,0.80)`) `(proposed)` | 50% opacity (`rgba(255,255,255,0.50)`) `(proposed)` | | Hairline edge | 1px `--x-border` on exposed content edges | 1px `--x-border` (faint neutral hairline) | | Dimming layer (clear, opt.) | n/a | 35% dark dimming layer when over bright imagery `(Apple HIG)` | | Fallback | Opaque `--x-bg` or `--x-surface` | Opaque `--x-surface-2` or `--x-bg` | ### Rules & Permitted Scope 1. **Permitted Components**: - Navigation and structural bars (`Navbar`/`GlassBar`, `TabBar`, floating segmented bars). - Floating action controls and icon buttons (`IconButton glass`, `Button glass`, floating toolbars). - Floating overlays (`Popover`, `CommandPalette`, `Sheet` drag header, `Dialog`). 2. **Strictly Banned in Static Content**: - Never use Liquid Glass on standard content cards, form inputs, table rows, static inline buttons, or page canvas backgrounds. 3. **No Decorative Extras**: No saturation boost, no multi-color bloom, no gradients, and no drop shadows. 4. **Fallback Handling**: Gracefully falls back to opaque backgrounds when `prefers-reduced-transparency` is active, when `backdrop-filter` is unsupported, or on Android devices with low GPU capabilities. 5. **Component API**: Supported components accept `glass?: boolean | "regular" | "clear"` (`true` defaults to `"regular"`). Dedicated aliases like `GlassBar` are provided for developer ergonomics. 6. **Mirror edge (experimental, web only)**: Open Design-style mirror refraction remains an opt-in web-only prototype. Plain blur remains the universal cross-platform baseline. # Color and motion ## Color 1. **One accent at a time.** The global accent marks the primary action, selected state, focus ring and key indicators. Do not use two accents to decorate one screen. 2. **Neutral by default.** Roughly 90 percent of any screen is neutral surfaces and text; accent covers at most about 10 percent `(proposed)`. 3. **Accent is a fill, not body text on light.** Light-theme accent values are too bright for text on white. Use `--x-text` for text and reserve accent for fills, borders and indicators. 4. **Text on accent** is `--x-on-accent`. Check contrast per accent. 5. **Contrast.** 4.5:1 for text up to 17pt, 3:1 for 18pt and larger or bold `(Apple HIG: Accessibility)`. Xenon asks 4.5:1 for any text under 24px because of thin weights `(proposed)`. Offer an increased-contrast mode. 6. **Never rely on color alone.** Pair status color with an icon or text `(Apple HIG)`. 7. **AMOLED black.** The page is `#000000` in dark. Surfaces step up only slightly (see `TOKENS.md`). Do not use pure white text for body; use `--x-text`. 8. **Semantic colors** (danger, warning, success, info) are for status only, never decoration. 9. **Charts and tags** may use the other named hues, one hue per series, never in the same row as the accent unless they encode data. 10. **No gradients, no transparency tricks to fake depth.** Opacity is used for hairlines and disabled states only. 11. **Disabled** is 40 percent opacity and `cursor: not-allowed`. Never remove a disabled control's label. ## States Every interactive component defines: rest, hover, pressed, focus-visible, disabled, selected, loading and error where relevant. States change border, tone and text color only. They never change size or layout. ## Motion 1. **Purposeful.** Add motion to support understanding, not to decorate `(Apple HIG: Motion)`. 2. **Brief and precise.** Feedback animations are short and unobtrusive. Default 160 to 240ms. 3. **Do not animate frequent interactions.** Avoid extra motion on actions repeated constantly `(Apple HIG)`. 4. **Cancelable.** Users never wait on an animation to continue `(Apple HIG)`. Overlays stay interactive while animating out. 5. **Realistic.** Enter and exit follow the same path. A sheet that slides up exits downward `(Apple HIG)`. 6. **Optional.** Support `prefers-reduced-motion`: replace movement with a fade of at most 100ms. Never convey information by motion alone `(Apple HIG)`. 7. **Press.** Pressed controls scale to 0.98 over 100ms. Release is a spring. 8. **Easing.** Use `--x-ease-standard` for most; `--x-spring-soft` for press release, switch thumbs and sheets. 9. **Animate transform and opacity only.** Never animate layout properties. Use View Transitions for route and theme changes where supported. 10. **Theme and accent switching** crossfades colors in `--x-dur-base`. 11. **Stagger** is allowed on landing page reveals at 40ms steps, maximum 6 items, never on product UI. 12. **Zero instant/snappy transitions.** No UI state change is ever instantaneous or snappy. Disclosures, height changes (via CSS grid `0fr -> 1fr` with inner overflow clipping), active states, carets, appearances, and dismissals must transition with Apple-grade fluid curves (`--x-ease-standard` or physics springs). Never apply HTML `hidden` or `display: none` directly to elements undergoing transitions without presence/unmount coordination. # Interaction, forms and content ## Targets 1. **Hit area.** iOS default control 44x44pt, minimum 28x28; macOS default 28x28, minimum 20x20 `(Apple HIG: Accessibility)`. Xenon controls are 32, 40 or 48 high. On web `pointer: coarse` and on native (`hitSlop`) the hit area expands to at least 44 with invisible padding. Native defaults to `md` or `lg` controls. 2. **Space between targets.** Keep about 12px around bezelled controls, about 24px around bezel-less ones `(Apple HIG)`. 3. **Use style, not size, to mark the primary action.** Same-size buttons form a set of equal choices; make one filled and the others outline or ghost `(Apple HIG: Buttons)`. 4. **One primary per view.** At most one filled accent button in a surface. 5. **Avoid white fill with black text as a custom style.** It reads as a selected or toggled state. 6. **Focus and press.** On web every interactive element has a visible `:focus-visible` ring (2px accent outline, 2px offset); never remove outlines without replacement. On native, show a pressed state and give hardware-keyboard and screen-reader focus a visible ring. 6a. **Hover is an enhancement.** It exists on web under `@media (hover: hover)` only. Touch has none, so every hover cue needs a pressed or focus equivalent. 7. **Keyboard and assistive tech.** Every control works by keyboard on web (WAI-ARIA Authoring Practices) and with VoiceOver and TalkBack on native (`accessibilityRole`, `accessibilityState`). 8. **Mobile keyboards.** Forms scroll the focused field into view, use the right `inputMode` or `keyboardType`, and never let the on-screen keyboard cover the action button. ## Forms 1. **Label above, always visible.** No placeholder-as-label. Placeholder is an example, in muted color. 2. **Help text below the field, error replaces help text.** Error text uses the danger color plus an icon. 3. **Inline validation on blur**, then on change after the first error. Never validate while the user is typing the first time. 4. **One column.** Forms are a single column up to 560px wide. Pair fields only when they are naturally paired (first name, last name). 5. **Required marking.** Mark optional fields as "Optional", not required ones with asterisks. 6. **Group related inputs** with a fieldset and legend, separated by a divider, not by nested cards. 7. **Disable only when useful.** Prefer explaining why an action is unavailable. ## Feedback 1. **Respond within 100ms** with a visible state change. 2. **Loading.** Use a skeleton for content, a spinner inside a button for actions. Keep the button width fixed. 3. **Toast** for non-blocking confirmation, auto-dismissed after 5 seconds, pausable, never the only place an error appears. 4. **Dialogs** for decisions that need attention. They trap focus and restore it on close. Max one stacked dialog. 5. **Empty states** have a short title, one sentence of help, and one action. No illustrations required. 6. **Errors** say what happened and what to do, with no blame and no jargon. 7. **Destructive actions** use a confirm step with the verb in the button ("Delete project"), never "OK". ## Content and microcopy 1. Sentence case. Verbs for actions. Short. 2. No exclamation marks, no emoji, no filler words ("Please", "Simply"). 3. Numbers and units with a space when readable, e.g. `12 items`. 4. Dates in the user's locale. Use relative time only when it is under a day old. 5. Plain labels; avoid trailing ellipsis unless the action opens a further step. ## Accessibility baseline 1. WCAG 2.2 AA minimum. Semantic HTML first, ARIA only to fill gaps. 2. Icon-only controls require `aria-label`. Icons beside text are `aria-hidden`. 3. Respect `prefers-reduced-motion`, `prefers-contrast`, `prefers-color-scheme`, and user font size. 4. Do not trap keyboard focus except in modal dialogs. 5. Touch, pointer and keyboard are equal citizens. ## The Design of Everyday Things (Norman Principles) All Xenon components strictly adhere to Don Norman's cognitive design framework: 1. **Affordances & Signifiers**: - Every clickable, draggable, or expandable element must visually signal its affordance. - Disclosure and dropdown triggers must feature an animated Phosphor `thin` chevron (`CaretDown`) that rotates smoothly on open/close (`0deg` closed, `180deg` open). Naked labels without signifiers are banned for disclosures. 2. **Apple-grade Restraint & Anti-Bloat**: - Never overfill popovers or dialogs with redundant controls, duplicated buttons, or unnecessary preview boxes. - If a slider or segmented control already manipulates a property, do not stack duplicate button rows or extraneous decorative containers below it. Ruthless reduction produces calm elegance. 3. **Feedback & Realtime Indication**: - Every input change provides instant, tactile feedback (<100ms). - Selection controls communicate state directly through the control itself and clear metric readouts. 4. **Natural Mapping**: - Controls follow natural spatial progression: stepped sliders progress left-to-right from minimum to maximum, incrementing logically. 5. **Physical & Logical Constraints**: - Prevent user error by constraining options to valid discrete states (e.g., 7 discrete radius stops 0–6 rather than arbitrary fractional inputs; clamped popup surfaces to prevent corner clipping). 6. **Conceptual Clarity & Discoverability**: - The interface must communicate its state clearly at all times, ensuring both humans and AI agents share an accurate, transparent conceptual model. # Shape, radius and nesting ## Radius scale Seven discrete stops from sharp (0) to pill (6), set globally via `data-x-radius`. Values are in `TOKENS.md`. The scale is discrete only; there is no continuous slider. ## Controls versus surfaces - **Controls** (button, input, chip, switch, segmented) take the control radius for the stop, clamped to half their height. At stop 6 they are pills. - **Surfaces** (card, dialog, sheet, popover) take the surface radius for the stop, capped at 28px. A pill stop never makes a large surface circular. - Never write `border-radius: 9999px` on a surface. Use `--x-radius-surface`. ## Concentric nesting (Apple strategy) When a child sits inside a parent with padding `p`, the child radius is the parent radius minus `p`, so the curves share a center. On web the formula is CSS; on native it is `computeNestedRadius` from `packages/core`, with the parent radius and padding supplied by context. ```css .child { border-radius: max( calc(var(--x-r-parent) - var(--x-pad)), calc(var(--x-r-parent) * 0.4) ); } ``` - `--x-r-parent` is the nearest ancestor surface or control radius. `--x-pad` is the padding between parent and child edges. Both are set by the parent component and read by children. - **Floor.** The result never drops below 40 percent of the parent radius. This prevents a near-square button inside a large rounded surface `(proposed)`. - **Ceiling.** The result never exceeds the parent radius. - A pill control inside a surface follows the same math; its radius is also clamped to half its own height. - Padding larger than the parent radius collapses to the floor. Example: surface radius 24, padding 8, child radius 16. Surface radius 24, padding 24, child radius 9.6 (the floor). ## Grouped controls Button groups, input groups and segmented controls share edges. - Outer corners use the control radius (pill at stop 6). - Inner joints use the group joint radius from `TOKENS.md` (about 25 percent of the outer radius). - Joints are separated by one hairline, not by a gap and not by doubled borders. - Hover and focus raise the border of the active segment only; z-index brings it above neighbours. - Groups have one height. Mixed sizes are not allowed. ## No card nesting A surface never contains another surface with its own border and fill. Inside a surface, group with: 1. Dividers. 2. Spacing. 3. Header and footer rows. 4. Tone steps only for transient states such as hover and selected, never as permanent inner boxes. Controls inside a surface are allowed; they are controls, not cards. ## Hairlines - 1px, soft, low-alpha neutral (see `TOKENS.md`). Never 2px, never dashed for decoration. Native dividers use `StyleSheet.hairlineWidth`. - Use device-pixel-aware rendering: align the hairline to whole pixels, and do not scale elements by fractions that blur edges. - A surface has a border or a tone step against its parent, not both strongly. Dark theme surfaces use a border and a faint tone step. - No shadows and no glows, including Android `elevation` and iOS `shadow*` props. Web focus uses a 2px offset ring in the accent color, drawn as `outline`, not as a shadow. ## Icons in shapes Icon buttons are circles at stop 6 and rounded squares of control radius at lower stops. Icon is centred, 20px in a 40px control. # Spacing and layout 1. **Use the space scale only.** 4, 8, 12, 16, 24, 32, 48, 64, 96, 128 `(proposed)`. Pick, do not compute. No odd values like 10 or 20. 2. **Group by proximity.** Related items sit closer than unrelated ones. Gap inside a group is at most half the gap between groups. 3. **Negative space is the default.** Surface padding starts at 24. Section spacing on pages starts at 96. Dense layouts are opt-in and labelled `density="compact"`. 4. **Padding around controls.** About 12pt around elements with a bezel, about 24pt around elements without one `(Apple HIG: Accessibility)`. Keep that distance between adjacent interactive items. 5. **Alignment is relationship.** Aligned items read as related; indented items read as subordinate `(Apple HIG: Layout)`. Align to one left edge per column. Use indentation only for hierarchy. 6. **Optical padding.** Pill controls need more horizontal padding than vertical: horizontal is at least `height / 2`. Text must not touch the curve. 7. **Surface padding is symmetric** unless a header row or footer row is present. Header and footer are separated by a divider, not an inner card. 8. **Page and dashboard width.** Web content max width 1120, prose 680, wide showcase / docs 1280, dashboard layout max width 1440 to 1600 `(proposed)`. On large or ultrawide displays (21:9 / 32:9), never allow dashboard content to stretch arbitrarily edge-to-edge; cap the container and let outer negative space breathe naturally. Side margin is 24 on phone, 48 on tablet and 64 on desktop. 9. **Grid.** 12 columns, 24 gutter on desktop, 16 on mobile. Components snap to column edges. 10. **One focal point per viewport.** Landing sections hold one idea, one headline, one visual. 11. **Vertical rhythm.** Section gap 96 to 128, heading to content 24 to 32, paragraph gap 16. 12. **Safe areas.** Respect `env(safe-area-inset-*)` on web and `react-native-safe-area-context` on native for fixed bars and sheets `(Apple HIG: Layout)`. 13. **Adaptive layout.** Layout must survive resizing, rotation and window changes without changing familiarity `(Apple HIG: Layout)`. Design mobile first, then widen. 14. **Density levels.** `comfortable` (default), `compact` (steps controls down one size and padding down one space step). Never mix levels in one surface. 15. **Dividers & Act Boundaries (Gestalt Continuity).** Use a divider instead of a box. Hairline, full width of the group, with inset equal to the surface padding when inside a list. On pages and narrative showcase surfaces, dividers strictly demarcate **macro structural transitions between major Acts** (e.g. above the Act I headline, above the Act II headline, above the Act III headline, and above the closing CTA). **Never place arbitrary horizontal dividers between consecutive scenes, chapters, or sub-sections inside a single act.** Sub-sections within an act must remain visually and narratively connected through negative space, vertical rhythm, and proximity (`gap inside < gap between`). Slicing content within an act shatters Gestalt continuity, creating disjointed micro-islands instead of a unified, fluid journey. 16. **Lists.** Row height at least 44 on touch; separate rows with a hairline, not spacing and background. 17. **Sticky bars.** Fixed headers and tab bars are either opaque (`--x-bg` plus a hairline) or a `GlassBar`. No other blurred or translucent element exists. 18. **Z-order.** Page, surface, popover, dialog, toast. Only overlays sit above surfaces, each separated by a hairline plus a scrim at 60 percent black in dark theme, 30 percent in light `(proposed)`. 19. **Sidebar architecture.** - **Default: background-less** (`hasBackground={false}`). The sidebar lives directly on the page canvas (`--x-bg`), letting navigation float quietly in negative space without boxing in the UI. - **Separator**: Separator-less by default (`separator={false}`) in documentation and sparse layouts where whitespace provides the natural visual boundary. An optional 1px hairline right separator (`separator={true}`) is available for users and dense dashboards that require structural guidance. - **Solid / Muscular variant**: When a dense application specifically requires a grounded, framed console look, `hasBackground={true}` applies `--x-surface` to the sidebar. # Typography 1. **Use the text styles, never ad hoc sizes.** Pick a style from `TOKENS.md`. Apple defines a style as weight, size and leading together `(Apple HIG)`. 2. **Hierarchy by size and tone, not weight.** Xenon caps weight at 400. Separate levels with size steps and `--x-text` versus `--x-text-muted`. 3. **Go larger when lighter.** Apple advises larger-than-recommended sizes for thin custom fonts `(Apple HIG)`. Weight 200 starts at 28px, weight 300 at 13px. 4. **Floors.** Apple's iOS default is 17pt and minimum 11pt; macOS default 13pt and minimum 10pt `(Apple HIG)`. On native, body is 17pt. On web, body is 16px and the scale is derived from Apple's `(proposed)`. Never under 11. 5. **Few typefaces.** Geist Sans, plus Geist Mono in code, plus the display face for wordmark and display headings only `(Apple HIG: minimize typefaces)`. 6. **Tracking tightens as size grows to about 20px, then loosens.** Apply the tracking column in `TOKENS.md` for the platform. Never add tracking by hand. 7. **Measure.** Prose width 55 to 75 characters (about 560 to 680px). Cap with `max-width` in `ch`. 8. **Line height.** Use the paired value from the style. Do not set `line-height` separately. 9. **Alignment.** Left align text. Center only short headings and single lines. Never justify. 10. **One heading level per idea.** Do not skip levels. One display or large-title per page. 11. **Case.** Sentence case for UI labels and headings. No all-caps, except tiny overline labels at caption-2 with tracking `(proposed)`. 12. **Numbers.** Use tabular figures (`font-variant-numeric: tabular-nums`) in tables, stats and timers. 13. **Truncation.** Truncate rarely. Allow wrapping in labels. Truncate only single-line list items and always provide the full text in a tooltip or detail view `(Apple HIG: Dynamic Type)`. 14. **Respect user text size.** Web uses `rem` so browser settings scale it. Native honors the OS font scale within the caps in `TOKENS.md`. Test at 200 percent. 15. **Do not scale everything.** When text grows, tab titles and chrome stay fixed; prioritize content `(Apple HIG)`. 16. **Links.** Underline with a hairline offset, or accent color plus underline on hover. Never color alone. 17. **Code.** Geist Mono at footnote size, on `--x-surface`, with a hairline border. ## Design Tokens - **Themes**: `dark` (default), `light` - **AMOLED Mode**: `data-x-amoled='true'` (#000000 pure canvas background) - **Accents**: `lime` (#D4FF00 dark / #4D7C0F light), `orange`, `pink`, `blue`, `purple`, `green` - **Radius Stops**: R0 (0px), R1 (4px), R2 (8px), R3 (12px), R4 (16px), R5 (20px - default), R6 (9999px pill) - **Control Heights**: sm (32px), md (40px), lg (48px) - **Touch Target Floor**: 44px minimum hit area - **Spring Physics**: springSoft (stiffness 300, damping 30), springSnappy (stiffness 400, damping 28) ## Components Detailed API --- ### Button (`button`) **Category**: Primitives **Description**: Signature pill-first action control with physics-based spring squash interaction (0.98 scale on press). **Accessibility**: Rendered as native button element with role='button', supports Space and Enter keys, manages disabled and aria-busy states. **Install**: `npm install @xenon-kit/web @phosphor-icons/react` | `npx @xenon-kit/cli init` #### Props | Name | Type | Default | Required | Description | | :--- | :--- | :--- | :--- | :--- | | `variant` | `'accent' | 'filled' | 'subtle' | 'outline' | 'ghost' | 'glass'` | `'filled'` | No | Visual hierarchy and surface style. | | `size` | `'sm' | 'md' | 'lg'` | `'md'` | No | Touch target and padding scale. | | `glassType` | `'regular' | 'clear'` | `'regular'` | No | Liquid Glass material type when variant='glass'. | | `disabled` | `boolean` | `false` | No | Disables interaction with 40% opacity. | | `loading` | `boolean` | `false` | No | Displays loading spinner and sets aria-busy. | | `fullWidth` | `boolean` | `false` | No | Expands button width to 100% of container. | | `onClick` | `(event: MouseEvent) => void` | - | No | Click event handler. | | `children` | `ReactNode` | - | No | Button content. | #### Web Usage ```tsx import { Button } from "@xenon-kit/web"; export function Example() { return ( ); } ``` #### Native Usage ```tsx import { Button } from "@xenon/native"; export function Example() { return ( ); } ``` --- ### IconButton (`icon-button`) **Category**: Primitives **Description**: Concentric circular action button strictly optimized for Phosphor Thin icons with mandatory accessible labeling. **Accessibility**: Enforces non-empty ariaLabel prop, rendered with role='button' and accessible screen reader name. **Install**: `npm install @xenon-kit/web @phosphor-icons/react` | `npx @xenon-kit/cli init` #### Props | Name | Type | Default | Required | Description | | :--- | :--- | :--- | :--- | :--- | | `ariaLabel` | `string` | - | **Yes** | Mandatory accessible description for screen readers. | | `variant` | `'accent' | 'filled' | 'subtle' | 'outline' | 'ghost' | 'glass'` | `'subtle'` | No | Surface styling. | | `size` | `'sm' | 'md' | 'lg'` | `'md'` | No | Icon and target dimension. | | `glassType` | `'regular' | 'clear'` | `'regular'` | No | Liquid Glass material type when variant='glass'. | | `disabled` | `boolean` | `false` | No | Disables button interactions. | | `loading` | `boolean` | `false` | No | Displays loading spinner. | | `onClick` | `(event: MouseEvent) => void` | - | No | Click event handler. | | `children` | `ReactNode` | - | No | Phosphor Thin icon element. | #### Web Usage ```tsx import { IconButton, Icon } from "@xenon-kit/web"; import { Gear } from "@phosphor-icons/react"; export function Example() { return ( ); } ``` #### Native Usage ```tsx import { IconButton, Icon } from "@xenon/native"; export function Example() { return ( ); } ``` --- ### ButtonGroup (`button-group`) **Category**: Primitives **Description**: Grouped capsule action bar where child buttons share outer bounds and internal 1px hairline dividers. **Accessibility**: Wraps buttons in a role='group' container with optional aria-label. **Install**: `npm install @xenon-kit/web @phosphor-icons/react` | `npx @xenon-kit/cli init` #### Props | Name | Type | Default | Required | Description | | :--- | :--- | :--- | :--- | :--- | | `variant` | `'accent' | 'filled' | 'subtle' | 'outline' | 'ghost' | 'glass'` | `'outline'` | No | Default variant passed to children. | | `size` | `'sm' | 'md' | 'lg'` | `'md'` | No | Default button size. | | `disabled` | `boolean` | `false` | No | Disables all child buttons. | | `children` | `ReactNode` | - | No | Button elements. | #### Web Usage ```tsx import { ButtonGroup, Button } from "@xenon-kit/web"; export function Example() { return ( ); } ``` #### Native Usage ```tsx import { ButtonGroup, Button } from "@xenon/native"; export function Example() { return ( ); } ``` --- ### Surface (`surface`) **Category**: Primitives **Description**: Base structural container supporting concentric radius inheritance and Apple HIG Liquid Glass floating layers. **Accessibility**: Semantic generic container, transparent to screen readers. **Install**: `npm install @xenon-kit/web @phosphor-icons/react` | `npx @xenon-kit/cli init` #### Props | Name | Type | Default | Required | Description | | :--- | :--- | :--- | :--- | :--- | | `variant` | `'default' | 'subtle' | 'glass'` | `'default'` | No | Background surface tone and treatment. | | `glassType` | `'regular' | 'clear'` | `'regular'` | No | Liquid Glass material for floating layers. | | `radius` | `RadiusStop | number` | `inherit` | No | Explicit corner radius override (clamped). | | `padding` | `number` | `24` | No | Internal content inset in pixels. | | `children` | `ReactNode` | - | No | Surface content. | #### Web Usage ```tsx import { Surface, Text } from "@xenon-kit/web"; export function Example() { return ( Concentric surface layer ); } ``` #### Native Usage ```tsx import { Surface, Text } from "@xenon/native"; export function Example() { return ( Concentric surface layer ); } ``` --- ### Typography (Text & Heading) (`typography`) **Category**: Primitives **Description**: Apple HIG calibrated Geist Sans typography system restricted strictly to light weights (200, 300, 400). **Accessibility**: Emits semantic h1-h6 headings and p/span elements with appropriate text hierarchy. **Install**: `npm install @xenon-kit/web @phosphor-icons/react` | `npx @xenon-kit/cli init` #### Props | Name | Type | Default | Required | Description | | :--- | :--- | :--- | :--- | :--- | | `styleKey` | `'display' | 'largeTitle' | 'title1' | 'title2' | 'title3' | 'headline' | 'body' | 'callout' | 'subhead' | 'footnote' | 'caption1' | 'caption2'` | `'body'` | No | Apple HIG typography scale tier. | | `weight` | `200 | 300 | 400` | `300` | No | Font weight (weights >= 500 are banned in Xenon). | | `tone` | `'default' | 'muted' | 'accent' | 'danger' | 'warning' | 'success' | 'info'` | `'default'` | No | Color token tone. | | `align` | `'left' | 'center' | 'right'` | `'left'` | No | Text alignment. | | `tabular` | `boolean` | `false` | No | Enables tabular mono digits for numbers. | | `truncate` | `boolean` | `false` | No | Truncates overflow with ellipsis. | | `as` | `'p' | 'span' | 'div' | 'label'` | `'p'` | No | Underlying HTML element tag for Text. | #### Web Usage ```tsx import { Heading, Text } from "@xenon-kit/web"; export function Example() { return ( <> Minimalist Architecture Geist typography with negative space. ); } ``` #### Native Usage ```tsx import { Heading, Text } from "@xenon/native"; export function Example() { return ( <> Minimalist Architecture Geist typography with negative space. ); } ``` --- ### Input (`input`) **Category**: Form Controls **Description**: Restrained architectural text field (6-8px radius, 12px optical padding) avoiding stadium pill shapes. **Accessibility**: Accessible input element supporting ARIA descriptions, errors, and clear triggers. **Install**: `npm install @xenon-kit/web @phosphor-icons/react` | `npx @xenon-kit/cli init` #### Props | Name | Type | Default | Required | Description | | :--- | :--- | :--- | :--- | :--- | | `size` | `'sm' | 'md' | 'lg'` | `'md'` | No | Height and typography scale. | | `variant` | `'default' | 'search'` | `'default'` | No | Field variant style. | | `placeholder` | `string` | `''` | No | Subtle ghost prompt text. | | `disabled` | `boolean` | `false` | No | Disables interaction. | | `clearable` | `boolean` | `false` | No | Shows clear trigger on text presence. | | `invalid` | `boolean` | `false` | No | Highlights 1px boundary in danger tone. | | `surface` | `'surface' | 'subtle'` | `'subtle'` | No | Background surface tone. | | `prefix` | `ReactNode` | `undefined` | No | Icon or badge inside left boundary. | | `suffix` | `ReactNode` | `undefined` | No | Icon or shortcut badge inside right boundary. | | `shortcutKey` | `string` | - | No | Keyboard shortcut hint badge displayed on right. | #### Web Usage ```tsx import { Input } from "@xenon-kit/web"; export function Example() { return ; } ``` #### Native Usage ```tsx import { Input } from "@xenon/native"; export function Example() { return ; } ``` --- ### Field (`field`) **Category**: Form Controls **Description**: Persistent structural wrapper binding labels, helper annotations, and error callouts to input controls. **Accessibility**: Connects label and input via htmlFor/id, injects aria-describedby for errors and helper texts. **Install**: `npm install @xenon-kit/web @phosphor-icons/react` | `npx @xenon-kit/cli init` #### Props | Name | Type | Default | Required | Description | | :--- | :--- | :--- | :--- | :--- | | `label` | `string` | - | **Yes** | Persistent top label text. | | `helpText` | `string` | - | No | Supporting helper guidance text. | | `error` | `string` | - | No | Error message displayed in danger tone. | | `optional` | `boolean` | `false` | No | Displays subtle optional indicator tag. | | `htmlFor` | `string` | - | No | Associated control ID for accessible binding. | | `children` | `ReactNode` | - | No | Form control element. | #### Web Usage ```tsx import { Field, Input } from "@xenon-kit/web"; export function Example() { return ( ); } ``` #### Native Usage ```tsx import { Field, Input } from "@xenon/native"; export function Example() { return ( ); } ``` --- ### Textarea (`textarea`) **Category**: Form Controls **Description**: Architectural multi-line text input with smooth auto-expansion, character limit tracking, and hairline borders. **Accessibility**: Standard textarea element with full keyboard and screen reader accessibility. **Install**: `npm install @xenon-kit/web @phosphor-icons/react` | `npx @xenon-kit/cli init` #### Props | Name | Type | Default | Required | Description | | :--- | :--- | :--- | :--- | :--- | | `size` | `'sm' | 'md' | 'lg'` | `'md'` | No | Dimension and typography scale. | | `rows` | `number` | `3` | No | Initial visible line count. | | `placeholder` | `string` | - | No | Ghost prompt text. | | `disabled` | `boolean` | `false` | No | Disables interaction. | | `invalid` | `boolean` | `false` | No | Danger error state. | | `maxLength` | `number` | - | No | Enforces max character limit with live counter. | #### Web Usage ```tsx import { Textarea } from "@xenon-kit/web"; export function Example() { return