Wordmark
Mẫu chuẩnChữ ký thương hiệu ở đầu một bề mặt. Component không sở hữu đường dẫn tài sản nào -- src và alt do caller cấp. Sự hiện diện của onClick đổi phần tử gốc từ span sang button, và đó là toàn bộ điểm quyết định tầng của file này.
Playground
Bật onClick để xem phần tử gốc đổi từ span sang button thật, cùng vành tiêu điểm khi focus bằng bàn phím.
Phần tử gốc hiện tại: <span>
import { Wordmark } from "@nexobox/ui";
<Wordmark
src="/api/brand-assets/brand/nexocrew/nexocrew-primary.svg"
alt="NexoCrew"
/>Bài toán
Logo ở đầu một trang phải làm ba việc cùng lúc và ba việc đó kéo về ba hướng khác nhau. Nó phải hiển thị một tài sản mà component không được biết đường dẫn — nếu component tự nhúng đường dẫn thì nó chỉ dùng được cho một sản phẩm, và corpus này có năm. Nó phải có chiều cao ổn định giữa các bề mặt. Và trên một số bề mặt nó bấm được để về trang chủ, trên số khác thì không — nhưng một thẻ <img> bấm được mà không phải <button> là một phần tử người dùng bàn phím không tới được. Phần còn lại — chọn phần tử bọc theo việc có hành động hay không — là việc của một tầng trên <img>.
Khi nào sử dụng
Nên dùng
Logo chữ ở đầu cột biểu mẫu, đầu panel kể chuyện, đầu sidebar ứng dụng. Khi caller đã có src và alt từ @nexobox/ui/assets/brand/.... Cả hai ca: logo tĩnh, và logo bấm được để điều hướng.
Khi nào không dùng
Tránh dùng
| Không dùng cho | Dùng thay |
|---|---|
| Logo kênh bên thứ ba — Facebook, Zalo | ChannelMark — tài sản kênh sống ở một thư mục khác, dưới một luật khác |
| Ảnh đại diện người dùng | Avatar |
| Thẻ trưng bày một thương hiệu trong lưới thương hiệu của site tài liệu | BrandMark trong chrome của chính site này — tên gần giống, API khác |
| Một nút có chữ | Button. Nếu thứ cần là một hành động thì nút mới là câu trả lời, logo chỉ tình cờ bấm được |
| Biểu tượng vuông không có chữ | Unknown — corpus chưa có dòng catalogue cho nó |
Dựng từ
| Primitive tầng 1 | Vai trong composite |
|---|---|
| — | Không primitive nào. Nó render một <img> gốc. |
| Wordmark thêm gì |
|---|
Nhánh phần tử bọc: <button type="button"> khi có onClick, <span> khi không |
aria-label của nút lấy từ cùng chuỗi alt |
Vành tiêu điểm bằng token component.focus.*, chỉ ở nhánh nút |
Chiều cao cố định với bề rộng tự do và object-contain, cộng object-left để neo mép trái |
Anatomy
| # | Phần | Ghi chú |
|---|---|---|
| 1 | Phần tử bọc | span (tĩnh) hoặc button type="button" (bấm được) — hộp ảnh giống hệt nhau giữa hai nhánh. |
| 2 | img | h-10 w-auto object-contain object-left. Cùng hộp ảnh ở cả hai nhánh nên logo không nhảy một pixel nào. |
Variants
Wordmark không có prop variant. Nó có hai hình dạng render do sự hiện diện của onClick quyết định:
| Hình dạng | Điều kiện | Phần tử gốc | Aria |
|---|---|---|---|
| Tĩnh | không onClick | <span> | Chỉ alt của <img> |
| Bấm được | có onClick | <button type="button"> | alt của <img> cộng aria-label cùng chuỗi trên nút |
Hệ quả cần biết: ở nhánh bấm được, chuỗi ấy có mặt hai lần trong cây trợ năng — trình đọc màn hình đọc nhãn của nút và bỏ qua nội dung bên trong, nên trong thực tế người dùng nghe nó một lần. Đúng hôm nay, cần kiểm lại nếu alt từng để rỗng.
States
Không con trỏ tay, không vành tiêu điểm, không nằm trong tab order.
Con trỏ tay. Tab tới nó để xem vành tiêu điểm khi :focus-visible.
Ảnh không tải được: trình duyệt hiện chữ alt — composite không có fallback riêng. Nhánh bấm được không có trạng thái hover riêng và không áp press-scale. Đó không còn là một khiếm khuyết: DS-018 clause 2 đảo luật cũ của DS-014 clause 16 — "press-scale lên mọi thứ nhấn được" không còn là một luật, token vẫn ở trong corpus nhưng chỉ áp khi chủ sở hữu yêu cầu cho một bề mặt cụ thể — nên không còn luật nào để file này "chưa tuân". Dòng ledger W9.7, từng theo dõi việc "press-scale lên mọi thứ nhấn được" còn pending, đóng lại theo chiều ngược: vì luật biến mất, không vì công việc hoàn thành.
Bàn phím & trợ năng
Seam — host sở hữu gì
Wordmark không biết logo nào thuộc sản phẩm nào, không điều hướng, và không đọc router. Theo ADR-UI-003 clause 2 nó không fetch, không giữ session, không import gì từ next — và onClick là một callback trần chính vì thế: một trang muốn logo dẫn về trang chủ thì truyền một onClick gọi router của nó, hoặc bọc composite trong Link của mình.
| Host sở hữu | Cấp qua |
|---|---|
| Đường dẫn tài sản | src. Tài sản ở packages/ui/assets/, component không nhúng đường dẫn |
| Chữ thay thế, và nghĩa của nó | alt — dùng cho cả <img> và aria-label của nút |
| Việc logo có bấm được hay không | Có truyền onClick hay không |
| Điều hướng, router, prefetch | onClick ở host |
| Lề và vị trí trong layout | className |
API & triển khai
| Prop | Mặc định | Quy ước |
|---|---|---|
| src | — | Bắt buộc. Một đường dẫn tài sản do caller cấp. |
| alt | — | Bắt buộc. Cũng trở thành aria-label của nút ở nhánh bấm được. |
| onClick | undefined | Sự hiện diện của nó đổi phần tử gốc — hành vi đáng nhớ nhất của API này. |
| className | undefined | Đi vào phần tử bọc (span hoặc button), không vào img. |
className ở đây đi vào phần tử bọc, còn className của Field đi vào Input bên trong. Hai composite trong cùng một tầng xử lý cùng một prop theo hai hướng khác nhau — một luật chung cho className trong tầng 2 là thứ corpus còn thiếu, theo dõi ở dòng ledger W10.22.
Design tokens
Wordmark là composite duy nhất trong bảy cái không tham chiếu một token màu hay khoảng cách nào — nó không có nền, không có viền, không có đệm. Ba token nó đọc đều thuộc họ tiêu điểm: --nf-component-focus-width, --nf-component-focus-color, --nf-component-focus-offset. Lỗ hổng đặt tên, ghi ra thay vì che: chiều cao logo là h-10 — 2.5rem trần từ thang Tailwind, không phải token. Corpus không có alias cho "chiều cao logo chữ"; một component.wordmark.height là bản sửa đúng, theo dõi bằng dòng ledger W10.19.
Do / Don't
Nên dùng
Truyền src từ @nexobox/ui/assets/brand/.... Bỏ onClick khi logo chỉ để xem. Truyền onClick gọi router của host. Viết alt là tên sản phẩm người đọc nhận ra. Dùng className cho lề và vị trí.
Tránh dùng
Nhúng một đường dẫn tài sản vào component. Truyền một onClick rỗng "để sau này dùng" — nó biến logo thành một nút trong tab order mà bấm vào không xảy ra gì. Trông đợi composite tự điều hướng. Để alt rỗng. Dùng className mong đổi chiều cao ảnh. Dùng Wordmark cho logo kênh.