feat(docs): add bilingual package documentation site

This commit is contained in:
Maofeng
2026-09-20 15:53:28 +08:00
parent 60f6f1fb1a
commit dc80bd8ae0
111 changed files with 6531 additions and 0 deletions
@@ -0,0 +1,40 @@
---
title: Appearance
description: Finish the application with persistent theme, color, and compact-layout preferences.
order: 22
toc:
- id: provide-ui-state
title: Provide UI state
- id: apply-preferences
title: Apply preferences
- id: add-locales
title: Add locales
---
## Provide UI state {#provide-ui-state}
Mount `UiStateProvider` near the application root. A controlled provider can persist every state update through its change handler.
```tsx
<UiStateProvider>
<AppearanceController />
<App />
<ThemeToggleButton />
</UiStateProvider>
```
## Apply preferences {#apply-preferences}
Render `AppearanceController` once so the current state becomes document classes and theme variables. `useUiState` reads or updates individual preferences, while `useResolvedTheme` returns the effective light or dark scheme after resolving system mode.
## Add locales {#add-locales}
Add the appearance catalog only when the application uses these controls:
```json
{
"catalogSources": ["@workspace/blocks/appearance/locales/{locale}"]
}
```
The application shell is now complete. Add only the other block-specific catalogs used by the product.
@@ -0,0 +1,34 @@
---
title: Media library
description: Supply a storage adapter and add browsing, upload, folders, and asset selection.
order: 21
toc:
- id: implement-the-adapter
title: Implement the adapter
- id: provide-media
title: Provide media
- id: selection-flows
title: Selection flows
---
## Implement the adapter {#implement-the-adapter}
`MediaAdapter` is the media feature's complete persistence boundary. Implement its query, upload, folder, update, and delete operations with the product's storage service.
## Provide media {#provide-media}
Mount the adapter once around the media surfaces:
```tsx
import { MediaLibrary, MediaProvider } from "@workspace/blocks/media"
;<MediaProvider adapter={mediaAdapter} notify={showNotice}>
<MediaLibrary />
</MediaProvider>
```
The optional `notify` callback translates operational results into the application's toast or notification system.
## Selection flows {#selection-flows}
Use `MediaPickerDialog` for single or multiple asset selection. `readMediaDimensions`, `formatMediaFileSize`, and `defaultMediaReference` cover the common presentation work around uploads and previews.
@@ -0,0 +1,21 @@
---
title: Notifications
description: Connect notification state without coupling the UI to a backend.
order: 20
toc:
- id: notifications-query
title: Notifications query
---
## Notifications query {#notifications-query}
Notifications use TanStack Query as their data boundary:
```tsx
const notifications = useNotifications({
queryKey: ["notifications"],
queryFn: loadNotifications,
})
```
The result includes unread counts, optimistic read-state updates, action execution, refetching, and pending or error status. `AppLayout` can create the sheet directly from the same query options.
@@ -0,0 +1,35 @@
---
title: Chats
description: Add a responsive conversation workspace and connect its events to application services.
order: 30
toc:
- id: render-the-workspace
title: Render the workspace
- id: controlled-state
title: Controlled state
- id: media-and-pagination
title: Media and pagination
---
## Render the workspace {#render-the-workspace}
`ChatWorkspace` renders conversation discovery, the active thread, and the composer:
```tsx
import { ChatWorkspace } from "@workspace/blocks/chats"
;<ChatWorkspace
conversations={conversations}
onSend={({ conversation, message }) => sendMessage(conversation, message)}
/>
```
## Controlled state {#controlled-state}
The active conversation, draft, search query, and Enter-to-send preference can be controlled individually. Leave a value undefined when the workspace should own that state.
The UI emits events but does not select a transport or persistence format. Map API responses into `ChatConversation` and the exported message variants at the application boundary.
## Media and pagination {#media-and-pagination}
Provide `resolveMediaUrl` when stored media references need signed or transformed URLs. Use `onLoadEarlierMessages` with `hasMoreMessages` and `isLoadingMoreMessages` to connect historical pagination.
@@ -0,0 +1,45 @@
---
title: Application shell
description: Assemble the shared header, sidebar, breadcrumbs, chat, and notification surfaces.
order: 11
toc:
- id: render-app-layout
title: Render AppLayout
- id: layout-inputs
title: Layout inputs
- id: optional-preset
title: Optional preset
---
## Render AppLayout {#render-app-layout}
`AppLayout` is the integration point for the rest of this tutorial:
```tsx
import { AppLayout } from "@workspace/blocks/layout"
export function WorkspaceLayout() {
return (
<AppLayout
navigationGroups={navigationGroups}
notifications={{
queryKey: ["notifications"],
queryFn: loadNotifications,
}}
chatThreads={chatThreads}
>
<Outlet />
</AppLayout>
)
}
```
## Layout inputs {#layout-inputs}
The shell composes `AppSidebar`, `AppBreadcrumb`, `AppQueryIndicator`, `UserMenu`, a notification sheet, and chat threads. Pass `headerActions` when the product needs additional global controls.
The route content remains the layout's `children`, so the package does not constrain the router used by the application.
## Optional preset {#optional-preset}
`@workspace/blocks/layouts/vega` provides an optional visual shell. It lives on a separate entry point so the standard layout does not include preset-specific code.
@@ -0,0 +1,40 @@
---
title: Installation
description: Add the package, its styles, and the providers required by the tutorial.
order: 10
toc:
- id: add-the-package
title: Add the package
- id: import-styles
title: Import styles
- id: application-providers
title: Application providers
---
## Add the package {#add-the-package}
Add the workspace dependency to the consuming application:
```json
{
"dependencies": {
"@workspace/blocks": "workspace:*"
}
}
```
Blocks use `@workspace/ui`, React Query, and the workspace internationalization runtime. The workspace package manager resolves those dependencies for local applications.
## Import styles {#import-styles}
Import the block stylesheet once from the application entry:
```ts
import "@workspace/blocks/globals.css"
```
Keep feature imports on their explicit subpaths. For example, importing `@workspace/blocks/media` does not pull chat into the same module graph.
## Application providers {#application-providers}
The full shell expects React Query and internationalization to be available above it. Add those providers before the route tree, then continue to the application-shell chapter.
@@ -0,0 +1,46 @@
---
title: Navigation
description: Define navigation groups once and connect them to desktop and mobile surfaces.
order: 12
toc:
- id: define-groups
title: Define groups
- id: provide-navigation
title: Provide navigation
- id: route-state
title: Route state
---
## Define groups {#define-groups}
Start with typed `NavigationGroup` values. Items may represent direct routes or nested navigation branches.
```ts
import type { NavigationGroup } from "@workspace/blocks/navigation"
export const navigationGroups: NavigationGroup[] = [
{
id: "workspace",
label: "Workspace",
items: [
{ id: "dashboard", label: "Dashboard", to: "/dashboard" },
{ id: "media", label: "Media", to: "/media" },
],
},
]
```
## Provide navigation {#provide-navigation}
`AppLayout` already mounts the provider and the responsive navigation surfaces. For a custom shell, compose them directly:
```tsx
<NavigationProvider groups={navigationGroups}>
<PrimaryNavigation groups={navigationGroups} />
<MobileNavigationSheet groups={navigationGroups} />
</NavigationProvider>
```
## Route state {#route-state}
Use `resolveNavigationRouteState` for the standard route model. Applications with custom routing can supply a `GetNavigationRouteState` implementation while keeping the same navigation UI.
+33
View File
@@ -0,0 +1,33 @@
---
title: Overview
description: Understand how the Blocks package turns UI primitives into complete application features.
order: 1
toc:
- id: what-you-will-build
title: What you will build
- id: design-boundary
title: Design boundary
- id: tutorial-map
title: Tutorial map
---
## What you will build {#what-you-will-build}
This tutorial builds an application shell step by step. You will begin with the shared layout, connect navigation, then add notifications, chat, media, and appearance preferences.
By the end, the application owns its data and business rules while `@workspace/blocks` owns the reusable presentation and interaction patterns.
## Design boundary {#design-boundary}
Blocks sit above `@workspace/ui`. They combine low-level components into features, but they do not choose your API, database, router configuration, or storage provider.
> Keep data access in the host application. Pass it into a block through props, query functions, providers, or adapters.
## Tutorial map {#tutorial-map}
1. Install the package and global styles.
2. Create the application shell.
3. Define navigation and route state.
4. Connect notifications.
5. Add chat and media workflows.
6. Finish with persistent appearance controls.
@@ -0,0 +1,40 @@
---
title: 外观设置
description: 使用可持久化的主题、颜色和紧凑布局偏好完成应用。
order: 22
toc:
- id: provide-ui-state
title: 提供 UI 状态
- id: apply-preferences
title: 应用偏好
- id: add-locales
title: 添加词典
---
## 提供 UI 状态 {#provide-ui-state}
在应用根节点附近挂载 `UiStateProvider`。受控 Provider 可以通过变更处理器持久化每次状态更新。
```tsx
<UiStateProvider>
<AppearanceController />
<App />
<ThemeToggleButton />
</UiStateProvider>
```
## 应用偏好 {#apply-preferences}
渲染一次 `AppearanceController`,使当前状态转换为文档类名和主题变量。`useUiState` 读取或更新单个偏好,`useResolvedTheme` 在解析系统模式后返回最终的亮色或暗色主题。
## 添加词典 {#add-locales}
只有应用使用这些控件时才添加外观词典:
```json
{
"catalogSources": ["@workspace/blocks/appearance/locales/{locale}"]
}
```
至此应用外壳已经完成。其他功能也只需添加产品实际使用的 Block 词典。
@@ -0,0 +1,34 @@
---
title: 媒体库
description: 提供存储 Adapter,并加入浏览、上传、文件夹和资源选择能力。
order: 21
toc:
- id: implement-the-adapter
title: 实现 Adapter
- id: provide-media
title: 提供媒体能力
- id: selection-flows
title: 选择流程
---
## 实现 Adapter {#implement-the-adapter}
`MediaAdapter` 是媒体功能完整的持久化边界。通过产品存储服务实现查询、上传、文件夹、更新和删除操作。
## 提供媒体能力 {#provide-media}
在媒体界面外挂载一次 Adapter:
```tsx
import { MediaLibrary, MediaProvider } from "@workspace/blocks/media"
;<MediaProvider adapter={mediaAdapter} notify={showNotice}>
<MediaLibrary />
</MediaProvider>
```
可选的 `notify` 回调把操作结果转换为应用的 Toast 或通知。
## 选择流程 {#selection-flows}
单选或多选资源使用 `MediaPickerDialog`。`readMediaDimensions`、`formatMediaFileSize` 和 `defaultMediaReference` 覆盖上传与预览相关的常用展示工作。
@@ -0,0 +1,21 @@
---
title: 通知
description: 接入通知状态,同时避免让 UI 与后端耦合。
order: 20
toc:
- id: notifications-query
title: 通知查询
---
## 通知查询 {#notifications-query}
通知以 TanStack Query 作为数据边界:
```tsx
const notifications = useNotifications({
queryKey: ["notifications"],
queryFn: loadNotifications,
})
```
返回结果包含未读数量、乐观已读更新、操作执行、重新请求以及等待和错误状态。`AppLayout` 可以直接通过相同查询选项创建通知 Sheet。
@@ -0,0 +1,35 @@
---
title: 聊天示例
description: 添加响应式会话工作区,并将事件连接到应用服务。
order: 30
toc:
- id: render-the-workspace
title: 渲染工作区
- id: controlled-state
title: 受控状态
- id: media-and-pagination
title: 媒体与分页
---
## 渲染工作区 {#render-the-workspace}
`ChatWorkspace` 渲染会话查找、当前线程和消息编辑器:
```tsx
import { ChatWorkspace } from "@workspace/blocks/chats"
;<ChatWorkspace
conversations={conversations}
onSend={({ conversation, message }) => sendMessage(conversation, message)}
/>
```
## 受控状态 {#controlled-state}
当前会话、草稿、搜索词和回车发送偏好都可以单独受控。当工作区应自行管理某项状态时,不传对应值即可。
UI 只发送事件,不选择传输方式或持久化格式。在应用边界将 API 响应转换为 `ChatConversation` 和导出的消息类型。
## 媒体与分页 {#media-and-pagination}
当已存储媒体需要签名或转换 URL 时,提供 `resolveMediaUrl`。使用 `onLoadEarlierMessages`、`hasMoreMessages` 和 `isLoadingMoreMessages` 接入历史消息分页。
@@ -0,0 +1,45 @@
---
title: 应用外壳
description: 组装共享 Header、Sidebar、面包屑、聊天和通知界面。
order: 11
toc:
- id: render-app-layout
title: 渲染 AppLayout
- id: layout-inputs
title: 布局输入
- id: optional-preset
title: 可选预设
---
## 渲染 AppLayout {#render-app-layout}
`AppLayout` 是本教程其余部分的集成点:
```tsx
import { AppLayout } from "@workspace/blocks/layout"
export function WorkspaceLayout() {
return (
<AppLayout
navigationGroups={navigationGroups}
notifications={{
queryKey: ["notifications"],
queryFn: loadNotifications,
}}
chatThreads={chatThreads}
>
<Outlet />
</AppLayout>
)
}
```
## 布局输入 {#layout-inputs}
应用外壳组合了 `AppSidebar`、`AppBreadcrumb`、`AppQueryIndicator`、`UserMenu`、通知 Sheet 和聊天线程。产品需要更多全局控件时可传入 `headerActions`。
路由内容仍作为布局的 `children`,因此该包不会限制应用使用的路由器。
## 可选预设 {#optional-preset}
`@workspace/blocks/layouts/vega` 提供可选的视觉外壳。它位于独立入口,因此标准布局不会包含预设专属代码。
@@ -0,0 +1,40 @@
---
title: 安装
description: 添加教程所需的包、样式和 Providers。
order: 10
toc:
- id: add-the-package
title: 添加包
- id: import-styles
title: 导入样式
- id: application-providers
title: 应用 Providers
---
## 添加包 {#add-the-package}
在使用方应用中添加工作区依赖:
```json
{
"dependencies": {
"@workspace/blocks": "workspace:*"
}
}
```
Blocks 使用 `@workspace/ui`、React Query 和工作区国际化运行时。工作区包管理器会为本地应用解析这些依赖。
## 导入样式 {#import-styles}
在应用入口导入一次 Block 样式:
```ts
import "@workspace/blocks/globals.css"
```
功能模块应始终从显式子路径导入。例如,导入 `@workspace/blocks/media` 不会把聊天功能加入同一个模块图。
## 应用 Providers {#application-providers}
完整应用外壳要求上层已经提供 React Query 和国际化。在路由树之前加入这些 Providers,然后继续应用外壳章节。
@@ -0,0 +1,46 @@
---
title: 导航
description: 统一定义导航分组,并将其连接到桌面和移动端界面。
order: 12
toc:
- id: define-groups
title: 定义分组
- id: provide-navigation
title: 提供导航
- id: route-state
title: 路由状态
---
## 定义分组 {#define-groups}
从类型安全的 `NavigationGroup` 开始。导航项可以是直接路由,也可以是嵌套导航分支。
```ts
import type { NavigationGroup } from "@workspace/blocks/navigation"
export const navigationGroups: NavigationGroup[] = [
{
id: "workspace",
label: "工作区",
items: [
{ id: "dashboard", label: "仪表盘", to: "/dashboard" },
{ id: "media", label: "媒体", to: "/media" },
],
},
]
```
## 提供导航 {#provide-navigation}
`AppLayout` 已经挂载 Provider 和响应式导航界面。自定义外壳可以直接组合它们:
```tsx
<NavigationProvider groups={navigationGroups}>
<PrimaryNavigation groups={navigationGroups} />
<MobileNavigationSheet groups={navigationGroups} />
</NavigationProvider>
```
## 路由状态 {#route-state}
标准路由模型使用 `resolveNavigationRouteState`。使用自定义路由的应用可以提供 `GetNavigationRouteState` 实现,同时复用相同导航 UI。
+33
View File
@@ -0,0 +1,33 @@
---
title: 概览
description: 了解 Blocks 包如何把 UI 基础组件组合成完整应用功能。
order: 1
toc:
- id: what-you-will-build
title: 将要构建的内容
- id: design-boundary
title: 设计边界
- id: tutorial-map
title: 教程路线
---
## 将要构建的内容 {#what-you-will-build}
本教程会逐步构建一个应用外壳。你将从共享布局开始,接入导航,再添加通知、聊天、媒体和外观偏好。
完成后,应用负责数据和业务规则,`@workspace/blocks` 负责可复用的展示与交互模式。
## 设计边界 {#design-boundary}
Blocks 位于 `@workspace/ui` 之上。它们将底层组件组合成完整功能,但不会替你选择 API、数据库、路由配置或存储服务。
> 将数据访问保留在宿主应用中,通过属性、查询函数、Provider 或 Adapter 传给 Block。
## 教程路线 {#tutorial-map}
1. 安装包和全局样式。
2. 创建应用外壳。
3. 定义导航和路由状态。
4. 接入通知。
5. 添加聊天和媒体工作流。
6. 使用持久化外观控件完成应用。