Shell
主应用布局组件,包含侧边栏和标题栏
概述
Shell 是应用的主布局组件,提供:
- 顶部标题栏(TitleBar)
- 侧边栏导航
- 主内容区域
- 插槽支持
导入
import { Shell } from '@linch-tech/desktop-core';Props
interface ShellProps {
/**
* 子组件(在 noOutlet 模式下使用)
*/
children?: ReactNode;
/**
* 自定义 className
*/
className?: string;
/**
* 如果为 true,不渲染 Outlet(直接渲染 children)
*/
noOutlet?: boolean;
}基本用法
作为路由布局组件使用:
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>
);
}布局结构
┌─────────────────────────────────────────────────┐
│ TitleBar │
│ [Logo] [App Name] [Theme] [×] │
├────────────┬────────────────────────────────────┤
│ │ │
│ Sidebar │ Main Content │
│ │ (<Outlet />) │
│ [Nav 1] │ │
│ [Nav 2] │ │
│ [Nav 3] │ │
│ │ │
├────────────┤ │
│ [Footer] │ │
└────────────┴────────────────────────────────────┘noOutlet 模式
如果不使用 react-router-dom 的 Outlet,可以使用 noOutlet 模式:
<Shell noOutlet>
<MyContent />
</Shell>自定义样式
<Shell className="custom-shell-class" />配置驱动
Shell 的行为由配置控制:
// src/config.ts
export const config = {
nav: [
{ title: 'Home', path: '/', icon: Home },
{ title: 'Settings', path: '/settings', icon: Settings },
],
layout: {
sidebar: {
width: 200,
position: 'left', // 或 'right'
},
},
slots: {
sidebar: {
header: <WorkspaceSwitcher />,
footer: <UserProfile />,
},
shell: {
beforeContent: <AlertBanner />,
},
},
};覆盖 Shell 组件
完全自定义 Shell:
import type { ShellProps } from '@linch-tech/desktop-core';
function CustomShell({ children, className, noOutlet }: ShellProps) {
return (
<div className={className}>
{/* 完全自定义的布局 */}
<MyCustomSidebar />
<main>
{noOutlet ? children : <Outlet />}
</main>
</div>
);
}
// 在配置中使用
export const config = {
components: {
Shell: CustomShell,
},
};导航项渲染
导航项根据配置自动渲染,支持:
- 图标
- 标题(支持 i18n)
- 徽标
- 激活状态高亮
自定义导航项组件:
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,
},
};侧边栏插槽
| 插槽 | 位置 |
|---|---|
slots.sidebar.header | 侧边栏顶部 |
slots.sidebar.beforeNav | 导航列表前 |
slots.sidebar.afterNav | 导航列表后 |
slots.sidebar.footer | 侧边栏底部 |
Shell 插槽
| 插槽 | 位置 |
|---|---|
slots.shell.beforeContent | 主内容区域上方 |
slots.shell.afterContent | 主内容区域下方 |