Day 1 提到,希望把不同系統中重複出現的 UI 整理成共用元件,也希望把 Accessibility 從開發後期的檢查項目,往前移到 Component 的設計階段。
既然方向已經決定了,接下來似乎就可以直接:
npm create vite@latest
然後開始寫 Component。
不過在真的建立專案之前,我想先把另一件事情想清楚:
這套 UI Kit 到底要給誰用?
實際想了一下目前需要維護的系統,發現答案其實不只有 React。
目前工作上維護的網站與系統並不是使用同一套技術建立的。
新的系統可以使用比較現代的前端框架,但同時還是有不少既有的 Legacy Web 需要繼續維護。
而且不同時期建立的系統,也常常有自己的 UI。
可能都是一顆「儲存」按鈕:
系統 A → 一種 Button
系統 B → 另一種 Button
系統 C → 又有自己的 CSS
即使有一些共用 CSS,隨著系統增加,樣式還是很容易慢慢長成不同的樣子,維護起來不太方便。
所以這次想做的 UI Kit,如果最後只能在新的 React 專案裡使用,好像還是只解決了一半的問題。
Legacy Web 不會因為一套新的 UI Kit出現,就突然全部重寫成 React。
如果可以全部重寫當然很好。
但現實通常不是這樣。
因此希望這套 UI Kit 最後能做到的,不只是:建立一套 React Components
而是:
讓不同技術環境的系統,也能逐漸使用同一套 UI 與 Accessibility 規範。
目前整理出三種主要的使用情境。
新的 React 專案,可以直接使用 UI Kit 提供的 Components。
例如未來可能會像這樣:
<Button variant="primary">
儲存
</Button>
Button 的樣式、狀態、Focus、Disabled 等規則都由 UI Kit 統一處理,而不是每建立一個系統,就重新寫一次。
但既有系統裡還有一些不是 React。
例如目前仍然需要維護的原生頁面。
這些頁面不太可能為了使用 UI Kit 全部改寫成 React,所以我希望最後也能同時輸出 CSS 與必要的 JavaScript,讓 Legacy Web 可以透過 CDN 的方式使用。
概念上可能會像:
<link rel="stylesheet" href="ui-kit.min.css">
<script src="ui-kit.min.js"></script>
這樣即使不是 React 專案,也能逐步使用同一套 Design Tokens、Component Style 與互動規範。
至於 React Component 和 Legacy Web 最後到底要怎麼共用這些東西,現在還沒有打算一次把答案全部決定好。
這也是接下來 30 天想慢慢實作看看的一部分。
既然元件開始共用了,就會出現另一個問題:
其他人怎麼知道這顆 Component 要怎麼用?
Button 有哪些 Variant?
Input 發生 Error 時要怎麼呈現?
Dialog 的鍵盤操作應該是什麼?
哪些 Accessibility 行為是使用元件時不能破壞的?
所以我希望之後透過 Storybook,把 Component 的 Variant、State、使用方式以及 Accessibility 注意事項整理成文件。
另外,現在寫程式已經不一定是「人」在讀文件。
如果 Storybook 是讓人知道怎麼使用 UI Kit,那是不是也可以整理一套規範,讓 AI 知道有哪些 Component、應該怎麼使用,以及哪些規則不能破壞?
這部分目前先留一個坑~
畢竟現在連第一顆 Button 都還沒有XD
把目前的需求整理,大概會變成這樣:
UI Kit
│
┌───────────┼───────────┐
▼ ▼ ▼
React Storybook CDN
│ │ │
新系統 文件 Legacy Web
React 和 CDN 是不同技術環境使用 UI Kit 的方式。
Storybook 則負責讓開發者知道這些元件有哪些狀態、應該如何使用,以及有哪些 Accessibility 規範需要注意。
而這幾個出口背後,希望最後都能建立在同一套:
至少目前的藍圖是這樣
30 天後會不會長得完全不一樣,就到時候再回來看。XD
知道大概想做什麼之後,終於可以來決定第一階段的開發環境了。
這次先從:
React + TypeScript + Vite
開始。
其中一個原因很直接:
我希望新的系統可以直接使用 React Components。
而且 UI Kit 本身就是由一個個 Component 組成,Button、Input、Dialog、Tabs 等元件都很適合用 Component 的方式拆分與組合。
且Day 1 已經決定會以 shadcn/ui 作為這次 UI Kit 的起點,因此 React 自然也成為目前的主要開發環境。
對一般網站來說,TypeScript 可以幫忙檢查型別。
但放到 UI Kit 裡,我覺得它還多了一個很重要的用途:
定義 Component API。
例如:
<Button variant="primary" size="sm">
儲存
</Button>
這顆 Button 到底有哪些 variant?
size 可以放哪些值?
還有哪些 Props?
這些其實都是 Component 設計的一部分。
透過 TypeScript,可以把這些使用規則更明確地描述出來,而不是只能靠文件告訴使用者:
「這裡記得只能填這幾個值喔。」
這次我需要的第一件事情,其實很單純:
快速建立一個 React + TypeScript 的開發環境。
Vite 本身提供 React + TypeScript 的 Template,也有 Dev Server、HMR 與 Production Build 等基本能力,因此很適合作為目前的開發起點。
而且這個專案後面還有另一個需求:
它最後不只是一個 Web App。
除了 React Components 之外,我還希望能輸出給 Legacy Web 使用的 Assets。
所以後面勢必還會碰到 Library Build、CSS、JavaScript 輸出等問題。
不過那是未來需要煩惱的事情。
Day 2 先讓專案跑起來就好。XD
前面想了這麼久,現在終於可以真的建立專案。
首先確認目前的 Node.js 版本。
node -v
接著建立 Vite 專案:
npm create vite@latest
依照提示選擇:
Framework: React
Variant: TypeScript
建立完成後:
cd <project-name>
npm install
npm run dev
如果一切正常,就可以看到 Vite 預設的 React 畫面。
至少目前還沒有 Error。
Day 2 開局順利。XD
*:Vite 對 Node.js 版本有最低需求,如果建立專案時出現 Node.js 版本相關警告,可以先確認 Node.js 是否符合官方文件的版本要求(node -v),若不符合可以裝nvm來管理不同版本。
專案建立成功之後先把 Vite 預設的 Demo 清掉。
Logo、Counter 和目前用不到的預設 Style 都先移除,讓 App.tsx 回到比較單純的狀態。
剩下:
function App() {
return (
<main>
<h1>Accessible UI Kit</h1>
</main>
)
}
export default App
目前 App 只需要負責讓我確認專案正常執行。
真正的 Components 之後再慢慢放進來。
我原本很容易在建立新專案時陷入一個問題:
「資料夾是不是應該先規劃完整?」
例如開始思考:
components/
primitives/
tokens/
themes/
patterns/
utilities/
...
結果資料夾很多。
Component:0。
所以這次先忍住。XD
目前只建立確定會需要的基本結構:
src/
├─ components/
├─ styles/
├─ lib/
├─ App.tsx
└─ main.tsx
components/ 放之後建立的 UI Components。
styles/ 預計放共用樣式以及後續會建立的 Design Tokens。
lib/ 則保留給共用的 Utilities。
至於 React Components 和 CDN Assets 最後要如何拆分、Design Tokens 要怎麼共用,現在先不急著決定。
讓架構跟著實際需求一起長。
等真正遇到問題,再來決定應該怎麼拆。
今天終於正式把專案建立起來了。
目前完成:
✓ 確認 UI Kit 的主要使用情境
✓ 畫出第一版架構
✓ 決定 React + TypeScript + Vite
✓ 建立 Vite 專案
✓ 清掉預設 Demo
✓ 建立最小的專案結構
✓ npm run dev 正常執行
雖然做到這裡:
還沒有任何一顆真正的 UI Component。
但至少現在已經知道,接下來做出來的 Component 最後要往哪裡去。
Day 1 已經決定這次會以 shadcn/ui 作為 UI Kit 的元件基礎。
但做到 Day 2 結束,我甚至還沒有把 shadcn/ui 裝進專案。XD
在直接開始之前,我想先弄懂一件事情:
shadcn/ui 到底是什麼?
它和一般安裝進 node_modules、然後直接 import 使用的 Component Library 有什麼不同?
當我們把一顆 shadcn/ui Component 加進專案時,到底拿到了哪些東西?
Day 3,就來正式認識 shadcn/ui!!