UI & Layout

App shell, sidebar, and theming.

Chelone's UI components are the pieces of the admin shell: the layout that frames every screen, the pages for login, loading and failure, and the menu items and buttons inside them. <Admin> has a named slot for each page, and each page has a default component you can pass in or replace.

Admin slots

Fill a slot with a child (<Admin.Layout>) or with the matching prop (layout={...}). The prop wins when both are given. Every slot is optional. An empty slot has no built-in page, except two. error falls back to a plain error message with the stack. loginPage falls back to a working <LoginPage>, so requireAuth never lands on a blank screen. Pass loginPage={null} to turn that one off. An empty layout renders the routes with no shell. For the other slots, pass the component from this table to turn a page on.

SlotComponentWhen it renders
layout<Layout>Wraps every authenticated screen: sidebar, app bar and content area.
loginPage<LoginPage>While unauthenticated, when requireAuth is set. Defaults to <LoginPage>.
dashboardYour own componentThe index route. Without one, the index redirects to the first resource that has a list. If your authProvider denies list on that resource, the index renders blank.
errorAny element, such as a page of your ownWhen rendering throws.
ready<Ready>When no resource or custom route is registered.
loading<Loading>While the auth check or an async <Admin> child is pending.
accessDenied<AccessDenied>At /access-denied.
authenticationError<AuthenticationError>At /authentication-error.
authCallback<AuthCallback>At /auth-callback, the redirect target of an OAuth login.
catchAll<NotFound>For a URL no route matches. Empty, it renders nothing.

<Admin> has one more slot with no component here: title, the app title.

import {
  AccessDenied,
  Admin,
  AuthCallback,
  AuthenticationError,
  Layout,
  Loading,
  LoginPage,
  NotFound,
  Ready,
} from "@chelone/react";
 
<Admin dataProvider={dataProvider} queryClient={queryClient} requireAuth>
  <Admin.Layout>
    <Layout />
  </Admin.Layout>
  <Admin.LoginPage>
    <LoginPage />
  </Admin.LoginPage>
  <Admin.Loading>
    <Loading />
  </Admin.Loading>
  <Admin.Ready>
    <Ready />
  </Admin.Ready>
  <Admin.AccessDenied>
    <AccessDenied />
  </Admin.AccessDenied>
  <Admin.AuthenticationError>
    <AuthenticationError />
  </Admin.AuthenticationError>
  <Admin.AuthCallback>
    <AuthCallback />
  </Admin.AuthCallback>
  <Admin.CatchAll>
    <NotFound />
  </Admin.CatchAll>
</Admin>;

An element in the error slot renders as is, so it gets no props. To use <Error>, which needs the boundary's { error, errorInfo, resetErrorBoundary }, pass a render function to Layout's error prop:

<Layout error={(props) => <Error {...props} />} />

Layout overrides

<Layout> renders <AppSidebar> around <Menu>, then <AppBar> above the content, inside its own error boundary. Four props swap a part. The first three take a component, not an element:

PropReplacesDefault
appBarThe bar above the content.<AppBar>
menuThe navigation inside the sidebar.<Menu>
sidebarThe sidebar that holds the menu.<AppSidebar>
errorThe fallback when the content area throws. A node renders as is. A function receives { error, errorInfo, resetErrorBoundary }.The built-in fallback: the message and the stack.
import { Admin, Layout, Menu } from "@chelone/react";
 
const MyMenu = () => (
  <Menu>
    <Menu.DashboardItem />
    <Menu.ResourceItem name="posts" />
    <Menu.Item to="/reports" label="Reports" />
  </Menu>
);
 
<Admin.Layout>
  <Layout menu={MyMenu} />
</Admin.Layout>;

The Menu.* parts are listed on the <Menu> page.

The rest of the section

The other pages are the parts these are built from: the sidebar items (<ResourceMenuItem>, <MenuItemLink>, <DashboardMenuItem>), the app-bar controls (<UserMenu>, <ThemeModeToggle>, <SidebarToggleButton>, <TitlePortal>), the auth pieces (<LoginForm>, <AuthLayout>, <Logout>, <CanAccess>) and feedback (<Notification>, <Confirm>, <LinearProgress>). Each is a props reference, read from the source, with no live examples.