UI 基礎元件——實用指南
如果你曾經看著一個現代應用程式,心想「那個東西到底叫什麼?」——這個頁面就是為你而寫的。
你使用的每一個介面,都是由數量驚人地少的可重複使用元件所組成,這些元件被稱為 UI 基礎元件(UI primitives)。它們都有名字。有時候名字還挺奇怪的。但一旦你理解了背後的比喻,就再也回不去了。
En Parlant~ 使用 Mantine,一個 React 元件庫,內建提供了所有這些元件。以下就是你的實用指南。
聽起來像家具的那些
Section titled “聽起來像家具的那些”Toast(吐司通知)
Section titled “Toast(吐司通知)”Toast 是一個從螢幕邊緣彈出的小通知,停留幾秒鐘後滑走。就像一片麵包從烤麵包機彈出來——只不過重力方向相反,它最終會自己縮回去。
在 En Parlant~ 中,toast 出現在右下角(透過 Mantine 的 @mantine/notifications),用於以下情境:
- 「資料庫載入成功」——彈
- 「TTS 語音未設定」——彈
- 「無法連線至 Lichess」——彈,然後你會有點難過
你從來沒有主動要求它們。它們就是自己出現、傳達訊息、然後離開。它們是 UI 世界裡的信鴿。
Card(卡片)
Section titled “Card(卡片)”Card 是一個帶有邊框或陰影的矩形容器,將相關內容組合在一起。想像一張放在桌上的索引卡——它有明確的邊界、承載一件事情,而且你可以拿起來移動。
在 En Parlant~ 中,你會看到卡片用於:
- 對局預覽,在資料庫瀏覽器中(
GameCard)——棋手姓名、結果、日期 - 棋盤位置編輯器(
EditingCard)——設定自訂局面時翻開的那張卡片 - 資料庫條目,在資料庫頁面上——每個資料庫都有自己的卡片排列在網格中
Card 有一個近親叫做 Paper,基本上就是一張上過藝術學校的卡片。概念相同——一個帶有邊框或陰影的容器——但語義意義較少。Paper 只是說「我是一個表面。」它出現在分析面板和資料庫資訊顯示的背景中。
Drawer / Sheet(抽屜 / 面板)
Section titled “Drawer / Sheet(抽屜 / 面板)”目前在 En Parlant~ 中沒有使用,但值得了解:drawer 是一個從螢幕邊緣滑入的面板,就像一個書桌抽屜。(就這樣。整個比喻就是這麼直白。UI 設計師那天非常務實。)
擋住你去路的那些
Section titled “擋住你去路的那些”Modal(模態對話框)
Section titled “Modal(模態對話框)”Modal 是一個彈出式對話框,要求你集中注意力。它會將背景變灰,讓你必須先處理它才能做其他事情。它是 UI 模式中的幼兒——「現在馬上看我!」
En Parlant~ 在真正需要你專注的時刻使用 modal:
- 「確定要清除所有資料嗎?」(
ClearDataModal)——附有核取方塊讓你選擇哪些資料要清除 - 「有可用更新」(
UpdateModal)——下載時顯示進度條 - 「匯入對局」(
ImportModal)——貼上 PGN、輸入 FEN 或拖放連結 - 「建立新開局庫」(
CreateRepertoireModal)——命名、設定、開始 - 「關於 En Parlant~」(
About)——版本資訊、致謝名單,一般的幕後通行證
Modal 說的是:「這是一段對話。我們現在就要進行。」
Dialog(對話框)
Section titled “Dialog(對話框)”Dialog 是 modal 的有禮貌表親。在 Mantine 中,它們基本上是同一個元件,但在 UI 設計理論中,dialog 更小、更聚焦——一個簡單的問答。「要儲存變更嗎?」是 / 否。結束。
En Parlant~ 使用 ConfirmModal 處理這類快速的是非題,例如確認你是否要捨棄未儲存的變更。
來來去去的那些
Section titled “來來去去的那些”Tooltip(工具提示)
Section titled “Tooltip(工具提示)”Tooltip 是當你將滑鼠懸停在某個東西上方時出現的小標籤。它就像一個好心的路人,在你一臉困惑時悄悄告訴你答案。
Tooltip 在 En Parlant~ 中無處不在。幾乎懸停在任何圖示按鈕上都會看到:
- 懸停在 ↻ 按鈕上 → 「重新載入」
- 懸停在被截斷的檔案路徑上 → 顯示完整路徑
- 懸停在註解符號上 → 該符號的含義
- 懸停在分析面板中的走步上 → 彈出一個迷你棋盤預覽
Tooltip 是最原始的「不需要說明書」。
Popover(彈出框)
Section titled “Popover(彈出框)”Popover 是念了研究所的 tooltip。它不只是顯示一段文字標籤,還可以包含任何東西——按鈕、圖片,甚至一個小棋盤。
在 En Parlant~ 中,當你將滑鼠懸停在引擎分析中的某一步棋上時,popover 會渲染出該位置的棋盤預覽。它是一個 tooltip,但帶了視覺輔助教材。
Menu(選單)
Section titled “Menu(選單)”Menu 是當你點擊(或右鍵點擊)某個東西時出現的動作列表。從電腦誕生以來你就在用它們——檔案、編輯、檢視。你懂的。
En Parlant~ 有兩種風味:
- 頂部選單列 ——經典的「檔案 / 編輯 / 檢視」選單列,使用 Mantine 的
Menu元件建構。鍵盤快速鍵列在右邊。這個設計模式老到可以領退休金了。 - 右鍵選單 ——在棋譜樹中的某一步棋上按右鍵,你會看到「升級變著」、「從這裡刪除」、「複製棋步序列」等選項。這些使用
mantine-contextmenu函式庫以獲得更精緻的效果。
選單有自己的子詞彙:Menu.Target(你點擊的東西)、Menu.Dropdown(出現的列表)、Menu.Item(每個選項)和 Menu.Divider(那條細線表示「現在是不同區段了」)。
組織空間的那些
Section titled “組織空間的那些”Stack 與 Group
Section titled “Stack 與 Group”這兩個是排版界的花生醬和果醬。
- Stack 將元素垂直排列——一個疊在另一個上面。就像堆書一樣。
- Group 將元素水平排列——並排放置。就像把棋子排列在架子上。
它們各自出現在超過 100 個檔案中。它們是整個應用程式中最常見的元件。每當東西排列整齊,背後就有 Stack 或 Group 在負責。
Flex 是 Stack 和 Group 的瑞士刀表親。當東西需要換行、延伸、縮小、反轉或做出其他異常行為時,Flex 就帶著對 CSS Flexbox 模型的完整控制登場了。
用在分析面板的走步列表中——那些像文字一樣換行流動的走步序列?那就是 Flex 在幕後出力。
Box 是一個戴了高帽的 <div>。它本身什麼都不做——只是一個通用容器。但它接受 Mantine 的樣式屬性,這使得它成為「我需要在這個東西外面包一層」時極其好用的包裝器。
Box 出現在 150 多個檔案中。它是元件庫裡的萬用膠帶。
Center
Section titled “Center”功能如其名。把東西放在正中央。水平置中。垂直置中。兩者兼具。搞定。
出現在空白狀態中——當沒有連結帳號、沒有載入資料庫、還沒有資料的時候。一個大圖示、一段訊息,然後 Center 確保它們完美定位。沒有人喜歡偏離中心的空白狀態。
SimpleGrid
Section titled “SimpleGrid”一個很簡單的網格。你告訴它要幾欄,它就把你的卡片排列成整齊的網格,並隨著視窗大小重新排列。資料庫頁面用它來以響應式網格呈現資料庫卡片。
ScrollArea
Section titled “ScrollArea”一個當內容溢出時可以捲動的容器。你可能覺得這應該是免費的——透過 CSS overflow: auto 確實是——但 ScrollArea 加上了樣式化的捲軸、慣性捲動和溢出偵測。它包裹著棋譜樹面板、分析行,以及任何內容可能長得比容器還高的地方。
AppShell
Section titled “AppShell”AppShell 是主版面配置——整個應用程式的骨架。它定義了頁首的位置、側邊欄的位置,以及主內容區域的位置。其他所有東西都嵌套在它裡面。
你只會用它一次。它是房屋的地基。
Portal
Section titled “Portal”Portal 是一個神奇的蟲洞。它將元件渲染到 DOM 樹中正常位置以外的地方——通常是文件的根節點。這就是 popover 和棋盤預覽如何避免被設有 overflow: hidden 的父容器裁切的方式。
你永遠看不到 Portal 本身。你只看到它的效果。它是 UI 元件中的幕後工作人員。
你會互動的那些
Section titled “你會互動的那些”Button(按鈕)
Section titled “Button(按鈕)”一個可點擊的帶有文字的矩形。你認識它。在 Mantine 中,按鈕有不同的樣式變體(variants):
- filled ——實心色彩,高強調。「點我,我很重要。」
- outline ——只有邊框。「我是個選項,但別有壓力。」
- subtle ——幾乎看不見。「需要的時候我在。」
- default ——中性的折衷方案。
En Parlant~ 在 150 多個檔案中使用了所有這些變體。最常見的模式:在 modal 底部的一排 Group 按鈕——「取消」(subtle)和「確認」(filled)。經典。
ActionIcon
Section titled “ActionIcon”ActionIcon 是一個放棄了文字標籤、全心擁抱圖示生活方式的按鈕。它緊湊、方正,依靠圖示(加上 tooltip)來傳達用途。
工具列按鈕、面板控制按鈕、關閉按鈕——都是 ActionIcon。它們是提供操作的最節省空間的方式。
Switch(開關)
Section titled “Switch(開關)”Switch 是一個看起來像迷你電燈開關的切換控制。往左撥、往右撥。開。關。
在設定中,開關控制二元選擇:
- 聲音開/關
- TTS 語音朗讀啟用/停用
- 深色模式 / 淺色模式
這個物理比喻好到連你的祖父母都能理解。
Slider(滑桿)
Section titled “Slider(滑桿)”Slider 是一條帶有把手的軌道,你可以前後拖動來選擇一個值。就像一個被壓扁的音量旋鈕。
En Parlant~ 使用滑桿的場景:
- 字體大小 ——拖動調整
- 音量 ——拖動調整(當然)
- CPU 核心數 ——引擎應該使用多少核心?
- 雜湊記憶體 ——引擎的雜湊表要用多少 RAM?
還有一個 RangeSlider,帶有兩個把手用於選擇範圍——用來按照 Elo 等級分(例如 2000–2200)和時間區間篩選對局。
SegmentedControl(分段控制)
Section titled “SegmentedControl(分段控制)”一排按鈕,同一時間只能選擇其中一個。就像汽車收音機的預設頻道——按下一個,其他的就彈起來。
用於切換:
- 分析圖表上的厘兵值評估 vs. 勝/和/負機率
- 不同的走步記譜格式
- 引擎分析行數
Checkbox 與 Select
Section titled “Checkbox 與 Select”你認識這些。Checkbox(核取方塊)用於「勾選所有適用的選項」,Select(下拉選單)用於「從列表中選一個」。它們出現在整個應用程式的設定、篩選器和表單中。清除資料的 modal 有一組特別令人滿足的核取方塊,讓你可以選擇自己的毀滅方式。
Autocomplete(自動完成)
Section titled “Autocomplete(自動完成)”一個在你輸入時建議補全內容的文字輸入框。資料庫瀏覽器中的棋手搜尋使用了它——開始輸入名字,匹配的棋手就會出現在下方。
FileInput 與 DateInput
Section titled “FileInput 與 DateInput”FileInput 在點擊時開啟檔案選擇器——在匯入 modal 中用於載入 PGN 檔案。DateInput 彈出日曆以選擇日期——用於按日期篩選對局。還有 MonthPickerInput 和 YearPickerInput,用於不需要那麼精確的時候(Lichess 資料庫按月篩選、Masters 資料庫按年篩選)。
顯示進度的那些
Section titled “顯示進度的那些”Progress Bar(進度條)
Section titled “Progress Bar(進度條)”一個從左到右填充的水平條,顯示某件事進行到哪裡了。用於應用程式更新(下載進度),以及——更有創意地——用於在分析面板中顯示勝/和/負機率。三個彩色區段(白、灰、黑)按比例填充進度條。它是一個偽裝成進度指示器的迷你長條圖。
Loader(載入指示器)
Section titled “Loader(載入指示器)”Loader 是一個旋轉動畫,表示「我正在處理,等我一下。」在資料庫載入、棋手統計資料擷取中,或任何非同步操作進行時出現。
Skeleton(骨架屏)
Section titled “Skeleton(骨架屏)”Skeleton 是一個模仿尚未載入內容形狀的灰色佔位符。不是空白畫面或旋轉指示器,而是顯示卡片和文字即將出現位置的幽靈輪廓。它是載入狀態的建築藍圖——「真正的家具已經在路上了。」
資料庫頁面在卡片網格載入時使用骨架屏。比單獨使用旋轉指示器優雅得多。
LoadingOverlay(載入覆蓋層)
Section titled “LoadingOverlay(載入覆蓋層)”一層半透明的遮罩覆蓋在正在載入的元件上。分析圖表使用了這個——你仍然可以透過遮罩看到圖表,但它被調暗了,上面還有一個旋轉指示器。「我還在這裡,只是在更新。」
標記事物的那些
Section titled “標記事物的那些”Badge(徽章)
Section titled “Badge(徽章)”Badge 是一個小型彩色標籤——就像會議上的名牌。在 En Parlant~ 中,SpeedBadge 元件使用徽章以色彩編碼顯示時間控制:
- 🩷 粉紅色 — UltraBullet
- 🔴 紅色 — Bullet
- 🟠 橘色 — Blitz
- 🟢 綠色 — Rapid
- 🔵 藍色 — Classical
- 🟣 紫色 — Correspondence
每個徽章都小巧、色彩鮮明,一眼就能傳達對局的時間模式。
keyboard 的縮寫。以那種特徵性的凸起按鍵樣式顯示鍵盤按鍵。在按鍵綁定設定中用來顯示 Ctrl + Z 之類的內容。它是用 CSS 重現你鍵盤上實體按鍵的效果。令人愉悅的擬物設計。
分隔與摺疊的那些
Section titled “分隔與摺疊的那些”Divider(分隔線)
Section titled “Divider(分隔線)”一條分隔區段的水平線。就這樣。它是一條線。但它是一條有樣式的線,而且可以選擇性地在中間放一個文字標籤——就像匯入 modal 中「貼上 PGN」和「輸入 FEN」之間的「— 或 —」分隔線。
超過三十個檔案使用了 Divider。事實證明,東西經常需要被分隔。
Collapse(摺疊)
Section titled “Collapse(摺疊)”Collapse 是一個可以平滑動畫展開和收合的區段。點擊展開,再點擊隱藏。資料庫的篩選選項使用了這個——你不一定總是需要看到每個篩選器,所以它們藏在 Collapse 後面,直到你需要時再展開。
RichTextEditor(富文字編輯器)
Section titled “RichTextEditor(富文字編輯器)”一個完整的所見即所得文字編輯器,建立在 TipTap 之上。粗體、斜體、列表,應有盡有。用於撰寫對局註解——你為了解釋某一步棋為什麼精妙或糟糕而添加的評論筆記。
這是唯一一個與其說是單一細胞,不如說是複合有機體的基礎元件。底層是 TipTap + ProseMirror + Mantine 樣式。但從使用者的角度來看,它只是一個格式化功能正常運作的文字方塊。
AreaChart(面積圖)
Section titled “AreaChart(面積圖)”來自 @mantine/charts(它包裝了 Recharts),AreaChart 驅動了評估圖表——分析面板底部那條波形圖。中線以上的白色區域表示白方佔優;下方的黑色區域表示黑方佔優。
你可以點擊圖表上的任何一點跳到那一步棋。互動式資料視覺化與西洋棋分析的完美結合。它甚至有自訂 tooltip 和標記對局階段的參考線(開局 → 中局 → 殘局)。
DataTable(資料表格)
Section titled “DataTable(資料表格)”透過 mantine-datatable 函式庫——一個功能完整的資料表格,支援排序、分頁、列選取和篩選。驅動資料庫瀏覽器的對局列表、棋手列表和錦標賽列表。它是一個知道自己在西洋棋應用程式裡的試算表。
有些基礎元件本身不渲染任何可見的東西,但讓其他一切正常運作:
- MantineProvider ——包裝整個應用程式,提供主題(色彩、深色模式、元件預設值)
- Portal ——將渲染內容傳送到 DOM 的另一個位置
- useHotkeys ——一個 hook(不是元件),用來綁定鍵盤快速鍵
- useForm ——管理表單狀態、驗證和錯誤處理
- useDebouncedValue ——等你停止輸入後再觸發搜尋。有禮貌的 hook。
供參考,以下是 En Parlant~ 中使用的每一個基礎元件家族,按功能分組:
| 類別 | 基礎元件 |
|---|---|
| 排版 | AppShell, Box, Center, Flex, Group, Stack, SimpleGrid, ScrollArea, Portal |
| 表面 | Card, Paper |
| 覆蓋層 | Modal, Tooltip, Popover, Menu, ContextMenu, LoadingOverlay |
| 通知 | Toast(透過 @mantine/notifications) |
| 按鈕 | Button, ActionIcon, CloseButton, ThemeIcon |
| 輸入 | TextInput, Textarea, NumberInput, Select, Autocomplete, Checkbox, Switch, Slider, RangeSlider, SegmentedControl, FileInput, DateInput, MonthPickerInput, YearPickerInput |
| 資料顯示 | Table, DataTable, Badge, Code, Kbd, Rating, Image |
| 文字排版 | Text, Title, Anchor |
| 進度 | Progress, Loader, Skeleton |
| 結構 | Divider, Collapse |
| 豐富內容 | RichTextEditor (TipTap), AreaChart (Recharts) |
| 主題 | MantineProvider, createTheme, useColorScheme |
| Hooks | useForm, useHotkeys, useToggle, useDebouncedValue, useClickOutside, useElementSize |
全部來自 Mantine v8 及其生態系套件:@mantine/core、@mantine/notifications、@mantine/dates、@mantine/charts、@mantine/form、@mantine/tiptap、mantine-datatable 和 mantine-contextmenu。
現在你知道了
Section titled “現在你知道了”下次你看到一條小訊息從螢幕角落滑上來——那是 toast。對局預覽周圍的矩形——那是 card。內容載入前閃爍的灰色色塊——那些是 skeleton。
一旦你學會了這些名字,就會開始到處看到它們。每個應用程式。每個網站。同樣的二十幾個基礎元件,以千百種不同的方式重新組合。
一路往下拆,全是樂高積木。