feat: add new components, Sidebar, TreeView, Pagination, Progress Stepper, File Upload#73
feat: add new components, Sidebar, TreeView, Pagination, Progress Stepper, File Upload#73ross-nics wants to merge 15 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces several new accessible UI components, including side navigation, tree view, pagination, progress stepper, and file upload, complete with SCSS styles, JavaScript behavior, HTML partials, and documentation. Feedback on these additions highlights opportunities to improve accessibility and robustness: specifically, refining the tree view click handler to target labels and prioritizing selected nodes for roving tabindex, adding outline: none to the transparent file input to prevent overlapping focus rings, ensuring progressive enhancement for the side navigation when JavaScript is disabled, and ensuring pre-selected tree view nodes are visible by default by expanding their parent elements.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| function ensureSingleTabstop () { | ||
| const all = items() | ||
| if (all.length === 0) return | ||
| const hasFocusable = all.some(it => it.tabIndex === 0) | ||
| all.forEach(it => { | ||
| if (it.tabIndex !== 0 && it.tabIndex !== -1) it.tabIndex = -1 | ||
| }) | ||
| if (!hasFocusable) all[0].tabIndex = 0 | ||
| } |
There was a problem hiding this comment.
在 ensureSingleTabstop() 中,若目前沒有可聚焦的節點,預設會將第一個節點(all[0])設為 tabIndex = 0。然而,如果樹狀檢視中已經有被選取的節點(aria-selected="true"),根據 WAI-ARIA APG 最佳實踐,應優先將焦點停靠點設在該選取節點上,以提供更好的鍵盤操作體驗。
function ensureSingleTabstop () {
const all = items()
if (all.length === 0) return
const hasFocusable = all.some(it => it.tabIndex === 0)
all.forEach(it => {
if (it.tabIndex !== 0 && it.tabIndex !== -1) it.tabIndex = -1
})
if (!hasFocusable) {
const selected = all.find(it => it.getAttribute('aria-selected') === 'true')
if (selected) {
selected.tabIndex = 0
} else {
all[0].tabIndex = 0
}
}
}| <li | ||
| role="treeitem" | ||
| aria-expanded="false" | ||
| aria-level="2" | ||
| aria-selected="false" | ||
| aria-labelledby="tvb-js" | ||
| tabindex="-1" | ||
| > |
There was a problem hiding this comment.
在此基本範例中,子節點「共同投標」預設為選取狀態(aria-selected="true"),但其父節點「採購作業」卻預設為收合狀態(aria-expanded="false")。這會導致頁面載入時,當前選取的活動節點被隱藏,使用者無法直觀地看到自己目前所在的位置。建議將父節點的預設狀態改為展開(aria-expanded="true")。
| <li | |
| role="treeitem" | |
| aria-expanded="false" | |
| aria-level="2" | |
| aria-selected="false" | |
| aria-labelledby="tvb-js" | |
| tabindex="-1" | |
| > | |
| <li | |
| role="treeitem" | |
| aria-expanded="true" | |
| aria-level="2" | |
| aria-selected="false" | |
| aria-labelledby="tvb-js" | |
| tabindex="-1" | |
| > |
支援無障礙日期選擇器,含降級策略: - 無 JS:原生 <input type="date"> - 觸控裝置:維持原生輸入 - 桌面 + JS:增強為 combobox + dialog + grid 模式
0ba1e2f to
bb4b232
Compare
- tree-view: restrict click handling to .tree-view__label to avoid parent node mis-selection on nested group whitespace - tree-view: prefer aria-selected node for initial roving tabstop (WAI-ARIA APG) - file-upload: hide native input default focus ring (outline: none); focus shown on button via :focus-within - side-navigation: gate collapsed-submenu hiding behind [data-js-enhanced] for progressive enhancement
新增五個元件
本 PR 為設計指引新增五個無障礙元件,皆遵循原生 HTML 語意搭配 ARIA 補強、不僅依賴色彩傳達資訊、並符合最小點擊區域(2.5rem)與漸進增強原則。所有元件成熟度標示為
new。元件清單
<input type="file">之上<ol>與aria-current="step"主要變更內容
content/components/*/_index.md,包含說明、變體、CSS 類別、使用規範、親和力與參考資料。file-upload.scss、pagination.scss、progress-stepper.scss、side-navigation.scss、tree-view.scss,並於main.scss匯入。side-navigation.js:切換<button>的aria-expanded狀態。tree-view.js:Roving tabindex 焦點管理與方向鍵展開/收合等完整鍵盤操作。無障礙重點
aria-hidden="true"隱藏避免重複朗讀,錯誤以aria-invalid標示。<nav>地標 +aria-current="page",省略符號以aria-hidden隱藏並補語意標籤。aria-current="step"與視覺隱藏的完成狀態文字。<nav>/<ul>/<button>+aria-expanded/aria-current,當前頁面同時以粗體與左側邊框指示。role="tree"/group/treeitem、aria-level、aria-labelledby(修正 VoiceOver 相容性)。