layouts

AppShell

Full-height flex column with header, sidebar, main, and footer slots.


AppShell is the chrome you wrap your routed views in. It doesn't take a router opinion, so you can use any navigator under it.

import { AppShell, Sidebar } from "@plyxui/layouts";

<AppShell
  header={<TitleBar />}
  sidebar={<Sidebar items={items} header={<Brand />} />}
>
  <Outlet />
</AppShell>

Props

PropTypeDefault
headerReactNode-
sidebarReactNode-
footerReactNode-
sidebarWidthnumber240
dividerbooleantrue

The sidebar slot is a single render slot, so consumers can put the plyxui Sidebar there or any custom navigation surface.

Native variant

On native the sidebar slot is dropped; tabs are the right pattern. Use OmniNavigator mode="tabs" from @plyxui/navigator/react-navigation and feed it the same OmniRoute[] you'd render in the web Sidebar.

Composing with the navigator

import { defineRoutes } from "@plyxui/navigator";
import { OmniRouter } from "@plyxui/navigator/react-router";

const routes = defineRoutes([
  { name: "home",     path: "/",         icon: "home",     title: "Home",     element: () => <Home /> },
  { name: "subjects", path: "/subjects", icon: "user",     title: "Subjects", element: () => <Subjects /> },
  { name: "settings", path: "/settings", icon: "settings", title: "Settings", element: () => <Settings /> },
]);

function Shell() {
  return (
    <BrowserRouter>
      <AppShell sidebar={<Sidebar items={sidebarItems(routes)} />}>
        <OmniRouter routes={routes} />
      </AppShell>
    </BrowserRouter>
  );
}

The routes table is the single source of truth for both the sidebar items and the routes themselves.