LobeHub React 元件撰寫慣例。用於編輯 TSX UI、選擇 base-ui 與 @lobehub/ui 與 antd、使用 antd-style 進行樣式設計、路由、桌面版變體、佈局或元件狀態時使用。
React 元件撰寫指南
樣式設計
| 情境 | 做法 |
|---|---|
| 大部分情況 | createStaticStyles + cssVar.*(零執行時期、模組層級) |
| 簡單一次性使用 | 行內 style 屬性 |
真正動態(JS 顏色函式如 readableColor/chroma) |
createStyles + token — 最後手段 |
元件優先順序
src/components— 專案專用的可重用元件@lobehub/ui/base-ui— 無頭(headless)基礎元件。如果元件存在於此,請使用它。不要匯入同名根匯出。@lobehub/ui— 較高層級 / 包裝 antd 的元件(僅在 base-ui 沒有對應元件時使用)- antd — 僅在 base-ui 和
@lobehub/ui根目錄都沒有提供時使用 - 自訂實作 — 真正的最後手段
如果不確定有哪些可用元件,請搜尋現有程式碼或檢查 node_modules/@lobehub/ui/es/index.mjs 和 node_modules/@lobehub/ui/es/base-ui/。
@lobehub/ui/base-ui — 以下情況永遠優先使用
| 元件 | 匯入方式 |
|---|---|
Select(+ SelectProps、SelectOption) |
import { Select } from '@lobehub/ui/base-ui'; |
Modal(指令式 API) |
import { createModal, confirmModal, useModalContext, type ModalInstance } from '@lobehub/ui/base-ui'; |
DropdownMenu |
import { DropdownMenu } from '@lobehub/ui/base-ui'; |
ContextMenu |
import { ContextMenu } from '@lobehub/ui/base-ui'; |
Popover |
import { Popover } from '@lobehub/ui/base-ui'; |
ScrollArea |
import { ScrollArea } from '@lobehub/ui/base-ui'; |
Switch |
import { Switch } from '@lobehub/ui/base-ui'; |
Toast |
import { Toast } from '@lobehub/ui/base-ui'; |
FloatingSheet |
import { FloatingSheet } from '@lobehub/ui/base-ui'; |
針對 Modal,請參閱專門的 modal 技能 — 使用指令式 createModal({ content: … }) 模式,而非舊式的 <Modal open … /> 宣告式模式。base-ui 已在 SPAGlobalProvider 中掛載了自己的 ModalHost。
常見錯誤:
import { Select } from '@lobehub/ui'看起來沒問題,但它是基於 antd 的 Select。請使用 base-ui 的 Select。Modal、DropdownMenu等元件也相同。
@lobehub/ui 根目錄 — 當 base-ui 沒有對應元件時使用
| 分類 | 元件 |
|---|---|
| 通用 | ActionIcon、ActionIconGroup、Block、Button、Icon |
| 資料顯示 | Avatar、Collapse、Empty、Highlighter、Markdown、Tag、Tooltip |
| 資料輸入 | CodeEditor、CopyButton、EditableText、Form、Input、InputPassword、SearchBar、TextArea |
| 回饋 | Alert、Drawer |
| 佈局 | Center、DraggablePanel、Flexbox、Grid、Header、MaskShadow |
| 導航 | Burger、Menu、SideNav、Tabs |
載入指示器
不要使用 antd 的 Spin / <Spin />。 請使用專案的載入器(NeuralNetworkLoading、DotsLoading 等)— 請參閱 ux 技能(「載入視覺效果」)以取得元件表格及使用時機。
狀態管理
當一個功能元件管理超過 3 個狀態(useState/useReducer/衍生狀態)時,請將邏輯提取到自訂 Hook(例如 useXxx)。讓元件專注於渲染 — Hook 持有狀態和處理函式,這樣邏輯就可以在不渲染元件的情況下進行單元測試。
佈局
使用 @lobehub/ui 提供的 Flexbox 和 Center。請參閱 references/layout-kit.md 以取得完整屬性和範例。
- 使用
gap而非margin來設定 flex 子項目的間距 - 使用
flex={1}來填滿可用空間 - 巢狀使用 Flexbox 來處理複雜佈局;設定
overflow: 'auto'以啟用可滾動區域
導航
對於 SPA 頁面,請使用 react-router-dom,而不是 next/link。
// ❌ 錯誤
import Link from 'next/link';
// ✅ 正確
import { Link, useNavigate } from 'react-router-dom';
從 store 存取 navigate:useGlobalStore.getState().navigate?.('/settings');
桌面版檔案同步規則
具有 .desktop.ts(x) 變體的檔案必須同步編輯。不同步會導致 Electron 中出現空白頁面。
| 基礎檔案(網頁) | 桌面版檔案(Electron) |
|---|---|
desktopRouter.config.tsx |
desktopRouter.config.desktop.tsx |
componentMap.ts |
componentMap.desktop.ts |
編輯任何 .ts/.tsx 後: 在相同目錄中搜尋 <filename>.desktop.{ts,tsx}。如果找到,請套用對應的同步匯入變更。
路由架構
| 路由類型 | 用途 | 實作方式 |
|---|---|---|
| Next.js App Router | 認證外殼 | src/app/spa-auth/(HTML 外殼;請參閱 spa-routes) |
| React Router DOM | 認證頁面 | src/routes/auth/(登入、註冊、OAuth 等) |
| React Router DOM | 主要 SPA | desktopRouter.config.tsx + .desktop.tsx(成對) |
路由工具:
import { dynamicElement, redirectElement, ErrorBoundary } from '@/utils/router';
element: dynamicElement(() => import('./chat'), 'Desktop > Chat');
element: redirectElement('/settings/profile');
errorElement: <ErrorBoundary />;
常見錯誤
| 錯誤 | 修正方式 |
|---|---|
在 SPA 中使用 next/link |
使用 react-router-dom 的 Link |
| 直接使用 antd | 優先使用 @lobehub/ui/base-ui,再使用 @lobehub/ui |
使用 antd 的 Spin / <Spin /> 作為載入指示器 |
使用 NeuralNetworkLoading / 專案載入器(請參閱 ux 技能) |
import { Select } from '@lobehub/ui' |
import { Select } from '@lobehub/ui/base-ui' |
import { Modal } from '@lobehub/ui' + <Modal open> 宣告式 |
使用 @lobehub/ui/base-ui 的 createModal / confirmModal(請參閱 modal 技能) |
import { DropdownMenu/Popover/Switch } from '@lobehub/ui' |
改從 @lobehub/ui/base-ui 匯入同名元件 |
對靜態樣式使用 createStyles |
使用 createStaticStyles + cssVar |
只編輯 desktopRouter.config.tsx |
必須同時編輯 .tsx 和 .desktop.tsx |
使用 margin 設定 flex 間距 |
使用 Flexbox 的 gap 屬性 |
| 未使用 selector 存取 zustand store | 使用 selector 存取 store 資料(請參閱 zustand 技能) |
使用 Flexbox/Text + onClick 建立文字或圖示文字操作 |
使用 Button type={'text'} size={'small'},並在需要時加上 icon |






