npm package: @mehdashti/shell
Description: Application shell with navigation components and enterprise layouts for Smart Platform
Author: mehdashti
Latest version: 0.2.1

# @mehdashti/shell

> Enterprise application shell with navigation and layouts for Smart Platform

## Installation

```bash
pnpm add @mehdashti/shell @mehdashti/ui lucide-react
```

## Features

### Core Shell Components
- ✅ **AppShell**: Complete application layout with sidebar and header
- ✅ **Sidebar**: Collapsible navigation with groups and nested items
- ✅ **Header**: User menu and actions
- ✅ **Breadcrumb**: Page location with overflow support (Phase 4)
- ✅ **TopNav**: Horizontal navigation bar (Phase 4)
- ✅ **DrilldownMenu**: Hierarchical drill-down navigation (Phase 4)

### Enterprise Layouts (Phase 4)
- ✅ **ObjectPage**: SAP Fiori-style entity detail layout with tabs
- ✅ **MasterDetail**: Resizable two-panel layout for list-detail interfaces
- ✅ **FlexibleColumn**: Responsive 1-3 column layout with progressive disclosure
- ✅ **Dashboard**: Grid-based widget layout for dashboards

### General
- ✅ **Responsive**: Mobile-friendly layouts
- ✅ **Accessible**: ARIA attributes and keyboard navigation
- ✅ **Type Safe**: Full TypeScript support

## Quick Start

### Basic Usage

```typescript
import { AppShell } from "@mehdashti/shell";
import { Home, Users, Settings } from "lucide-react";

function App() {
  const navigation = [
    {
      id: "main",
      items: [
        {
          id: "home",
          label: "Home",
          icon: Home,
          href: "/",
          active: true,
        },
        {
          id: "users",
          label: "Users",
          icon: Users,
          href: "/users",
          badge: 5,
        },
      ],
    },
    {
      id: "settings",
      label: "Settings",
      items: [
        {
          id: "settings",
          label: "Settings",
          icon: Settings,
          href: "/settings",
        },
      ],
    },
  ];

  const user = {
    name: "John Doe",
    email: "john@example.com",
  };

  const breadcrumbs = [
    { label: "Home", href: "/" },
    { label: "Users" },
  ];

  return (
    <AppShell
      navigation={navigation}
      user={user}
      breadcrumbs={breadcrumbs}
      onNavigate={(item) => console.log("Navigate to:", item.href)}
      onLogout={() => console.log("Logout")}
    >
      <h1>Your Content Here</h1>
    </AppShell>
  );
}
```

## Components

### AppShell

Main application layout combining sidebar, header, and content area.

```typescript
import { AppShell } from "@mehdashti/shell";
import { Home, Settings } from "lucide-react";

<AppShell
  navigation={[
    {
      id: "main",
      items: [
        { id: "home", label: "Home", icon: Home, href: "/" },
        { id: "settings", label: "Settings", icon: Settings, href: "/settings" },
      ],
    },
  ]}
  user={{ name: "John Doe", email: "john@example.com" }}
  breadcrumbs={[{ label: "Home", href: "/" }, { label: "Dashboard" }]}
  defaultSidebarCollapsed={false}
  onNavigate={(item) => console.log(item)}
  onLogout={() => console.log("Logout")}
  onSettings={() => console.log("Settings")}
  onProfile={() => console.log("Profile")}
>
  <YourContent />
</AppShell>
```

**Props:**

- `navigation`: NavigationGroup[] - Navigation groups for sidebar
- `user`: UserInfo - User information for header
- `breadcrumbs`: BreadcrumbItem[] - Breadcrumb items
- `defaultSidebarCollapsed`: boolean - Initial sidebar state
- `onNavigate`: (item: NavigationItem) => void - Navigation callback
- `onLogout`: () => void - Logout callback
- `onSettings`: () => void - Settings callback
- `onProfile`: () => void - Profile callback
- `headerActions`: ReactNode - Additional header actions
- `children`: ReactNode - Main content

### Sidebar

Collapsible navigation sidebar with groups and nested items.

```typescript
import { Sidebar } from "@mehdashti/shell";
import { Home, Users, Settings } from "lucide-react";

<Sidebar
  groups={[
    {
      id: "main",
      label: "Main Menu",
      items: [
        { id: "home", label: "Home", icon: Home, href: "/", active: true },
        { id: "users", label: "Users", icon: Users, href: "/users", badge: 5 },
      ],
    },
  ]}
  collapsed={false}
  onNavigate={(item) => console.log(item)}
/>
```

