元件總覽
:::info 內容來源
本頁依
appfuse-web/lib/components/README.md
與套件公開 barrel exports 整理。若名稱或型別有差異,以該版本安裝後的 TypeScript 宣告為準。
:::
AppFuse Web 提供 React 19 元件、react-hook-form 整合層、訊息服務、Hooks 與工具函數。 升級前請先閱讀 Web Changelog;以下清單描述目前發布線的公開介面。
匯入原則
使用功能所屬的公開 subpath,避免依賴套件內部檔案:
import { Button, DataTable, DatePicker, FileDownloadLink } from '@appfuse/appfuse-web/components'
import { Input, Select, validatorResolver } from '@appfuse/appfuse-web/form'
import { schema } from '@appfuse/appfuse-web/form/validator'
import { prompt, MessageToast, MessageDialog } from '@appfuse/appfuse-web/messaging'
import { useTimeout, useInfiniteList } from '@appfuse/appfuse-web/hooks'
import { cn, getApiErrorMessage, time } from '@appfuse/appfuse-web/utils'
components:不依賴 react-hook-form 的 UI primitive。form:綁定control、name與欄位錯誤的 react-hook-form wrapper。messaging:應用層全域訊息服務與容器。hooks、utils:跨元件使用的 Hooks 與工具。
資料輸入與表單
除 SelectMenu、OptionRow 等低階組裝元件外,下表元件同時提供
@appfuse/appfuse-web/components 的 UI 版,以及
@appfuse/appfuse-web/form 的 react-hook-form 版。
| 元件 | 用途與值契約 |
|---|---|
Input / Textarea | 單行與多行文字輸入 |
Checkbox / CheckboxGroup | 布林值或多選集合 |
Radio / RadioGroup | 單選集合 |
Switch | 布林開關 |
Select | 單選、多選、搜尋與建立選項 |
SelectMenu / OptionRow | 可獨立組裝的選單與 rich option;由 components 匯入 |
TagInput | 可建立的多值標籤輸入 |
RichTextEditor | 基於 Tiptap v3 / ProseMirror 的富文字編輯器 |
FileInput / MediaInput | 檔案與媒體選擇、驗證及預覽 |
DatePicker | type="local-date" 使用 ISO 日期字串;type="instant" 使用 Date |
TimePicker | LocalTime 語意;表單值為無時區的時間字串 |
DateTimePicker | type="local-date-time" 使用無時區字串;type="instant" 使用 Date |
兩個 picker 的 type 都是必填辨識欄位,讓 TypeScript 直接約束 value/onChange 的型別。
Instant 模式預設採瀏覽器時區,時區控制位於月曆標題;LocalDate(Time) 模式不顯示時區。
DatePicker 的 Instant 模式在未提供 instantTime 時正式預設為 start-of-day;改用
end-of-day 或自訂鐘面時間,必須由人類指定,或由 AI 建議並經人類確認。DateTimePicker 編輯後
以分鐘或秒精度重建 Instant,因此不保留毫秒。非法時區、非法 instantTime 與非法
DayStatus.date 會顯示欄位錯誤。
表單驗證
匯入路徑:@appfuse/appfuse-web/form/validator
| 匯出 | 說明 |
|---|---|
schema | 輕量 Schema 建構器 |
validatorResolver | react-hook-form resolver |
mapViolationsToFormErrors | 將後端 violations 映射為欄位錯誤 |
createServerErrorHandler | 建立一致的 Server error handler |
詳細用法請參閱表單元件指南。
動作與資料顯示
匯入路徑:@appfuse/appfuse-web/components
| 分類 | 元件 | 說明 |
|---|---|---|
| Actions | Button | variant、color、density、loading 與 confirmation |
| Actions | FileDownloadLink | 透過應用 HTTP client 下載受保護檔案 |
| Data Display | Badge | 狀態或標籤 chip |
| Data Display | DataTable | 傳統分頁與欄位操作 |
| Data Display | VirtualTable | 虛擬化表格與無限捲動 |
| Data Display | VirtualList | 自訂複合列的虛擬化清單 |
| Data Display | Icon | Lucide React 圖示包裝 |
| Data Display | MediaViewer | 圖片與影片檢視 |
| Data Display | PdfViewer | PDF 預覽、翻頁與縮放 |
| Data Display | AuthImage | 透過 HTTP client 載入需授權的圖片 |
下載受保護檔案
應用層不應直接以 <a href> 下載需要 Bearer token 的 API 檔案;瀏覽器原生導覽不會沿用
AppFuse HTTP client 的 base URL、認證與 401 refresh。改用 FileDownloadLink:
import { FileDownloadLink } from '@appfuse/appfuse-web/components'
<FileDownloadLink source={attachment.url} filename={attachment.filename}>
下載附件
</FileDownloadLink>
內部 API URL 會透過應用程式根節點 HttpClientProvider 注入的 client 取得 Blob,再觸發瀏覽器
下載。外部、presigned、blob: 與 data: URL 則直接交由瀏覽器處理,不會附加應用程式的
Authorization header。元件下載期間會自動禁止重複操作,失敗時預設顯示後端錯誤訊息。
若使用者操作的目的其實是頁面導航,仍應使用真正的 <a> 或路由元件。
圖表
匯入路徑:@appfuse/appfuse-web/components
圖表基於 Nivo 並使用 AppFuse 主題配色:
LineChart、AreaChartBarChart、PieChartRadarChart、ScatterPlotFunnelChart、ParallelCoordinates
版面、導航與覆蓋層
匯入路徑:@appfuse/appfuse-web/components
| 分類 | 元件 | 說明 |
|---|---|---|
| Layout | Card | 標頭、內文、表面層級與可折疊內容 |
| Layout | Fieldset | 語意化 fieldset / legend 表單分組 |
| Navigation | Tabs | 受控或非受控的鍵盤可操作分頁 |
| Overlays | Dropdown | Compound Component 下拉選單 |
| Overlays | Dialog | 任務型對話框外殼——title / description / children / footer 皆為 slot,承載表單、上傳與多步驟流程 |
| Overlays | Popover | 非模態互動浮層,支援 click/hover 與任意內容 |
| Overlays | Sheet | 貼邊任務外殼,支援 right/bottom responsive placement |
| Overlays | Tooltip | 浮動提示與位置控制 |
回饋與訊息
低階元件由 @appfuse/appfuse-web/components 匯入:
| 元件 | 說明 |
|---|---|
Alert | 頁面內的語意化狀態訊息 |
Toast / ToastContainer | 非阻塞式通知與定位容器 |
PromptDialog | 系統訊息對話框——severity 彩色標題列、字串內容與字串動作陣列 |
UnderConstruction | 尚未完成頁面的標準提示 |
MswHealthGuard | Prototype 的 MSW 攔截健康守衛(探測失效並自動恢復) |
應用程式通常改用 @appfuse/appfuse-web/messaging 的 prompt、
MessageToast 與 MessageDialog 管理全域訊息。詳見訊息系統指南。
Dialog 還是 PromptDialog?
兩支都是模態對話框,但服務不同角色,不可互換:
PromptDialog(Feedback) | Dialog(Overlays) | |
|---|---|---|
| 角色 | 系統訊息 | 任務介面 |
| 標題列 | severity 驅動的彩色列 | 中性列(可帶 icon) |
| 內容 | content: string | children: ReactNode + 選用 description |
| 動作 | actions: string[](資料陣列) | footer: ReactNode(自由 slot) |
| 驅動來源 | prompt.*() / MessageDialog | 呼叫端自行持有 open 狀態 |
判斷句:需要顯示一則訊息、或要一個是/否的答案 → PromptDialog;需要放一個表單、
一份摘要、或任何自訂動作鍵(含送出中鎖定)→ Dialog。
PromptDialog 的 content / actions 形狀直接對應 prompt 佇列的資料,刻意不接 ReactNode——
需要結構化內容時答案一律是 Dialog,而非擴充 PromptDialog。命名沿革見 ADR-010。
<Dialog
open={open}
onClose={close}
title="停用商品分類"
description="停用後,此分類將不再出現在新商品的選單中。"
closeDisabled={submitting}
footer={
<>
<Button variant="outline" color="neutral" onClick={close} disabled={submitting}>
取消
</Button>
<Button color="error" loading={submitting} onClick={deactivate}>
確認停用
</Button>
</>
}
>
<AffectedProductSummary products={products} />
</Dialog>
無障礙由框架吸收:focus trap、初始焦點與關閉後焦點還原皆內建,title 關聯
aria-labelledby、description 關聯 aria-describedby。closeDisabled 一次擋掉
關閉鈕、點擊背景與 ESC 三條途徑,用於送出期間防止半途關閉。
Hooks 與工具
Hooks
匯入路徑:@appfuse/appfuse-web/hooks
| Hook | 說明 |
|---|---|
useTimeout / useInterval | 自動清理的計時器 |
useFloatingPortal | 浮動定位與 Portal |
useInfiniteList | TanStack Query 無限清單 |
工具
匯入路徑:@appfuse/appfuse-web/utils
| 匯出 | 說明 |
|---|---|
createHttpClient / HttpClientProvider / useHttpClient | HTTP client 與 React context |
getApiErrorMessage | 從 RFC 7807 / violations 萃取可顯示的錯誤訊息 |
i18n / useTranslation / I18nProvider | 國際化 |
time / toDateString | 日期時間工具 |
logger | 日誌 |
cn | clsx + tailwind-merge 類別合併 |
cookie / environ / browser | 瀏覽器與環境工具 |
numeral / template / filter | 格式化、模板與查詢建構 |
詳細用法請參閱工具函數指南。
互動式 API 探索
元件的 props、狀態、設計語言矩陣與使用情境以
Storybook 為準。若本頁清單、Storybook 與安裝版本的 .d.ts
不一致,先確認網站與套件是否為同一次發布,再以安裝版本的型別宣告作為消費端契約。
共用設計原則
- 使用 DaisyUI 語意色與主題,不硬編碼 Tailwind 顏色。
- 資料輸入元件以
compact、comfortable密度維持一致尺寸。 - 公開 props 與鍵盤互動以 WCAG 2.1 AA 為基線。
- 只從
package.json#exports定義的 subpath 匯入,不使用dist/或lib/內部路徑。