Shell

Main application layout component with sidebar and title bar

Overview

Shell is the main layout component of the application, providing:

  • Top title bar (TitleBar)
  • Sidebar navigation
  • Main content area
  • Slot support

Import

import { Shell } from '@linch-tech/desktop-core';

Props

interface ShellProps {
  /**
   * Children (used in noOutlet mode)
   */
  children?: ReactNode;

  /**
   * Custom className
   */
  className?: string;

  /**
   * If true, don't render Outlet (render children directly)
   */
  noOutlet?: boolean;
}

Basic Usage

Use as a route layout component:

import { Routes, Route } from 'react-router-dom';
import { Shell } from '@linch-tech/desktop-core';

function App() {
  return (
    <Routes>
      <Route element={<Shell />}>
        <Route path="/" element={<Home />} />
        <Route path="/settings" element={<Settings />} />
      </Route>
    </Routes>
  );
}

Layout Structure

┌─────────────────────────────────────────────────┐
│                   TitleBar                       │
│  [Logo] [App Name]              [Theme] [×]     │
├────────────┬────────────────────────────────────┤
│            │                                    │
│  Sidebar   │         Main Content               │
│            │         (<Outlet />)               │
│  [Nav 1]   │                                    │
│  [Nav 2]   │                                    │
│  [Nav 3]   │                                    │
│            │                                    │
├────────────┤                                    │
│  [Footer]  │                                    │
└────────────┴────────────────────────────────────┘

noOutlet Mode

If not using react-router-dom's Outlet, use noOutlet mode:

<Shell noOutlet>
  <MyContent />
</Shell>

Custom Styling

<Shell className="custom-shell-class" />

Configuration Driven

Shell behavior is controlled by configuration:

// src/config.ts
export const config = {
  nav: [
    { title: 'Home', path: '/', icon: Home },
    { title: 'Settings', path: '/settings', icon: Settings },
  ],

  layout: {
    sidebar: {
      width: 200,
      position: 'left',  // or 'right'
    },
  },

  slots: {
    sidebar: {
      header: <WorkspaceSwitcher />,
      footer: <UserProfile />,
    },
    shell: {
      beforeContent: <AlertBanner />,
    },
  },
};

Overriding Shell Component

Fully customize Shell:

import type { ShellProps } from '@linch-tech/desktop-core';

function CustomShell({ children, className, noOutlet }: ShellProps) {
  return (
    <div className={className}>
      {/* Fully custom layout */}
      <MyCustomSidebar />
      <main>
        {noOutlet ? children : <Outlet />}
      </main>
    </div>
  );
}

// Use in configuration
export const config = {
  components: {
    Shell: CustomShell,
  },
};

Navigation items are automatically rendered based on configuration, supporting:

  • Icons
  • Titles (i18n supported)
  • Badges
  • Active state highlighting

Custom navigation item component:

import type { NavItemComponentProps } from '@linch-tech/desktop-core';

function CustomNavItem({ item, isActive, onClick }: NavItemComponentProps) {
  return (
    <button
      onClick={onClick}
      className={isActive ? 'active' : ''}
    >
      <item.icon />
      <span>{item.title}</span>
    </button>
  );
}

export const config = {
  components: {
    NavItem: CustomNavItem,
  },
};
SlotPosition
slots.sidebar.headerTop of sidebar
slots.sidebar.beforeNavBefore navigation list
slots.sidebar.afterNavAfter navigation list
slots.sidebar.footerBottom of sidebar

Shell Slots

SlotPosition
slots.shell.beforeContentAbove main content area
slots.shell.afterContentBelow main content area