**Props:**

- `groups`: NavigationGroup[] - Navigation groups
- `collapsed`: boolean - Collapsed state
- `onNavigate`: (item: NavigationItem) => void - Navigation callback
- `className`: string - Additional CSS class

### Header

Application header with user menu and actions.

```typescript
import { Header } from "@mehdashti/shell";

<Header
  user={{ name: "John Doe", email: "john@example.com" }}
  sidebarCollapsed={false}
  onToggleSidebar={() => console.log("Toggle")}
  onLogout={() => console.log("Logout")}
  onSettings={() => console.log("Settings")}
  onProfile={() => console.log("Profile")}
  actions={<button>Custom Action</button>}
/>
```

**Props:**

- `user`: UserInfo - User information
- `sidebarCollapsed`: boolean - Sidebar state
- `onToggleSidebar`: () => void - Toggle callback
- `onLogout`: () => void - Logout callback
- `onSettings`: () => void - Settings callback
- `onProfile`: () => void - Profile callback
- `actions`: ReactNode - Additional actions
- `className`: string - Additional CSS class

### Breadcrumb

Breadcrumb navigation with overflow support for long paths (Phase 4).

```typescript
import { Breadcrumb } from "@mehdashti/shell";

<Breadcrumb
  items={[
    { label: "Home", href: "/" },
    { label: "Users", href: "/users" },
    { label: "John Doe", href: "/users/123" },
    { label: "Profile" },
  ]}
  showHomeIcon={true}
  maxItems={4}
/>

// With overflow - collapses middle items
<Breadcrumb
  items={longBreadcrumbList}
  maxItems={3}
  renderCollapsed={(items) => (
    <span>{items.length} more...</span>
  )}
/>
```

**Props:**

- `items`: BreadcrumbItem[] - Breadcrumb items
- `showHomeIcon`: boolean - Show home icon for first item
- `separator`: ReactNode - Custom separator
- `maxItems`: number - Max items before collapse (Phase 4)
- `renderCollapsed`: (items) => ReactNode - Custom collapsed renderer (Phase 4)
- `className`: string - Additional CSS class

### TopNav

Horizontal navigation bar for modern app layouts (Phase 4).

```typescript
import { TopNav } from "@mehdashti/shell";
import { Home, Users, Settings } from "lucide-react";

<TopNav
  links={[
    {
      id: "home",
      label: "Home",
      href: "/",
      icon: Home,
      active: true,
    },
    {
      id: "users",
      label: "Users",
      href: "/users",
      icon: Users,
      badge: 5,
    },
    {
      id: "settings",
      label: "Settings",
      href: "/settings",
      icon: Settings,
      disabled: true,
    },
  ]}
  onNavigate={(link) => navigate(link.href)}
/>
```

**Props:**

- `links`: TopNavLink[] - Navigation links
- `onNavigate`: (link: TopNavLink) => void - Navigation callback
- `className`: string - Additional CSS class

**TopNavLink Interface:**

```typescript
interface TopNavLink {
  id: string
  label: string
  href: string
  icon?: React.ComponentType<{ className?: string }>
  active?: boolean
  disabled?: boolean
  badge?: string | number
}
```

### DrilldownMenu

Hierarchical menu with drill-down navigation pattern (Phase 4).

```typescript
import { DrilldownMenu } from "@mehdashti/shell";
import { Folder, File } from "lucide-react";

const menuItems = [
  {
    id: "docs",
    label: "Documents",
    icon: Folder,
    children: [
      { id: "2023", label: "2023", icon: Folder, children: [...] },
      { id: "2024", label: "2024", icon: Folder, children: [...] },
    ],
  },
  { id: "settings", label: "Settings", icon: Settings },
]

<DrilldownMenu
  items={menuItems}
  onSelect={(item) => console.log("Selected:", item)}
  showBackButton={true}
/>
```

**Props:**

- `items`: DrilldownMenuItem[] - Menu items with optional children
- `onSelect`: (item: DrilldownMenuItem) => void - Selection callback
- `showBackButton`: boolean - Show back navigation button
- `className`: string - Additional CSS class

## Enterprise Layouts

### ObjectPage

