141 lines
4.1 KiB
Markdown
141 lines
4.1 KiB
Markdown
|
|
# Layout
|
|||
|
|
|
|||
|
|
`@workspace/layout` 提供路由无关的应用级布局。`AppLayout` 以内容区为核心,并按需组合 Header、Navigation Rail、Sidebar、Aside 和 Footer。
|
|||
|
|
|
|||
|
|
## 安装样式源
|
|||
|
|
|
|||
|
|
在应用的全局样式中导入:
|
|||
|
|
|
|||
|
|
```css
|
|||
|
|
@import "@workspace/layout/globals.css";
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 布局模型
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
+-------------------------------------+
|
|||
|
|
| header | headerStart="rail"
|
|||
|
|
+------+---------+---------+----------+
|
|||
|
|
| | header | headerStart="sidebar"
|
|||
|
|
| +---------+---------+----------+
|
|||
|
|
| | | header | headerStart="content"
|
|||
|
|
| | +---------+----------+
|
|||
|
|
| | | | |
|
|||
|
|
| rail | sidebar | content | |
|
|||
|
|
| | +---------+ aside |
|
|||
|
|
| | | footer | | footerStart="content"
|
|||
|
|
| +---------+---------+ |
|
|||
|
|
| | footer | | footerStart="sidebar"
|
|||
|
|
+------+-------------------+----------+
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图中的多个 Header 和 Footer 表示可选位置,不会同时渲染。`children` 是唯一必需的内容区,其他区域均为可选 slot:
|
|||
|
|
|
|||
|
|
- `rail`:最外侧的一级导航,类似 Activity Bar。
|
|||
|
|
- `sidebar`:当前一级导航下的导航或工作区上下文。
|
|||
|
|
- `aside`:AI、文档、检查器等内容辅助区域。
|
|||
|
|
- `header`:右边界始终包含有效的 `aside`。
|
|||
|
|
- `footer`:始终属于中心工作区,不会延伸到 `rail` 或 `aside` 下方。
|
|||
|
|
|
|||
|
|
## 基本用法
|
|||
|
|
|
|||
|
|
Slot 可以接收已经创建的 React 节点,也可以接收无必需属性的组件定义。组件定义在 `AppLayout` 的 Provider 内创建,因此可以调用 `useLayoutConfig`。
|
|||
|
|
|
|||
|
|
```tsx
|
|||
|
|
import { AppLayout } from "@workspace/layout"
|
|||
|
|
|
|||
|
|
export function Application() {
|
|||
|
|
return (
|
|||
|
|
<AppLayout
|
|||
|
|
header={AppHeader}
|
|||
|
|
rail={ActivityRail}
|
|||
|
|
sidebar={<NavigationSidebar groups={navigationGroups} />}
|
|||
|
|
aside={AssistantPanel}
|
|||
|
|
footer={StatusBar}
|
|||
|
|
defaultLayout={{
|
|||
|
|
asideOpen: true,
|
|||
|
|
footerStart: "sidebar",
|
|||
|
|
headerStart: "sidebar",
|
|||
|
|
}}
|
|||
|
|
>
|
|||
|
|
<RouterOutlet />
|
|||
|
|
</AppLayout>
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## LayoutConfig
|
|||
|
|
|
|||
|
|
`LayoutConfig` 是扁平、可序列化的完整快照;`layout` 和 `defaultLayout` 接收 `Partial<LayoutConfig>`。
|
|||
|
|
|
|||
|
|
```ts
|
|||
|
|
interface LayoutConfig {
|
|||
|
|
asideEnabled: boolean
|
|||
|
|
asideOpen: boolean
|
|||
|
|
footerStart: "sidebar" | "content"
|
|||
|
|
headerStart: "rail" | "sidebar" | "content"
|
|||
|
|
sidebarCollapsible: boolean
|
|||
|
|
sidebarOpen: boolean
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
默认值:
|
|||
|
|
|
|||
|
|
```ts
|
|||
|
|
const defaultLayoutConfig = {
|
|||
|
|
asideEnabled: true,
|
|||
|
|
asideOpen: false,
|
|||
|
|
footerStart: "content",
|
|||
|
|
headerStart: "rail",
|
|||
|
|
sidebarCollapsible: true,
|
|||
|
|
sidebarOpen: true,
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- 提供 `layout` 时采用受控模式,交互后通过 `onLayoutChange` 返回完整快照。
|
|||
|
|
- 未提供 `layout` 时采用非受控模式,以 `defaultLayout` 或默认配置初始化。
|
|||
|
|
- 区域暂时不可用只影响有效布局,不会覆盖配置中保存的用户偏好。
|
|||
|
|
|
|||
|
|
## useLayoutConfig
|
|||
|
|
|
|||
|
|
区域组件可以读取布局状态并触发布局更新:
|
|||
|
|
|
|||
|
|
```tsx
|
|||
|
|
import { useLayoutConfig } from "@workspace/layout"
|
|||
|
|
|
|||
|
|
export function AppHeader() {
|
|||
|
|
const {
|
|||
|
|
layout,
|
|||
|
|
setAsideOpen,
|
|||
|
|
setSidebarOpen,
|
|||
|
|
toggleAside,
|
|||
|
|
toggleSidebar,
|
|||
|
|
updateLayout,
|
|||
|
|
} = useLayoutConfig()
|
|||
|
|
|
|||
|
|
// Render application controls.
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Hook 必须在 `AppLayout` 子树内调用。`updateLayout` 接收局部配置或根据当前完整配置生成局部配置的函数。
|
|||
|
|
|
|||
|
|
## 自动内移
|
|||
|
|
|
|||
|
|
`headerStart` 和 `footerStart` 表示期望位置。布局会根据当前实际可见的区域计算有效位置,但不会改写原配置:
|
|||
|
|
|
|||
|
|
- `headerStart="rail"` 表示全局 Header;没有 Rail 时从第一个实际存在的区域开始。
|
|||
|
|
- 只有 Rail 与 Sidebar 同时可见时,`headerStart="sidebar"` 和 `footerStart="sidebar"` 才会生效。
|
|||
|
|
- 其他情况下,`"sidebar"` 自动内移为 `"content"`。
|
|||
|
|
- Aside 始终贯穿中心工作区高度,不参与 Footer 范围。
|
|||
|
|
|
|||
|
|
## 尺寸
|
|||
|
|
|
|||
|
|
可以通过 CSS 自定义属性调整三个辅助列:
|
|||
|
|
|
|||
|
|
```css
|
|||
|
|
.application-layout {
|
|||
|
|
--layout-rail-width: 4rem;
|
|||
|
|
--layout-sidebar-width: 18rem;
|
|||
|
|
--layout-aside-width: 22rem;
|
|||
|
|
}
|
|||
|
|
```
|