# ThemePicker Lưới ô chọn màu giao diện, mỗi ô là một vòng tròn chia đôi (nền / màu nhấn) của chính theme đó. ## Khi nào dùng - Hộp thoại "Màu giao diện" trong Cài đặt. - Năm theme: Kem sữa, Nâu cà phê, Sô cô la, Đêm dịu (bốn theme của game) và Tương phản cao (`hc`, theme do design system thêm, đạt ngưỡng tương phản AAA cho chữ (SC 1.4.6) và 3:1 cho viền, focus, đồ hoạ (SC 1.4.11) trên các preview, kể cả các trạng thái mở bằng JS có `data-audit-click`). ## Biến thể | Biến thể | Lớp | Dùng khi | |---|---|---| | 3 cột | `tt-theme-picker` | Mặc định như game (lưới 3 cột, gap 8px). Với 5 theme thành 3 + 2: hàng dưới có hai ô căn trái và một ô trống ở cuối, nhìn vẫn cân vì mọi ô cùng bề rộng; đây là bố cục chuẩn cho 5 theme | | 2 cột | `tt-theme-picker tt-theme-picker--two` | Chỉ hợp khi số theme chẵn; với 5 theme thành 2 + 2 + 1 và ô cuối mồ côi, nên tránh | ## Cấu trúc ```html
``` Ô màu mang `data-theme` của chính nó nên luôn hiện đúng màu theme đó, dù trang đang ở theme nào. ## Trạng thái | Trạng thái | Hiệu ứng | |---|---| | Chưa chọn | Viền `line`, nền `bg` | | `aria-checked="true"` | Viền `pink` và vòng 2px `pink` (`shadow-ring-pink`) | | Focus bàn phím | Vòng `focus-ring` 3px | ## Hành vi JS ```js TTMU.themePicker(root, { onChange: function (id) {} }) // → { value, set(id), destroy() } (gắn lần hai trả về null) ``` - Bấm nút → `TTMU.setTheme(id)`, cập nhật `aria-checked`, gọi `onChange(id)` (chỉ khi theme đổi; bấm lại theme đang chọn không gọi). - **Quy ước `onChange`:** chỉ thao tác của người dùng mới gọi `onChange`, và chỉ khi giá trị thật sự đổi; `set(id)` từ code thì im lặng. - Phím mũi tên chọn theme kế/trước (vòng tròn) và chuyển focus; chỉ nút đang chọn có `tabindex="0"`. - Nếu `root` trống, JS tự dựng 5 nút từ `TTMU.themes`. ## Token sử dụng `bg`, `pink`, `line`, `ink`, `outline`, `shadow-ring-pink`, `radius-14`, `radius-round`, `space-4/8/10`. ## Khả năng tiếp cận - `role="radiogroup"` + `role="radio"` với `aria-checked`; mũi tên di chuyển lựa chọn. - Tên theme (kể cả Tương phản cao) là chữ trong nút nên screen reader đọc được; ô màu chỉ trang trí. ## Nên / Không nên | Nên | Không nên | |---|---| | Hiện tên theme dưới ô màu | Chỉ hiện màu không có chữ | | Đặt `data-theme` lên ô màu | Dùng màu hex cố định cho ô màu | ## Nguồn `.thg`, `.thb`, `.thb i`, `.thb.on` — css/style.css; `themeDlg()` — js/game.js. - Game có 8 theme và vẽ ô màu bằng style nội tuyến; design system có 5 theme (4 theme của game cộng `hc`) và dùng `var(--bg)`/`var(--pink)` theo `data-theme`. - Vòng ngoài ô màu `rgba(0,0,0,.12)` đổi sang `color-mix` với `outline`. - `.thb.on` dùng `box-shadow:0 0 0 2px var(--pink)` = token `shadow-ring-pink`.