Nền tảng
Kích thước
Đã đặc tảMười token kích thước nền tảng. Bốn chiều cao control — 32, 36, 40, 44 — nhưng chỉ ba bậc lộ ra cho tác giả, và hai chiều cao hàng 40, 48. touchTarget là 44 và nó là sàn của vùng chạm, không phải một chiều cao: sau DS-017 clause 6 nó và chiều cao control không còn là cùng một loại đại lượng. Hai trục độc lập: size của Button và density của một vùng.
Token
Mười token
| Token | Giá trị |
|---|---|
--nf-foundation-size-control-xs | Unknown |
--nf-foundation-size-control-sm | Unknown |
--nf-foundation-size-control-md | Unknown |
--nf-foundation-size-control-lg | Unknown |
--nf-foundation-size-compact-row | Unknown |
--nf-foundation-size-comfortable-row | Unknown |
--nf-foundation-size-touch-target | Unknown |
--nf-foundation-size-icon | Unknown |
--nf-foundation-size-icon-small | Unknown |
--nf-foundation-size-focus-offset | Unknown |
controlXs 32px phục vụ đúng một vai — hàng trong danh sách overlay ở compact — và không có API nào lộ nó cho tác giả. touchTarget và controlLg cùng là 44px và đó không còn là trùng lặp: sau DS-017 clause 6 chúng thậm chí không còn so sánh được với nhau. controlLg là chiều cao của một hộp; touchTarget là cạnh nhỏ nhất của vùng chạm, thứ được mở rộng bằng một lớp phủ chứ không bằng cách phóng to hộp.
Render
Ba chiều cao control cạnh nhau, ở cả hai density
Ba size thật của Button, đặt trong hai ThemeScope mật độ khác nhau. sm và lg là hai mỏ neo cố định; chỉ md trượt — ở compact, md hội tụ với sm về 36px, còn lg vẫn tách 44px. Chiều cao thị giác không đổi theo loại con trỏ ở cả ba size, kể cả sm: vùng chạm mở ra 44px bằng một lớp phủ vô hình, không bằng cách phóng to hộp.
nexoframe · light · comfortable
nexoframe · light · compact
Hai trục
size của Button và density của vùng
| size của Button | data-nexo-density | |
|---|---|---|
| Phạm vi | một control | một vùng và mọi thứ trong nó |
| Ai đặt | tác giả của control đó | tổ tiên: theme root, hoặc thân bảng |
| Nói gì | "hành động này quan trọng cỡ này" | "vùng này ưu tiên thấy nhiều dòng" |
| Có bị con trỏ thô ghi đè | không đổi chiều cao; vùng chạm mở ra 44px | không đổi, trừ ba vai ở bảng dưới |
Hai trục không thay nhau được. Một nút lg trong một vùng compact vẫn là nút lớn nhất của vùng đó — sm và lg là hai mỏ neo cố định, chỉ md trượt. Nếu density san bằng cả ba size thì tác giả mất cách nói "hành động này quan trọng hơn" trong đúng những vùng dày đặc nơi điều đó cần nhất.
Token
Bảng remap theo density
| Vai trò | comfortable | compact | Token nền tảng |
|---|---|---|---|
| Button sm | 36px | 36px | control-sm ở cả hai |
| Button md | 40px | 36px | control-md / control-sm |
| Button lg | 44px | 44px | control-lg ở cả hai |
| Ô nhập | 40px | 36px | control-md / control-sm |
| Tab | 40px | 36px | control-md / control-sm |
| Hàng menu | 36px | 32px | control-sm / control-xs |
| Hàng bảng | 48px | 40px | comfortable-row / compact-row |
| Accordion trigger | 48px | 44px | comfortable-row / control-lg |
| Kiểu chữ control | typography-ui-* | typography-caption-* | — |
sm và lg là hai mỏ neo cố định; chỉ md trượt. Ở compact, sm và md hội tụ về 36px — chủ ý: trong một vùng đã dày đặc, "phụ" và "mặc định" nên cùng chiều cao, thứ phân biệt chúng là kiểu chữ (caption so với ui) và đệm (12px so với 16px), không phải kích thước.
Con trỏ thô
Ba ngoại lệ, và một công thức
Lớp phủ vùng chạm chỉ hợp lệ khi control có khoảng trống thật ≥ (44 − chiều cao) / 2 ở mỗi phía. Một Button 36px đứng cạnh nhau với khe space-2 (8px) cần 4px mỗi phía — vừa đủ, và hai vùng chạm chạm nhau mà không chồng. Đó cũng là lý do thang dừng ở bậc 32 và không đi thấp hơn: 36 + 4 + 4 = 44 ăn khớp với khe mặc định, còn một bậc 28px sẽ cần khe ≥ 16px và đẻ ra một luật khoảng cách riêng.
Ba vai xếp chồng khoảng cách 0 nên không có chỗ cho lớp phủ, và chúng phải cao thật ở con trỏ thô:
| Vai | coarse |
|---|---|
| Hàng menu | 44px |
| Hàng bảng | 48px |
| Accordion trigger | 48px |
Hệ quả nhìn thấy được: trên tablet, menu và bảng dài ra trong khi nút và ô nhập thì không. Đó là kết quả đúng — bấm nhầm một mục trong menu là lỗi tệ hơn hẳn một menu hơi thô.
Chi tiết
focusOffset — token nhỏ nhất và hay bị bỏ qua nhất
--nf-foundation-size-focus-offset là 2px. Ring tiêu điểm cách phần tử 2px thay vì dán sát, để nó đọc ra là một ring, không phải một viền dày hơn.
Quy tắc
Do / Don't
| Do | Don't | Vì sao |
|---|---|---|
| Bind --nf-component-button-height từ primitive | Bind --nf-foundation-size-control-* từ primitive hay từ màn hình | Alias component là chỗ density remap; bind nền tảng là thoát khỏi density. infra/check-control-heights.mjs chặn |
| Dùng md cho gần như mọi nút | Dùng lg cho mọi hành động chính | Nếu mọi thứ là lg thì không gì là chính |
| Dùng sm trong hàng bảng | Dùng sm để nhồi thêm nút vào một thanh chật | Thanh chật là vấn đề layout; sm không sửa được nó và làm đích nhỏ hơn |
| Để lớp phủ lo sàn chạm | Ghi đè @media (pointer: coarse) để lấy lại layout dày | Phần Never của A11 không đổi sau DS-017 |
| Bind --nf-foundation-size-touch-target khi ý là một sàn | Bind nó khi ý là một chiều cao | Sau DS-017 clause 6 đây là hai loại đại lượng khác nhau. pagination.tsx bind nó đúng |
| Đặt density lên một vùng | Truyền một prop density xuống từng component | A12: density thuộc về vùng |
Chưa quyết
Open questions
| Question | Owner | Resolves when |
|---|---|---|
| Có size thứ tư cho Button không? | nexoboxvn@gmail.com | Một bề mặt sản phẩm cần nó. controlXs 32px tồn tại nhưng không trả lời câu này — nó không có API |
| touchTarget và chiều cao mặc định có nên tách giá trị không? | — | Đóng 2026-09-25 theo DS-017 clause 6. Chúng không còn cùng loại đại lượng: một cái là cạnh của vùng chạm, cái kia là chiều cao của hộp |
| Hàng bảng có cần bậc thứ ba cho hàng có hai dòng chữ không? | nexoboxvn@gmail.com | Một bảng thật có hàng hai dòng |
| Sau DS-017, bậc cao nhất của thang bằng đúng sàn chạm. Một bề mặt cần nút cao hơn 44px thì lấy ở đâu? | nexoboxvn@gmail.com | Một bề mặt nêu nhu cầu. Đây là khả năng mà DS-017 đóng lại khi bỏ bậc 52 |