{
  "id": "page-shell",
  "name": "PageShell",
  "level": "organism",
  "status": "stable",
  "purpose": "The app frame: an icon rail whose rows peek, the page header, the content; tabs on phones.",
  "description": "**Purpose.** The slot-based layout organism for application pages. Its default frame is **Poesía's navigation (ADR-044)**: a permanent icon rail in a glass capsule centred on the window (`sidebarMode=\"rail\"`, `sidebarPresentation=\"inset\"`), every row in one untitled `NavGroup`, each row wrapped in `<PageShell.RailPeek>` so hovering it opens a glass panel over the page — composed from `PeekHeader`, `PeekFacts` and `PeekLinks`. Search and settings are rows; there is no top bar; phones get `<PageShell.MobileTabBar>` (`mobileNav=\"tabs\"`). See the Playground story.\n\n**Opt-ins.** The labelled panel (`sidebarMode=\"auto\"` / `\"panel\"`, collapsible with ⌘\\, ADR-014/040), the `island` and `column` presentations (ADR-025), a `topBar` for pages without a rail (ADR-009), and the floating bubble with its drawer on phones (`mobileNav=\"bubble\"`, ADR-011/013). The stories below that show them say so.\n\n**Identity moves.**\n- The rail never grows; the page keeps its width. A detail (a count, a status) goes in the row's peek, never on the icon.\n- One group, one gap: home first, settings last (J-36).\n- Glass only where you navigate or act (ADR-038): the rail capsule and the peek; the content rests on the content material.\n\n**Controls that stay in reach (ADR-045).** A screen whose content scrolls past its filters, search, view switch or section tabs puts them in `<PageShell.StickyBar title=\"…\">` right under its `PageHeader`. At rest the bar is part of the page; once it pins it condenses onto glass and the page title folds into it, small (left out on phones). Its box never changes, so nothing jumps; it never hides focus. With `edge=\"bottom\"` it holds a selection's or a form's actions. One bar per edge: put a view switch and its filter in the same bar. See the Sticky bars story.\n\n**When to use.**\n- Any application page: the rail frame, a page header and the content body.\n- A settings page (`width=\"md\"`), a data page (`width=\"xl\"` + `mainPadding=\"flush\"`), a dashboard (`width=\"xl\"`), a marketing surface (`width=\"fluid\"` + `frame=\"off\"`).\n\n**When NOT to use.**\n- An overlay surface (Dialog, DropdownMenu, Popover) — these are not pages.\n- A fixed authentication / onboarding screen with a single centered card → use a simpler `<main>` + `Card` directly.\n\n**Composes with.**\n- `<SidebarSection aria-label>` + one `<NavGroup>` of `<PageShell.RailPeek>`-wrapped `<NavItem>`s in the `sidebar` slot.\n- `<CommandMenu>` opened by the search row (⌘K).\n- `<PageHeader>` in the `header` slot — title, breadcrumb, page actions — or in the body, followed by a `<PageShell.StickyBar>` when the screen has controls to keep in reach (ADR-045).\n- `<TopBar>` in the `topBar` slot only for pages without a rail (marketing, reading).\n\n**Mobile.** The tab bar by default (five tabs at most). The bubble is an opt-in:\n- With `mobileNav=\"bubble\"` (or no `mobileTabBar`) it auto-renders at `<md` whenever a `sidebar` is provided. Override via `navBubble={false}` to suppress (and mount the compound manually for full positioning control), or `navBubblePosition=\"start\"` to anchor it on the left.\n- The bubble is `<PageShell.MobileNavBubble />`. Its predecessor `<PageShell.MobileNavTrigger />` is deprecated — kept exported one release for migration, removed in the next.\n\n**Accessibility.**\n- Renders `<main aria-label={mainLabel}>` (default `\"Main content\"`).\n- The mobile drawer is a Radix Dialog — focus trap, Escape-to-close and overlay click are right by construction.\n- The bubble announces `aria-expanded` and `aria-controls` linking to the drawer; its `aria-label` toggles between \"Open navigation\" and \"Close navigation\" depending on state.\n- The shell uses an **app-shell scroll model**: only the main column scrolls. PageHeader stays sticky inside that scroll context.\n\n**Related patterns.**\n- `Patterns/Page Shells · DashboardSurface / SettingsPage / DataPage` — the canonical configurations.\n- `Patterns/Information Architecture · SectionAnatomy` — why the shell stays visually quiet.\n- `Patterns/Decision Matrix · LayoutPrimitive` — when PageShell vs a simpler `<main>` is the right answer.",
  "role": "surface",
  "import": "@rrios-forge/ui/organisms/page-shell",
  "exports": [
    "PageShell",
    "PageShellMobileNavBubble",
    "PageShellMobileNavTrigger",
    "PageShellMobileTabBar",
    "PageShellRailPeek",
    "PageShellSidebarTrigger",
    "usePageShellMobileNav",
    "usePageShellSidebar",
    "PageShellStickyBar",
    "PAGE_SHELL_FRAMES",
    "PAGE_SHELL_MAIN_PADDINGS",
    "PAGE_SHELL_MOBILE_NAVS",
    "PAGE_SHELL_NAV_BUBBLE_POSITIONS",
    "PAGE_SHELL_SIDEBAR_MODES",
    "PAGE_SHELL_SIDEBAR_TONES",
    "PAGE_SHELL_WIDTHS",
    "pageShellFooterVariants",
    "pageShellFrameVariants",
    "pageShellHeaderVariants",
    "pageShellMainVariants",
    "pageShellMobileNavBubbleIconVariants",
    "pageShellMobileNavBubbleVariants",
    "pageShellMobileSheetOverlayVariants",
    "pageShellMobileSheetVariants",
    "pageShellMobileTabBarSlotVariants",
    "pageShellOuterVariants",
    "pageShellRowVariants",
    "pageShellScrollVariants",
    "pageShellSidebarBodyVariants",
    "pageShellSidebarFooterVariants",
    "pageShellSidebarHeaderVariants",
    "pageShellSidebarVariants",
    "pageShellTopBarSlotVariants"
  ],
  "source": "packages/ui/src/organisms/page-shell",
  "axes": [
    {
      "axis": "frame",
      "part": null,
      "values": [
        "auto",
        "on",
        "off"
      ],
      "default": "auto",
      "meaning": "PageShell editorial frame."
    },
    {
      "axis": "scroll",
      "part": null,
      "values": [
        "pane",
        "page"
      ],
      "default": "pane",
      "meaning": "PageShell scroll owner."
    },
    {
      "axis": "stage",
      "part": null,
      "values": [
        "field",
        "none"
      ],
      "default": "field",
      "meaning": "PageShell stage paint."
    },
    {
      "axis": "sidebarMode",
      "part": null,
      "values": [
        "auto",
        "panel",
        "rail"
      ],
      "default": "auto",
      "meaning": "How the app frame shows its navigation: rail, the default, is a column of icons whose rows preview their page; auto and panel show the labelled panel instead."
    },
    {
      "axis": "presentation",
      "part": null,
      "values": [
        "island",
        "column",
        "inset"
      ],
      "default": "island",
      "meaning": "How the same thing is staged."
    },
    {
      "axis": "material",
      "part": null,
      "values": [
        "solid",
        "vibrant"
      ],
      "default": "solid",
      "meaning": "The layer's material (ADR-022, ADR-027)."
    },
    {
      "axis": "mainPadding",
      "part": null,
      "values": [
        "default",
        "flush"
      ],
      "default": "default",
      "meaning": "PageShell main padding."
    },
    {
      "axis": "position",
      "part": null,
      "values": [
        "start",
        "end"
      ],
      "default": "end",
      "meaning": "Placement of a docked element."
    }
  ],
  "needs": [
    {
      "need": "App frame / navigation",
      "answer": "**The rail that peeks (ADR-044) — the default and the recommendation.** `PageShell` (defaults: `sidebarMode=\"rail\"`, `sidebarPresentation=\"inset\"`, `mobileNav=\"tabs\"`) + `SidebarSection aria-label` + ONE untitled `NavGroup`: home, search, the rooms, settings — same size, same gap. Wrap every `NavItem` in `PageShell.RailPeek` and compose its panel with `PageShell.PeekHeader` / `PeekFacts` / `PeekLinks`. Search is a button row opening `CommandMenu` (⌘K); settings' peek holds the quick controls; phones get `PageShell.MobileTabBar` (≤ 5). No `TopBar` in an app frame. Opt-ins only when a product needs them: the labelled panel (`sidebarMode=\"auto\"`, ⌘\\\\ collapse, ADR-040), `island`/`column` (ADR-025), the bubble (`mobileNav=\"bubble\"`)"
    },
    {
      "need": "Controls that must stay in reach while the screen scrolls (filters, search, a view switch, section tabs) — or a selection's / a form's actions",
      "answer": "`PageShell.StickyBar` (ADR-045) under the `PageHeader`, `edge=\"bottom\"` for actions: at rest part of the page; pinned, it condenses onto glass and carries the page title small. One bar per edge; never hides focus"
    }
  ],
  "patterns": [
    "Patterns/Page Shells · DashboardSurface",
    "Patterns/Page Shells · SettingsPage",
    "Patterns/Page Shells · DataPage",
    "Patterns/Information Architecture · SectionAnatomy",
    "Patterns/Navigation · NavigationLayers",
    "Patterns/Density & Growth · ContentGrowth",
    "Patterns/Decision Matrix · ComponentChoice + LayoutPrimitive"
  ],
  "a11yExceptions": [],
  "decisions": [
    {
      "id": "ADR-003",
      "title": "Storybook editorial convention and pattern↔component bidirectionality"
    },
    {
      "id": "ADR-004",
      "title": "Migrate boolean configuration props to semantic axes"
    },
    {
      "id": "ADR-009",
      "title": "Editorial Frame: PageShell v3 + new `TopBar` molecule"
    },
    {
      "id": "ADR-010",
      "title": "PageShell v4: bottom dock + mobile floating bubble"
    },
    {
      "id": "ADR-011",
      "title": "PageShell v5: adaptive lateral sidebar + mobile nav bubble"
    },
    {
      "id": "ADR-013",
      "title": "PageShell: mobile-nav polymorphism"
    },
    {
      "id": "ADR-014",
      "title": "PageShell: Apple Mail / macOS Big Sur visual register"
    },
    {
      "id": "ADR-015",
      "title": "Drawer molecule on top of Radix Dialog"
    },
    {
      "id": "ADR-016",
      "title": "NotificationCenter v2: Popover → Drawer + Provider/Hooks"
    },
    {
      "id": "ADR-018",
      "title": "Motion language as a Pattern Layer contract"
    },
    {
      "id": "ADR-022",
      "title": "The material family: `solid` and `vibrant`"
    },
    {
      "id": "ADR-025",
      "title": "The sidebar is an island, not a wall (amended: two stagings)"
    },
    {
      "id": "ADR-026",
      "title": "Sunset functional palette + the stage field"
    },
    {
      "id": "ADR-027",
      "title": "Vibrant is the system's material, not one of its members"
    },
    {
      "id": "ADR-029",
      "title": "The page gutter belongs outside the frame"
    },
    {
      "id": "ADR-030",
      "title": "Axis vocabulary: one name, one meaning"
    },
    {
      "id": "ADR-032",
      "title": "Themes compose by layers; brands are a checked layer"
    },
    {
      "id": "ADR-033",
      "title": "The material ships once, and the night is tokens"
    },
    {
      "id": "ADR-037",
      "title": "Continuity motion: a decelerating curve, a travelling indicator, view transitions and the SegmentedControl"
    },
    {
      "id": "ADR-038",
      "title": "Liquid Glass layers: glass for navigation and controls, a content material for everything read"
    },
    {
      "id": "ADR-039",
      "title": "The component premium pass: translucent fills, a selected register, quiet scroll, and a system-wide audit"
    },
    {
      "id": "ADR-040",
      "title": "The sidebar collapses by default and gives the page the room"
    },
    {
      "id": "ADR-041",
      "title": "The rail peeks instead of growing"
    },
    {
      "id": "ADR-044",
      "title": "Navigation is a rail that peeks"
    },
    {
      "id": "ADR-045",
      "title": "A screen's controls pin and condense"
    }
  ],
  "stories": [
    {
      "name": "Playground",
      "id": "components-organisms-pageshell--playground",
      "interaction": false,
      "snapshots": [
        "dark",
        "high-contrast",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--playground",
      "frame": "/iframe.html?id=components-organisms-pageshell--playground&viewMode=story"
    },
    {
      "name": "Apple-style desktop",
      "id": "components-organisms-pageshell--apple-style-desktop",
      "interaction": false,
      "snapshots": [
        "dark",
        "high-contrast",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--apple-style-desktop",
      "frame": "/iframe.html?id=components-organisms-pageshell--apple-style-desktop&viewMode=story"
    },
    {
      "name": "Dashboard",
      "id": "components-organisms-pageshell--dashboard",
      "interaction": false,
      "snapshots": [
        "dark",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--dashboard",
      "frame": "/iframe.html?id=components-organisms-pageshell--dashboard&viewMode=story"
    },
    {
      "name": "Settings page",
      "id": "components-organisms-pageshell--settings-page",
      "interaction": false,
      "snapshots": [
        "dark",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--settings-page",
      "frame": "/iframe.html?id=components-organisms-pageshell--settings-page&viewMode=story"
    },
    {
      "name": "Data page",
      "id": "components-organisms-pageshell--data-page",
      "interaction": false,
      "snapshots": [
        "dark",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--data-page",
      "frame": "/iframe.html?id=components-organisms-pageshell--data-page&viewMode=story"
    },
    {
      "name": "Sticky bars",
      "id": "components-organisms-pageshell--sticky-bars",
      "interaction": true,
      "snapshots": [
        "dark",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--sticky-bars",
      "frame": "/iframe.html?id=components-organisms-pageshell--sticky-bars&viewMode=story"
    },
    {
      "name": "With footer",
      "id": "components-organisms-pageshell--with-footer",
      "interaction": false,
      "snapshots": [
        "dark",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--with-footer",
      "frame": "/iframe.html?id=components-organisms-pageshell--with-footer&viewMode=story"
    },
    {
      "name": "Frame · auto / on / off",
      "id": "components-organisms-pageshell--frame-triptych",
      "interaction": false,
      "snapshots": [
        "dark",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--frame-triptych",
      "frame": "/iframe.html?id=components-organisms-pageshell--frame-triptych&viewMode=story"
    },
    {
      "name": "Sidebar · panel / rail / auto",
      "id": "components-organisms-pageshell--sidebar-modes",
      "interaction": false,
      "snapshots": [
        "dark",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--sidebar-modes",
      "frame": "/iframe.html?id=components-organisms-pageshell--sidebar-modes&viewMode=story"
    },
    {
      "name": "Sidebar · column (Sissificate register)",
      "id": "components-organisms-pageshell--sidebar-column",
      "interaction": false,
      "snapshots": [
        "dark",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--sidebar-column",
      "frame": "/iframe.html?id=components-organisms-pageshell--sidebar-column&viewMode=story"
    },
    {
      "name": "Liquid Glass (inset sidebar)",
      "id": "components-organisms-pageshell--liquid-glass",
      "interaction": false,
      "snapshots": [
        "dark",
        "high-contrast",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--liquid-glass",
      "frame": "/iframe.html?id=components-organisms-pageshell--liquid-glass&viewMode=story"
    },
    {
      "name": "Sidebar · collapse (default)",
      "id": "components-organisms-pageshell--sidebar-collapsible",
      "interaction": true,
      "snapshots": [
        "dark",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--sidebar-collapsible",
      "frame": "/iframe.html?id=components-organisms-pageshell--sidebar-collapsible&viewMode=story"
    },
    {
      "name": "Sidebar · rail peek",
      "id": "components-organisms-pageshell--sidebar-rail-peek",
      "interaction": true,
      "snapshots": [
        "dark",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--sidebar-rail-peek",
      "frame": "/iframe.html?id=components-organisms-pageshell--sidebar-rail-peek&viewMode=story"
    },
    {
      "name": "Mobile (drawer + bubble)",
      "id": "components-organisms-pageshell--mobile",
      "interaction": false,
      "snapshots": [
        "dark",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--mobile",
      "frame": "/iframe.html?id=components-organisms-pageshell--mobile&viewMode=story"
    },
    {
      "name": "Mobile · drawer open",
      "id": "components-organisms-pageshell--mobile-bubble-open",
      "interaction": false,
      "snapshots": [
        "dark",
        "high-contrast",
        "light",
        "reduced-motion"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--mobile-bubble-open",
      "frame": "/iframe.html?id=components-organisms-pageshell--mobile-bubble-open&viewMode=story"
    },
    {
      "name": "Mobile · bubble start (left)",
      "id": "components-organisms-pageshell--mobile-bubble-start",
      "interaction": false,
      "snapshots": [
        "dark",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--mobile-bubble-start",
      "frame": "/iframe.html?id=components-organisms-pageshell--mobile-bubble-start&viewMode=story"
    },
    {
      "name": "Mobile · bottom tabs (iOS register)",
      "id": "components-organisms-pageshell--mobile-nav-tabs",
      "interaction": false,
      "snapshots": [
        "dark",
        "high-contrast",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--mobile-nav-tabs",
      "frame": "/iframe.html?id=components-organisms-pageshell--mobile-nav-tabs&viewMode=story"
    },
    {
      "name": "Mobile · no nav (embedded)",
      "id": "components-organisms-pageshell--mobile-nav-none",
      "interaction": false,
      "snapshots": [
        "dark",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--mobile-nav-none",
      "frame": "/iframe.html?id=components-organisms-pageshell--mobile-nav-none&viewMode=story"
    },
    {
      "name": "Container · flush body (own gutter)",
      "id": "components-organisms-pageshell--container-padding-flush",
      "interaction": false,
      "snapshots": [
        "dark",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--container-padding-flush",
      "frame": "/iframe.html?id=components-organisms-pageshell--container-padding-flush&viewMode=story"
    },
    {
      "name": "Container · opt-out (disableContainer)",
      "id": "components-organisms-pageshell--disable-container",
      "interaction": false,
      "snapshots": [
        "dark",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--disable-container",
      "frame": "/iframe.html?id=components-organisms-pageshell--disable-container&viewMode=story"
    },
    {
      "name": "Tablet",
      "id": "components-organisms-pageshell--tablet",
      "interaction": false,
      "snapshots": [
        "dark",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--tablet",
      "frame": "/iframe.html?id=components-organisms-pageshell--tablet&viewMode=story"
    },
    {
      "name": "Widths",
      "id": "components-organisms-pageshell--widths",
      "interaction": false,
      "snapshots": [
        "dark",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--widths",
      "frame": "/iframe.html?id=components-organisms-pageshell--widths&viewMode=story"
    },
    {
      "name": "Accessibility",
      "id": "components-organisms-pageshell--accessibility",
      "interaction": false,
      "snapshots": [
        "dark",
        "high-contrast",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--accessibility",
      "frame": "/iframe.html?id=components-organisms-pageshell--accessibility&viewMode=story"
    },
    {
      "name": "Vibrant chrome",
      "id": "components-organisms-pageshell--vibrant-chrome",
      "interaction": false,
      "snapshots": [
        "dark",
        "high-contrast",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-organisms-pageshell--vibrant-chrome",
      "frame": "/iframe.html?id=components-organisms-pageshell--vibrant-chrome&viewMode=story"
    }
  ],
  "storyFile": "tooling/storybook/stories/components/organisms/page-shell.stories.tsx"
}
