自製 UI 準則
修改 SqlAssist.Ssms22 的視窗、對話框或控制項前必讀。本頁只定義視覺與排版;平台 生命週期另讀平台接線護欄,對話框殼層見對話框。
基準與方向
- 物件結構預覽是視覺基準:安靜、內容優先、層級清楚、少線條、精準對齊。
- 清除紀錄對話框是標準對話框範本:原生標題列、資訊列、分段與單一頁尾,規範見對話框。
- Apple-like 指的是克制、留白、材質層級與細緻回饋,不是照搬 macOS,也不是大量玻璃、 漸層、陰影或圓角。介面仍須像 SSMS 的一部分。
- 精緻感來自一致的比例與減法;裝飾不能搶過 SQL、欄位與狀態。
視窗只有一個抬頭
先選一種殼層,不得混用:
| 殼層 | 抬頭做法 |
|---|---|
DialogWindow | 使用原生 Titlebar;內容直接進入工具列、摘要或主內容,不再放同義大標題 |
| 編輯器浮動預覽 | 使用物件預覽的整合式 Header;名稱、摘要、主要操作只佔同一列區域 |
Titlebar 回答「這是哪個工具」,內容第一列只放新的資訊。欄數、列數、型別、長度等 脈絡應是淡色單行摘要,可併入工具列或主內容上緣;不能再做一個看起來像第二條 Titlebar 的粗體區塊。第一個內容區塊不留額外上緣標題間距。
版面層級
- 間距是 token 不是字面量:4/8/16 由
SqlAssistChrome.Spacing一份發布(雙欄 18、 視窗外距 16,例外由內容密度說明)。各處各填數字的話,階數會長出沒人說得出代表哪一級的中間值。 - 規則是層級單調(區塊之內不得大於區塊之間),絕對值隨表面密度:對話框是標籤到欄位 4、 同組內容 8、區塊與頁尾 16;停靠工具窗整組降一階——列之間 4,區塊之間與視窗外距 8。 工具列整塊與下方清單之間不能是 0,那是最該分開的一刀。
- 間距由容器宣告一次,不由相鄰兩個元素各出一半。 隨時
Collapsed的那幾塊(主機訊息、 狀態列)收起之後,各出一半的那一版留下半格空白,而收起正是它們的常態。一列的上下對稱, 除非說得出兩邊分量為什麼不同。 - 用留白與極淡底色分層,不用成排框線。
Surface只包真正獨立的一塊內容,避免 外框裡再套外框。 - 標題靠字重與位置,不靠任意放大。物件名稱與摘要疊兩行時,名稱正常前景、摘要淡色; 清單的筆數與「這一份為什麼不完整」寫在清單頁尾;效果在視窗外的動作結果走通知。 SQL Search 沒有狀態列;SQL Memory 的狀態列平時留空,只留說明畫面的那幾句。
- 主內容優先取得伸縮空間;工具列與頁尾維持
Auto。捲軸只出現在可能溢出的內容本身, 不讓整個對話框同時橫向與縱向捲動。 - 捲軸兩級:對話框、資料格、編輯區用原生樣式;限高輔助區塊(通知明細、過濾面板選項) 用覆蓋式
ApplyOverlayScroll,內容右緣留空隙;浮在內容上的表面(通知島)另開靜止淡出與邊緣淡出。 - 會出現水平捲軸的內容(不換行的 SQL 預覽與編輯、差異比對、欄多的資料格、儲存格完整內容) 一律接上
ApplyShiftWheelPan:WPF 原生只認垂直滾輪,少了它左右捲動只剩拖那條十幾 DIP 的軌道。 捲不動時不攔滾輪,否則按著 Shift 會整個捲不動。接在建立那塊捲動內容的地方(CreateDataGrid、SqlTextEditor),不在每個視窗各補一次:漏掉的那一個只有在使用者真的去捲的時候才看得出來。 - 多欄表依閱讀順序排:識別資訊 → 性質/狀態 → 統計或範圍。文字靠左、可比較的數字 對齊;寬欄吃剩餘空間,窄欄維持穩定寬度。
視覺語言只有一份
字型、字級、按鈕、輸入欄位、核取方塊、分頁、清單與資料格一律由 UI/SqlAssistChrome.cs 建立;顏色一律繫結 VsThemeBrushes 發布的動態資源, 不得保存一次性筆刷;取色與生命週期見主題連動。中性色由前景色按比例 混合,主要動作與選取由主題強調色推導,並檢查文字對比。不得在功能目錄複製樣板、硬寫 RGB,或讓 Windows 預設控制項在 SSMS 深色主題露出白底。
- 介面字型:
Segoe UI Variable Text,回退Segoe UI;獨立的 SQL/JSON/XML 編輯區用Cascadia Mono,再回退Consolas。物件預覽的指令碼分頁例外,跟隨 SSMS 編輯器字型 與字級,方便並排比對。 - 對話框固定用
DefaultMetrics;只有貼著編輯器的預覽內容跟隨preview.fontSize。 標題列控制項固定 12,不被內容字級擠大。 - 強調色只給真正的焦點、選取與稀少的重要狀態。主索引鍵已是預覽中的強調;一般旗標 使用中性膠囊,而且狀態不能只靠顏色表達。搜尋命中自成一組色票、不借強調底, 規範見命中高亮。
- 資料格不畫格線,以 4.5% 交替底色分列,表頭只留底線。交替色須設在 DataGrid 的
RowBackground/AlternatingRowBackground,不要用會被轉移屬性蓋掉的 Row trigger。 - 一個視窗只有一個主要動作;放在右側並給淡底。次要動作用幽靈按鈕,停駐或按下才顯色; 停駐色預設中性,語意色只給破壞性與收藏這類警示。
PreviewChrome.cs只保留預覽專屬的圖示控制項排版與旗標徽章;SQL 圖示來源見 共用元件表,種類文字仍保留在摘要。共用樣板仍回到SqlAssistChrome, 不另開 ResourceDictionary。- SQL 圖示保留原生目錄的語意配色,不強制染色或為了顏色替換成不相干圖示,避免補全、 QuickInfo 與預覽的呈現分歧;辨識同時依靠形狀、種類文字與 Tooltip。
- 自製 UI 的語意圖示一律以
SqlIcon取原生目錄,不畫向量替代;只有展開箭頭等控制項外觀用 Path。
互動與品質
- 所有可操作項目要有停駐、按下、停用與可見鍵盤焦點;Tab 順序跟視覺順序一致。
- 游標說出能做什麼:每一種按鈕、開關、連結與膠囊選項都是手形,跟著外觀的來源走——
CreateButton等工廠用SetClickCursor,樣式用ClickCursorSetter,呼叫端不各自補;核取方塊與選項圓鈕維持 箭頭。可拖曳的抬頭是搬動游標;按鈕不能從可拖曳的父代繼承搬動游標。 - 所有互動外框預留 1 DIP,只更換 brush,不因 hover/focus/selected 改 padding 或位移; 由
SqlAssistChrome共用樣板的視覺測試保證。 - 動畫只在能說明狀態時使用,並分兩級;兩級都受全域動畫設定控制。
- 內容表面(對話框、SQL Search/Memory 的預覽):出現是 120 ms ease-out 淡入,內容不縮放、不回彈。 內容本身沒有狀態要說,放大或回彈只是在搶讀 SQL 的注意力。浮在編輯器上的浮動預覽改走 通知島的編排(
SurfaceMotion、SurfaceCapsule):外形用彈簧從錨點的圓點長成膠囊再攤開, 內容晚一步淡入並只從 0.96 放大一次,見預覽視窗。 - 狀態回饋(通知與狀態圖示):可用不超過 400 ms 的單次縮放回饋與不超過 300 ms 的 位移標示狀態轉換,例如成功的微彈出與失敗的短震動。同一個狀態不重複播放,也不因為 別的項目更新而重播;一律走 RenderTransform,不改變版面尺寸。 展開、收合與新列出現這類揭露動畫不屬於狀態回饋,本來就會改變尺寸,時間仍要短而可中途反向。 例外:通知島與浮動預覽的外形可用彈簧,回彈 3% 以內、約 400 ms 收斂、可中途反向。 停駐回饋維持短而不改變版面尺寸。
- 內容表面(對話框、SQL Search/Memory 的預覽):出現是 120 ms ease-out 淡入,內容不縮放、不回彈。 內容本身沒有狀態要說,放大或回彈只是在搶讀 SQL 的注意力。浮在編輯器上的浮動預覽改走 通知島的編排(
- 淺色、深色、高對比、100%/150%/200% DPI、最小尺寸、長字串與鍵盤操作都要實測。 文字至少維持 4.5:1 對比;省略文字須能從 ToolTip 或完整內容取得。
通知表面
右下角的通知島是唯一的浮動狀態表面,不錨在 SqlAssist 對話框上。
- 玻璃背景以 224/255 覆蓋率起算;黑/白底色上的文字都要維持 4.5:1,不足就提高覆蓋率。不是原生 Mica,也不即時模糊 SQL;文字保持不透明,高對比回到實色背景並取消柔影。
- 柔影掛在底色層並點陣快取,變形不得每一影格重跑模糊。按鈕與附條沿用
SqlAssistChrome.Notifications; 狀態圖示只有SurfaceStatusIcon一份,重複次數用中性膠囊徽章(×N),不借狀態色。
新增或審查 UI 時先畫出「Titlebar/內容/頁尾」三區、刪除重複抬頭,再檢查唯一主要動作、 空白/載入/錯誤/停用狀態與鍵盤路徑。