@alphinex/layouts
v2.2.0
Published
Layout Engine: Shell + slot model and named layout presets (Dashboard, POS, Auth, ...).
Readme
@alphinex/layouts
Layout Engine: a single slot-based <Shell> primitive plus ~9 named layout presets built on
top of it (Dashboard, POS, Auth, Blank, Print, Landing, Settings, Reports). Every preset is a
thin wrapper that fills <Shell>'s slots for a specific screen shape — reach for a preset
first, and drop to <Shell> directly only when none of them fit.
Shell + useShell()
<Shell> is the one primitive every named layout is a preset of. It arranges up to four
optional slots — header, rail (a narrow persistent icon strip, distinct from the full
sidebar), sidebar, and footer — around required children content. Below the desktop
breakpoint (min-width: 48rem), a supplied sidebar automatically becomes an off-canvas
drawer instead of an inline column; useShell() exposes the drawer's open/close state to
whatever you render in header, most commonly a menu-toggle button:
import { Shell, useShell } from "@alphinex/layouts";
import { Button } from "@alphinex/ui";
import { Icon } from "@alphinex/icons";
function MenuButton() {
const { toggleSidebar, isSidebarOpen } = useShell();
return (
<Button variant="ghost" size="sm" onClick={toggleSidebar} className="md:hidden">
<Icon name="menu" aria-label={isSidebarOpen ? "Close menu" : "Open menu"} />
</Button>
);
}
function CustomAppShell() {
return (
<Shell
header={
<div className="flex items-center gap-3 p-3">
<MenuButton />
<span className="font-medium">Alphinex Admin</span>
</div>
}
sidebar={<nav className="p-3">{/* nav items */}</nav>}
sidebarWidth="16rem"
defaultSidebarOpen={false}
>
<p className="p-4">Page content</p>
</Shell>
);
}useShell() throws if called outside a <Shell> — it only works inside content rendered by
one of Shell's slots or children. ShellProps also accepts className (outer wrapper) and
contentClassName (the scrollable <main> region only).
DashboardLayout + DashboardLayout.SidebarToggle
The default authenticated-app shell: header + collapsible sidebar + content. It's <Shell>
with the rail slot removed (DashboardLayoutProps = Omit<ShellProps, "rail">), plus a
ready-made hamburger button — DashboardLayout.SidebarToggle — attached as a static property,
so you don't have to hand-roll the useShell() toggle button shown above:
import { DashboardLayout } from "@alphinex/layouts";
function AdminShell() {
return (
<DashboardLayout
header={
<div className="flex items-center gap-3 p-3">
<DashboardLayout.SidebarToggle />
<span className="font-medium">Alphinex Admin</span>
</div>
}
sidebar={
<nav className="space-y-1 p-3 text-sm">
{["Overview", "Invoices", "Settings"].map((item) => (
<a key={item} href={`/${item.toLowerCase()}`} className="block px-2 py-1.5">
{item}
</a>
))}
</nav>
}
>
<p className="p-4 text-sm">Page content — the sidebar collapses into a drawer below 768px.</p>
</DashboardLayout>
);
}SidebarToggle renders <Icon name="menu"> in a ghost Button, is hidden at desktop widths
(md:hidden) since the sidebar is already visible inline there, and accepts any ButtonProps
except children/onClick/aria-label (which it sets itself).
Other presets
Each of these is a small, purpose-built wrapper around <Shell> (or, for PrintLayout,
around @alphinex/printing's <PrintFrame>). Import whichever fits the screen you're
building:
| Preset | Key props | Use for |
| ---------------- | ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| AuthLayout | children, illustration? | Centered content, no nav chrome — sign-in/sign-up/reset-password. illustration renders as a side panel, hidden below desktop width. |
| BlankLayout | children | No chrome at all — embeds and standalone flows that still participate in normal page flow. |
| PrintLayout | children, paperSize? ("a4" default) | No chrome, exact physical paper dimensions, print-isolated via @alphinex/printing's PrintFrame. Unlike BlankLayout, only one PrintLayout/PrintFrame may be mounted at a time. |
| LandingLayout | header?, footer?, children | Marketing-site chrome (nav + footer), distinct from the authenticated app shell. |
| SettingsLayout | nav, header?, children | A narrower (14rem) secondary-nav sidebar — typically rendered inside a DashboardLayout for a settings section. |
| ReportsLayout | header?, filters?, footer?, children, fullBleed? | A filter bar between header and content; fullBleed removes the default content padding for edge-to-edge charts/tables. |
| POSLayout | header?, catalog, cart, footer? | No sidebar, touch/tablet-optimized counter layout — catalog and cart stack vertically on narrow widths, sit side by side (cart capped at 24rem) above md. |
import { AuthLayout, POSLayout, ReportsLayout } from "@alphinex/layouts";
function SignIn() {
return (
<AuthLayout illustration={<img src="/auth-art.svg" alt="" />}>
<form className="space-y-3">{/* email/password fields */}</form>
</AuthLayout>
);
}
function Register() {
return (
<POSLayout
header={<div className="p-3 font-medium">Register 1</div>}
catalog={<ProductGrid />}
cart={<CartSummary />}
footer={<CheckoutBar />}
/>
);
}
function RevenueReport() {
return (
<ReportsLayout
header={<h1 className="p-3 font-medium">Revenue</h1>}
filters={<FilterBar />}
fullBleed
>
<RevenueChart />
</ReportsLayout>
);
}See documentation/ARCHITECTURE.md for the full package contract, dependency rules, and roadmap placement.
