iT邦幫忙

2026 iThome 鐵人賽

DAY 2
0
自我挑戰組

30 天打造 Accessible UI Kit:從 shadcn/ui 到自己的 Design System系列 第 2

Day2: 開工!用 Vite + React + TypeScript 建立 UI Kit

  • 分享至 

  • xImage
  •  

Day 1 提到,希望把不同系統中重複出現的 UI 整理成共用元件,也希望把 Accessibility 從開發後期的檢查項目,往前移到 Component 的設計階段。

既然方向已經決定了,接下來似乎就可以直接:

npm create vite@latest

然後開始寫 Component。

不過在真的建立專案之前,我想先把另一件事情想清楚:

這套 UI Kit 到底要給誰用?

實際想了一下目前需要維護的系統,發現答案其實不只有 React。


先別急著 npm create:這套 UI Kit 要解決什麼?

目前工作上維護的網站與系統並不是使用同一套技術建立的。

新的系統可以使用比較現代的前端框架,但同時還是有不少既有的 Legacy Web 需要繼續維護。

而且不同時期建立的系統,也常常有自己的 UI。

可能都是一顆「儲存」按鈕:

系統 A → 一種 Button
系統 B → 另一種 Button
系統 C → 又有自己的 CSS

即使有一些共用 CSS,隨著系統增加,樣式還是很容易慢慢長成不同的樣子,維護起來不太方便。

所以這次想做的 UI Kit,如果最後只能在新的 React 專案裡使用,好像還是只解決了一半的問題。

Legacy Web 不會因為一套新的 UI Kit出現,就突然全部重寫成 React。

如果可以全部重寫當然很好。

但現實通常不是這樣。

因此希望這套 UI Kit 最後能做到的,不只是:建立一套 React Components

而是:

讓不同技術環境的系統,也能逐漸使用同一套 UI 與 Accessibility 規範。


誰會使用這套 UI Kit?

目前整理出三種主要的使用情境。

1. React:給新的系統使用

新的 React 專案,可以直接使用 UI Kit 提供的 Components。

例如未來可能會像這樣:

<Button variant="primary">
  儲存
</Button>

Button 的樣式、狀態、Focus、Disabled 等規則都由 UI Kit 統一處理,而不是每建立一個系統,就重新寫一次。

2. CDN:給 Legacy Web 使用

但既有系統裡還有一些不是 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 天想慢慢實作看看的一部分。

3. Storybook:給開發者看的使用說明

既然元件開始共用了,就會出現另一個問題:

其他人怎麼知道這顆 Component 要怎麼用?

Button 有哪些 Variant?

Input 發生 Error 時要怎麼呈現?

Dialog 的鍵盤操作應該是什麼?

哪些 Accessibility 行為是使用元件時不能破壞的?

所以我希望之後透過 Storybook,把 Component 的 Variant、State、使用方式以及 Accessibility 注意事項整理成文件。

另外,現在寫程式已經不一定是「人」在讀文件。

如果 Storybook 是讓人知道怎麼使用 UI Kit,那是不是也可以整理一套規範,讓 AI 知道有哪些 Component、應該怎麼使用,以及哪些規則不能破壞?

這部分目前先留一個坑~

畢竟現在連第一顆 Button 都還沒有XD


UI Kit 的第一版藍圖

把目前的需求整理,大概會變成這樣:

                  UI Kit
                    │
        ┌───────────┼───────────┐
        ▼           ▼           ▼
      React      Storybook      CDN
        │           │            │
     新系統        文件       Legacy Web
                                

React 和 CDN 是不同技術環境使用 UI Kit 的方式。

Storybook 則負責讓開發者知道這些元件有哪些狀態、應該如何使用,以及有哪些 Accessibility 規範需要注意。

而這幾個出口背後,希望最後都能建立在同一套:

  • Design Tokens
  • Component Rules
  • Accessibility Rules

至少目前的藍圖是這樣

30 天後會不會長得完全不一樣,就到時候再回來看。XD


技術選型:React + TypeScript + Vite

知道大概想做什麼之後,終於可以來決定第一階段的開發環境了。

這次先從:

React + TypeScript + Vite

開始。

為什麼是 React?

其中一個原因很直接:

我希望新的系統可以直接使用 React Components。

而且 UI Kit 本身就是由一個個 Component 組成,Button、Input、Dialog、Tabs 等元件都很適合用 Component 的方式拆分與組合。

且Day 1 已經決定會以 shadcn/ui 作為這次 UI Kit 的起點,因此 React 自然也成為目前的主要開發環境。

為什麼使用 TypeScript?

對一般網站來說,TypeScript 可以幫忙檢查型別。

但放到 UI Kit 裡,我覺得它還多了一個很重要的用途:

定義 Component API。

例如:

<Button variant="primary" size="sm">
  儲存
</Button>

這顆 Button 到底有哪些 variant

size 可以放哪些值?

還有哪些 Props?

這些其實都是 Component 設計的一部分。

透過 TypeScript,可以把這些使用規則更明確地描述出來,而不是只能靠文件告訴使用者:

「這裡記得只能填這幾個值喔。」

為什麼使用 Vite?

這次我需要的第一件事情,其實很單純:

快速建立一個 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


終於可以 npm create 了

前面想了這麼久,現在終於可以真的建立專案。

首先確認目前的 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

專案建立成功之後先把 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 要怎麼共用,現在先不急著決定。

讓架構跟著實際需求一起長。

等真正遇到問題,再來決定應該怎麼拆。


Day 2 Done

今天終於正式把專案建立起來了。

目前完成:

✓ 確認 UI Kit 的主要使用情境
✓ 畫出第一版架構
✓ 決定 React + TypeScript + Vite
✓ 建立 Vite 專案
✓ 清掉預設 Demo
✓ 建立最小的專案結構
✓ npm run dev 正常執行

雖然做到這裡:

還沒有任何一顆真正的 UI Component。

但至少現在已經知道,接下來做出來的 Component 最後要往哪裡去。


下一步:shadcn/ui 到底扮演什麼角色?

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!!


上一篇
Day1: 都有 shadcn/ui 了,為什麼還要做自己的 UI Kit?
下一篇
Day 3: shadcn/ui 到底是什麼?它和一般元件庫有什麼不同?
系列文
30 天打造 Accessible UI Kit:從 shadcn/ui 到自己的 Design System3
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言