零截圖文件示意
問題
操作手冊配截圖,截圖第一天就開始過期。
改一次按鈕位置,全手冊的圖都要重錄。於是沒人重錄。於是手冊開始說謊—— 而且說謊的方式很難察覺:圖看起來很專業,只是跟現在的系統不一樣。
更慘的是有版本的系統:v1 的截圖、v2 的截圖、v3 的截圖, 沒有人知道哪一張對應哪一版。
做法:用真元件排出示意圖
重點控制項 → 元件庫的真元件 + <Spotlight> 圈起來
其餘區域 → <Placeholder> 佔位留白
整體版面 → <MockScreenFrame>
元件改版,示意圖跟著改版。沒有人需要去重拍任何東西。
三條規約
重點包 Spotlight(真元件),其餘一律 Placeholder。
不要用 Placeholder 去「假裝」一個真元件。那又變成一種會過期的截圖, 只是畫得比較醜。
聚光用與系統內導覽同一套視覺(同一個 .spotlight-ring)。
讀者在文件與系統裡看到同一種「看這裡」。
不要在文件裡另外設計一套紅框箭頭。多一套視覺語言就多一份要維護、 要解釋的東西。
把「禁止截圖」寫成守衛測試,不然三個月後一定有人偷偷加一張。
不要只靠 code review 的自律。趕時間的時候,截圖永遠是最快的選項。
取捨
代價:示意圖不會百分百等於實際畫面。 版面是簡化的、佔位塊是抽象的。
這是刻意的取捨:讀者需要的是「該點哪裡」,不是像素級復刻。 而且簡化過的示意圖反而更好讀——真實畫面上的雜訊會蓋過重點。
第二個代價:一張示意圖只能表達「一步」。
但這不是這個手法的天花板——只是單張圖的天花板。跨步流程用 多步流程播放器(把每一步各排一張圖,串起來), 「點下去是什麼手感」用嵌入的 story。 真正示意不了的只剩拖曳與連續動畫,那些交給短影片。
(這一段原本寫的是「只能示意靜態一步,跨頁流程示意不了」。那句話是錯的, 而且是最貴的一種錯:限制一旦寫進規範,就沒有人會再去挑戰它。)
多步流程播放器
這一節是規範,播放器元件還沒收
下面的規約已經定稿,但 packages/react 還沒有這支元件——
目前要做多步流程,是自己排幾張示意圖依序陳列。元件層的細部規約見
Mockup 的〈播放器的元件層規約〉。
單一示意圖只能表達一步。但使用者要學的東西幾乎都是一串: 先切到哪個分頁、再勾哪幾列、再按哪顆按鈕、按完會看到什麼。
做法:把同一條流程的每一步各排一張示意圖,放進一個播放器。
<MockFlow name="batch-review" />
├─ ① 切到「已確認」分頁 ← 示意圖 1(聚光在分頁)
├─ ② 勾選要處理的列 ← 示意圖 2(聚光在勾選欄)
├─ ③ 按「送出批次」 ← 示意圖 3(聚光在按鈕)
└─ ④ 完成後你會看到:狀態變成「已排程」 ← 示意圖 4(聚光在狀態徽章)
每一張仍然遵守上面的三條規約(真元件 + Spotlight + Placeholder),
播放器只是把它們串起來。元件改版時,整條流程一起跟著改版——
這是截圖式教學永遠做不到的事。
自動輪播,但要能停
預設每 4.2 秒換一步,滑鼠移入就暫停。
自動輪播的理由:讀者在掃頁面時,一張靜止的圖只會被當成插圖略過; 會動的東西會讓人停下來看。但一旦他停下來要看清楚, 繼續動就變成干擾——所以 hover 暫停不是加分項,是自動輪播的前提。
「展開全部」與列印共用同一套展開樣式
標頭放一顆切換鈕:展開全部 → 所有步驟同時顯示、各自帶字幕、停止輪播。
/* 螢幕:只顯示當前步 */
.flow-step { display: none; }
.flow-step.is-active { display: block; }
/* 展開全部:螢幕上的展開狀態 */
.flow-expanded .flow-step { display: block; }
.flow-expanded .flow-controls { display: none; }
/* 列印:同一個展開狀態,不另寫一套 */
@media print {
.flow-step { display: block !important; }
.flow-controls { display: none !important; }
}
一份規則兩個用途:想逐步對照著操作的讀者按下「展開全部」, 而他看到的版面就是他印出來會拿到的版面。 細節見列印與匯出第 9 條。
每條流程都要有直達入口
流程標頭放一個連到系統對應畫面的連結(「開啟此作業」)。
理由:讀者讀操作說明的時候,十次有九次是正要去做那件事。 看得到卻進不去,他得自己回到系統、找到那一區、切到那一頁—— 而那三步正是他來看說明的原因。
互動示意:什麼時候該嵌 Storybook
零截圖示意圖表達得了「該點哪裡」,表達不了「點下去的手感」—— 展開收合、切換狀態、輸入時的即時回饋。這時候嵌一個可操作的元件:
iframe 指向隨文件一起發佈的 Storybook。讀者不用離開文件就能動手玩,
而且玩到的是真的元件庫元件,不是仿製品。上面那一框就是這樣來的:
<StoryFrame id="元件-資料-資料表-datatable--完整功能" title="資料表" height={460} />
| 要表達什麼 | 用什麼 |
|---|---|
| 這個畫面長怎樣、該點哪裡 | 靜態示意圖(Mockup 積木) |
| 一連串步驟 | 多步播放器(見上節) |
| 這個元件操作起來是什麼感覺 | 嵌入 Storybook story |
| 實際資料長什麼樣 | 直達入口連到系統本身 |
嵌入一定要有守衛
嵌入是一種以字串為鍵的跨檔案引用,而字串沒有型別檢查: story 改名、export 改名、元件被刪,都不會有任何東西告訴你。
失敗的樣子不是壞掉,是安靜地變成一塊空白——沒有錯誤訊息、沒有紅燈, 只有讀者看到空白然後以為文件壞了。
所以本書自己配了一支守衛(tests/doc-hooks.test.ts):掃出文件裡的每一個嵌入引用,
與 stories 檔推導出的合法 id 集合比對,指向不存在的 story 就紅。
做法與失敗訊息的寫法見漂移防護的第 7 支。
列印時換成替代說明框
iframe 的內容印不出來(延遲載入、跨文件)。
列印時要把它換成一個說明框,明講「這裡原本是可操作的展示」,
而不是印一個空框或直接隱藏。規則見列印與匯出第 8 條。
延伸:文件站嵌真元件
同一個手法可以再往前一步:讓文件站直接編譯並渲染元件庫原始碼。
你正在讀的這一頁就是——上面那個示意圖不是圖片,是真的 React 元件。 做法見 治理 → 漂移防護。