"use client"; import * as React from "react"; import type { ComponentDocSpec } from "@/lib/design-system/component-doc-types"; import { UtilityBarBackPreview, UtilityBarBreadcrumbPreview, UtilityBarComfortPreview, UtilityBarDensePreview, UtilityBarProductlessPreview, } from "@/components/design-system/utility-bar-previews"; function ex( section: Omit< ComponentDocSpec["sections"][number], "children" | "description" >, children: React.ReactNode, description?: string, ) { return { ...section, children, description }; } export const utilityBarComponentDoc: ComponentDocSpec = { slug: "utility-bar", summary: "Full-width shell chrome for product context, global actions, Ask Leo, notifications, scope, and identity. Density and page mode determine which actions stay visible.", sections: [ ex( { id: "comfort", title: "Comfort" }, , "The production order at full width: sidebar control, product, global actions, Ask Leo, scope, and profile.", ), ex( { id: "dense", title: "Dense and reflow" }, , "Search, updates, help, support, and onboarding move into More. Notifications, Ask Leo, scope, and profile stay pinned.", ), ex( { id: "back", title: "Back mode" }, , "A parent destination replaces the product cluster while Ask Leo stays pinned.", ), ex( { id: "breadcrumb", title: "Breadcrumb mode" }, , "Record detail and deep routes show the ancestor trail instead of the back icon. Ask Leo stays pinned.", ), ex( { id: "productless", title: "Workspace without a selected product" }, , "The Exxat mark and workspace-global controls remain. Product-owned controls are absent.", ), ], anatomy: [ { part: "UtilityBarSlot", description: "Shell mount above the app shell row.", }, { part: "UtilityBarProductSwitcher", description: "Leading product trigger. Dense mode keeps the product mark.", }, { part: "Breadcrumb", description: "Portaled from SiteHeader. Dense mode keeps the current location.", }, { part: "Search", description: "Opens the command menu. Moves into More on Dense.", }, { part: "Support chat", description: "Message icon that dispatches exxat:open-support-chat for the host support provider; moves into More on Dense.", }, { part: "AskLeoToggle", description: "Labeled on Comfort and icon-only on Dense. Pinned before identity.", }, { part: "Onboarding", description: "Icon link to /builder/onboarding." }, { part: "NotificationBell", description: "Icon button + dropdown; always visible.", }, { part: "UtilityBarWhatsNew", description: "Release updates; under More on Dense.", }, { part: "Get Help", description: "Help destination. Under More on Dense." }, { part: "UtilityUserMenu", description: "Avatar trigger with Profile settings + Workspace settings (same URL as the former Settings gear).", }, ], ux: { job: "Give users one persistent place to search, open Ask Leo, check notifications, and reach onboarding without hunting through the sidebar.", whenToUse: [ "Any signed-in shell route (not exam-lock, not /builder/onboarding).", "When a surface needs a canonical trigger for a global action instead of a page-local one.", ], whenNotToUse: [ "Page- or hub-scoped actions — those belong in PageHeader, not the utility bar.", "One-off promo messaging — use SystemBanner instead (full-bleed strip above the utility bar).", ], modernReferences: [ "Linear command bar + inbox bell", "Notion top bar with search + updates bell", ], patternDoc: "apps/web/docs/shell-utility-bar-pattern.md", }, guidelines: { do: [ "Reuse existing triggers (requestOpenCommandMenu, AskLeoToggle, getSecondaryNavForProduct, NAV_USER).", "Use `utilityBarActionButtonClass` for icon actions.", "Keep Search icon-only; Ask Leo shows icon + label before identity.", "Resolve Workspace settings via getSecondaryNavForProduct(product).", "Use Back mode for focus routes that publish a single parent destination.", "Use Breadcrumb mode for record detail routes with an ancestor trail (`utilityBarMode: \"breadcrumb\"`, or default on record detail when `breadcrumbs` are set).", "Use the productless inventory on Products home and sign-in flows.", "Render the bar full width. Do not place it inside a centered content rail.", ], dont: [ "Do not mount a Settings gear on the bar — use Workspace settings in the profile menu.", "Do not add a second Search/Ask Leo/Notifications trigger elsewhere in the shell.", "Do not give What's new its own dismissal store.", "Do not invent alternate utility bar layout pickers.", ], }, accessibility: [ "Every icon-only trigger has an aria-label + Tip (Search, Onboarding, Notifications, What's new, Help, profile).", "Ask Leo keeps a visible label for recognition.", "NotificationBell and What's new unread counts are also in the trigger aria-label.", "Search and Ask Leo keep ⌘K / ⌘⌥K.", ], extraImports: [ { label: "ShellLayoutContext", path: "@/contexts/shell-layout-context" }, { label: "UtilityBarProductSwitcher", path: "@/components/utility-bar-product-switcher", }, { label: "NotificationBell", path: "@/components/notification-bell" }, { label: "UtilityBarWhatsNew", path: "@/components/utility-bar-whats-new" }, { label: "WhatsNewSheet", path: "@exxatdesignux/ui/components/ui/whats-new-sheet" }, { label: "UtilityUserMenu", path: "@/components/utility-user-menu" }, ], relatedSlugs: ["banner", "site-header", "sidebar", "app-shell"], };