SAP Fiori-style layout for entity detail pages with header, tabs, and sections (Phase 4).

```typescript
import { ObjectPage } from "@mehdashti/shell";
import { User, Mail, Phone } from "lucide-react";

<ObjectPage
  title="John Doe"
  subtitle="Senior Developer"
  avatar="/avatars/john.jpg"
  headerActions={
    <>
      <Button>Edit</Button>
      <Button variant="destructive">Delete</Button>
    </>
  }
  tabs={[
    {
      id: "overview",
      label: "Overview",
      icon: User,
      content: <div>Overview content</div>,
    },
    {
      id: "contact",
      label: "Contact",
      icon: Mail,
      badge: "3",
      content: <div>Contact information</div>,
    },
    {
      id: "activity",
      label: "Activity",
      disabled: true,
      content: <div>Activity feed</div>,
    },
  ]}
  sections={[
    {
      id: "personal",
      title: "Personal Information",
      content: <div>Personal details</div>,
    },
    {
      id: "professional",
      title: "Professional Details",
      collapsible: true,
      defaultExpanded: false,
      content: <div>Professional information</div>,
    },
  ]}
  stickyHeader={true}
/>
```

**Props:**

- `title`: string - Page title
- `subtitle`: string - Page subtitle
- `avatar`: string - Avatar URL
- `headerActions`: ReactNode - Actions in header
- `tabs`: ObjectPageTab[] - Tab configuration
- `sections`: ObjectPageSection[] - Section configuration
- `stickyHeader`: boolean - Sticky header on scroll
- `className`: string - Additional CSS class

### MasterDetail

Resizable two-panel layout for list-detail interfaces (Phase 4).

```typescript
import { MasterDetail } from "@mehdashti/shell";

<MasterDetail
  master={<UserList onSelectUser={setSelectedUser} />}
  detail={selectedUser ? <UserDetail user={selectedUser} /> : <EmptyState />}
  defaultMasterWidth={300}
  minMasterWidth={200}
  maxMasterWidth={500}
  showResizeHandle={true}
/>
```

**Props:**

- `master`: ReactNode - Master panel content (typically a list)
- `detail`: ReactNode - Detail panel content
- `defaultMasterWidth`: number - Initial master panel width in px
- `minMasterWidth`: number - Minimum master panel width in px
- `maxMasterWidth`: number - Maximum master panel width in px
- `showResizeHandle`: boolean - Show resize handle between panels
- `className`: string - Additional CSS class

### FlexibleColumn

Responsive 1-3 column layout with progressive disclosure (Phase 4).

```typescript
import { FlexibleColumn, type ColumnLayout } from "@mehdashti/shell";

const [layout, setLayout] = useState<ColumnLayout>("TwoColumnsBegin")

<FlexibleColumn
  begin={<ProductList onSelect={setProduct} />}
  middle={product ? <ProductDetail product={product} /> : <EmptyState />}
  end={variant ? <VariantDetail variant={variant} /> : null}
  layout={layout}
  onLayoutChange={setLayout}
  showLayoutToggles={true}
/>
```

**Layout Modes:**

- `OneColumn` - Show only middle column (detail)
- `TwoColumnsBegin` - Show begin (33%) + middle (67%)
- `TwoColumnsEnd` - Show middle (67%) + end (33%)
- `ThreeColumns` - Show begin (25%) + middle (50%) + end (25%)

**Props:**

- `begin`: ReactNode - Begin column content (typically list)
- `middle`: ReactNode - Middle column content (typically detail)
- `end`: ReactNode - End column content (typically nested detail)
- `layout`: ColumnLayout - Current layout mode
- `onLayoutChange`: (layout: ColumnLayout) => void - Layout change callback
- `showLayoutToggles`: boolean - Show layout toggle buttons
- `className`: string - Additional CSS class

### Dashboard

Grid-based layout for dashboard widgets (Phase 4).

```typescript
import { Dashboard } from "@mehdashti/shell";
import { MoreVertical } from "lucide-react";

<Dashboard
  widgets={[
    {
      id: "revenue",
      title: "Total Revenue",
      colSpan: 6,
      rowSpan: 1,
      content: <RevenueChart />,
      actions: (
        <Button variant="ghost" size="icon">
          <MoreVertical className="size-4" />
        </Button>
      ),
    },
    {
      id: "users",
      title: "Active Users",
      colSpan: 6,
      content: <UserStats />,
    },
    {
      id: "activity",
      title: "Recent Activity",
      colSpan: 12,
      content: <ActivityFeed />,
    },
  ]}
  columns={12}
  gap="md"
/>
```

