Skip to content
UI
Language:en Author:AtomForge

Mental models

Three ideas explain most of the library's behavior.

1. Root provides context; descendants consume it

Root creates the theme state and the Modal, Drawer, Popup, and Toast managers, plus their containers.

flowchart TD
  L[Layout component] -->|renders| R[Root]
  R --> P[Page component]
  P -->|"getModalManager() at init"| M[Modal manager]
  P -->|"getToastManager() at init"| T[Toast manager]

A component that merely renders Root is not inside it. Call context getters in a descendant, during initialization, and use the returned manager later in event handlers.

Overlay managers

Root provides four imperative managers for overlay UI. Modal and Drawer opening APIs return result promises; Popup opening APIs also return promises, with replacement and pending-open limitations documented in Popup. Toast's show() returns an identifier. Retrieve all context getters during descendant component initialization, then use the managers in event handlers.

Toast

const toast = getToastManager();
toast.show('File saved!', { type: 'success' });
toast.show('Upload failed.', { type: 'error', duration: 0 });
const modal = getModalManager();
const result = await modal.open(ConfirmDialog, { message: 'Delete this?' });

Drawer

const drawer = getDrawerManager();
const result = await drawer.open(SettingsPanel, {}, { position: 'right', size: 'normal' });
const popup = getPopupManager();
const result = await popup.open.component(ContextMenu, { config: [...] }, { anchor: event });

None of these require manual container placement beneath <Root>. Root does not supply application validation or complete overlay accessibility; see Overlays.


2. Overlays are managers, not components

Modal is not a <Modal> tag. You call modal.open(Component, props) and await a result. Dismissal may resolve with undefined, so only an explicit value should authorize an action. Each overlay has its own result contract; see Overlays.

3. Semantic color tokens

Colors come in pairs (bg-surface with text-surface-contrast) that flip meaning between light and dark. Never hardcode Tailwind scales or hex values.

Core Philosophy: The Contrast Model

Every functional color in Atom Forge has a corresponding -contrast token. This ensures that text and icons are always legible, regardless of the active theme or the specific background color used.

  • Automatic Adaptability: When you switch to Dark Mode, the tokens don't just change shades—they flip their meaning. For example, primary is dark in light mode but becomes light in dark mode.
  • Zero Hardcoding: Never use numbered Tailwind scales like stone-500 or hex codes in your components. By sticking to semantic tokens, your UI will perfectly support custom themes and branding.

Surface Hierarchy

Surfaces define the physical structure of your app. They create depth and help users distinguish between layout containers and interactive content.

Token Utility Pair Description
bg bg-canvas / text-canvas-contrast Body background. The deepest layer of the application shell.
surface bg-surface / text-surface-contrast Component surface. Used for cards, panels, modals, and drawers.
muted bg-muted / text-muted-contrast Subtle background. Ideal for disabled states or secondary content areas.
input bg-control / text-canvas-contrast Form input background. Typically darker than surface in dark mode.

Layout Example

<div class="bg-canvas min-h-screen">
  <aside class="bg-surface border-r border-frame">
    <!-- Sidebar content -->
  </aside>
  <main class="p-6">
    <Card class="p-4">
      <h2 class="text-surface-contrast">Card Title</h2>
    </Card>igen
  </main>
</div>

The common thread: you own the application

Controls present and interact. Fetching, validation, persistence, permissions, and accessibility gaps stay with the application. Each recipe in Recipes ends with an explicit list.