**Props:**

- `widgets`: DashboardWidget[] - Widget configuration
- `columns`: 4 | 6 | 12 - Number of grid columns
- `gap`: "sm" | "md" | "lg" - Gap between widgets
- `className`: string - Additional CSS class

**DashboardWidget Interface:**

```typescript
interface DashboardWidget {
  id: string
  title?: string
  content: React.ReactNode
  colSpan?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
  rowSpan?: number
  actions?: React.ReactNode
  className?: string
}
```

## Types

### NavigationItem

```typescript
interface NavigationItem {
  id: string;
  label: string;
  icon?: LucideIcon;
  href?: string;
  badge?: string | number;
  active?: boolean;
  disabled?: boolean;
  children?: NavigationItem[];
}
```

### NavigationGroup

```typescript
interface NavigationGroup {
  id: string;
  label?: string;
  items: NavigationItem[];
}
```

### BreadcrumbItem

```typescript
interface BreadcrumbItem {
  label: string;
  href?: string;
}
```

### UserInfo

```typescript
interface UserInfo {
  name: string;
  email?: string;
  avatar?: string;
}
```

## Examples

### Nested Navigation

```typescript
const navigation = [
  {
    id: "main",
    items: [
      {
        id: "dashboard",
        label: "Dashboard",
        icon: Home,
        href: "/",
      },
      {
        id: "admin",
        label: "Admin",
        icon: Shield,
        children: [
          { id: "users", label: "Users", href: "/admin/users" },
          { id: "roles", label: "Roles", href: "/admin/roles" },
        ],
      },
    ],
  },
];
```

### With Badges

```typescript
const navigation = [
  {
    id: "main",
    items: [
      {
        id: "notifications",
        label: "Notifications",
        icon: Bell,
        href: "/notifications",
        badge: 12,
      },
      {
        id: "messages",
        label: "Messages",
        icon: MessageSquare,
        href: "/messages",
        badge: "New",
      },
    ],
  },
];
```

### Custom Header Actions

```typescript
import { Button } from "@mehdashti/ui/button";
import { Bell, Search } from "lucide-react";

<AppShell
  navigation={navigation}
  user={user}
  headerActions={
    <>
      <Button variant="ghost" size="icon">
        <Search className="size-5" />
      </Button>
      <Button variant="ghost" size="icon">
        <Bell className="size-5" />
      </Button>
    </>
  }
>
  <YourContent />
</AppShell>
```

### Router Integration

```typescript
// With React Router
import { useNavigate, useLocation } from "react-router-dom";

function App() {
  const navigate = useNavigate();
  const location = useLocation();

  const navigation = [
    {
      id: "main",
      items: [
        {
          id: "home",
          label: "Home",
          icon: Home,
          href: "/",
          active: location.pathname === "/",
        },
        {
          id: "users",
          label: "Users",
          icon: Users,
          href: "/users",
          active: location.pathname.startsWith("/users"),
        },
      ],
    },
  ];

  return (
    <AppShell
      navigation={navigation}
      onNavigate={(item) => {
        if (item.href) {
          navigate(item.href);
        }
      }}
    >
      <Outlet />
    </AppShell>
  );
}
```

### Responsive Sidebar

```typescript
import { useState, useEffect } from "react";

function App() {
  const [collapsed, setCollapsed] = useState(false);

  // Auto-collapse on mobile
  useEffect(() => {
    const handleResize = () => {
      setCollapsed(window.innerWidth < 768);
    };

    handleResize();
    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, []);

  return (
    <AppShell
      navigation={navigation}
      defaultSidebarCollapsed={collapsed}
    >
      <YourContent />
    </AppShell>
  );
}
```

## Styling

All components use design tokens from [@mehdashti/tokens](../tokens) and can be customized via CSS variables:

```css
:root {
  --background: #ffffff;
  --foreground: #09090b;
  --border: #e4e4e7;
  --accent: #f4f4f5;
  --accent-foreground: #18181b;
  /* ... more tokens */
}
```

## Accessibility

- All interactive elements have proper ARIA labels
- Keyboard navigation supported
- Focus visible states
- Screen reader friendly

## License

MIT