Bỏ qua tới nội dung
Component / 038 / NEXOFRAME

FormError

Mẫu chuẩn

Một băng lỗi ở mức biểu mẫu — không ở mức field — mang role “alert” nên trình đọc màn hình thông báo nó ngay khoảnh khắc nó xuất hiện. Hình học bám ô nhập bên dưới, không bám thẻ.

Composite tầng 2Không dựng từ primitive nàorole="alert" cố định1 prop

Playground

Đổi brand, theme và nội dung để xem cùng một FormError thích ứng.

LIVE PREVIEW

role hiện tại: alert — ngắt để đọc ngay khi node được thêm vào DOM.

import { FormError } from "@nexobox/ui";

{submitFailed ? <FormError>"Sai tài khoản hoặc mật khẩu."</FormError> : null}

Bài toán

Khi một lần nộp biểu mẫu thất bại vì lý do không thuộc một field nào — sai thông tin đăng nhập, phiên hết hạn, máy chủ từ chối — thì không có ô nào để gắn lỗi vào. Lỗi ấy phải xuất hiện ở đầu biểu mẫu, phải được thông báo ngay chứ không đợi người dùng tự cuộn lên, và nó phải trông thuộc về biểu mẫu chứ không nổi lên như một thẻ riêng. Một primitive không giải được vì đây là ba quyết định ghép: vai trò aria (alert, không status), hình học bám field (bán kính ô, viền subtle), và một icon cảnh báo cố định. Alert tồn tại nhưng mang hình học của thẻ chứ không của field — xem mục kế tiếp.

Khi nào sử dụng

Nên dùng

Lỗi ở mức biểu mẫu, đặt ngay trước field đầu tiên hoặc ngay trên nút nộp. Lỗi phải được thông báo ngay khi xuất hiện: đăng nhập sai, mã hết hạn, hành động bị từ chối. Một dòng, một câu — composite này không có tiêu đề riêng và không có nút đóng.

Khi nào không dùng

Tránh dùng

Không dùng choDùng thay
Lỗi thuộc một fieldField error hoặc PasswordField error
Thông báo thành côngFormNotice — cùng hình học, role="status", icon và màu khác
Thông báo có tiêu đề, danh sách, hoặc một nút hành động bên trongAlert. FormError chỉ nhận một dòng
Thông báo tự tắt, nổi ở góc màn hìnhToaster
Cảnh báo ambient không do người dùng vừa gây ra — "gói của bạn sắp hết hạn"Alert với kind="warning". FormError luôn chen ngang trình đọc màn hình; đó là tiếng ồn cho một điều kiện ambient

Vì sao FormError chưa thu lại thành preset của Alert. Vai trò aria khớp nhau — Alert kind="danger" cũng mặc định role="alert". Viền, bán kính và đệm khác nhau vì một băng nằm trong biểu mẫu nên đồng hình với ô nhập, không với thẻ — vai trò thật. Nhưng FormError còn tự giữ một margin-bottom, và đó không phải vai trò, đó là một khiếm khuyết: một component không nên sở hữu lề ngoài của chính nó. Cách đóng đúng là cho Alert một knob tone="subtle" rồi FormError trở thành một preset mỏng và bỏ lề ngoài — việc đó chạm một primitive đã có consumer nên là quyết định riêng, theo dõi bằng dòng ledger W10.20.

Dựng từ

Primitive tầng 1Vai trong composite
—Không primitive nào.
Icon (wrapper, không phải dòng catalogue)Vẽ AlertCircleIcon, cỡ small, màu status.danger.icon.

Đây là một trong hai composite trong tầng không dựng từ một primitive tầng 1 nào, và nó vẫn thuộc tầng 2 theo ADR-UI-005 clause 3: nó có thứ nó thêm mà không primitive nào có (hình học bám field, vai trò aria cố định), và nó không gọi tên khái niệm sản phẩm nào.

FormError thêm gì
role="alert" cố định — không nhận từ caller
Icon cảnh báo cố định, không chọn được
Hình học bám field: bán kính ô, viền bậc subtle, đệm băng
Icon căn theo dòng chữ đầu bằng một lề trên nhỏ

Anatomy

#PhầnGhi chú
1Icon (AlertCircle)Cỡ small, màu status.danger.icon, lề trên nhỏ để thẳng dòng chữ đầu.
2span (children)Câu chữ do host cấp.

Hai phần: icon và chữ. Không tiêu đề, không nút đóng, không vùng hành động.

States

HIỆN

Được render. Trình đọc màn hình thông báo ngay nhờ role="alert".

Không hiện: composite không có chế độ ẩn — caller render nó hoặc không. Hover, focus, disabled: không có. Đây không phải control; không có phần nào nhận tiêu điểm. Không có trạng thái "đóng" — băng biến mất khi nội dung sinh ra nó thay đổi, chứ không vì người dùng bấm vào một dấu nhân.

Bàn phím & trợ năng

Không phím nào -- composite không có phần tử tương tác, không nằm trong tab order, không nhận tiêu điểm.
Nghĩa vụ trợ năng nằm hoàn toàn ở role="alert", không ở bàn phím.

Seam — host sở hữu gì

FormError không biết vì sao lần nộp thất bại, không dịch mã lỗi thành câu chữ, không thử lại, và không quyết định khi nào nó nên xuất hiện. Theo ADR-UI-003 clause 2 nó không fetch, không đọc router, không giữ session, không import gì từ next.

Host sở hữuCấp qua
Câu chữ của lỗi, bằng ngôn ngữ người đọcchildren
Khi nào băng tồn tạiRender có điều kiện. Không có prop visible
Ánh xạ từ mã lỗi kỹ thuật sang câu người đọc hiểuHost. Composite không mang một bảng chuỗi nào
Lề ngoài của khối, về lâu dàiHiện composite tự giữ — khiếm khuyết đã ghi ở mục Không dùng cho, dòng ledger W10.20

Composite không giữ trạng thái nào. Không useState, không useId.

API & triển khai

PropMặc địnhQuy ước
children—Bắt buộc. Một dòng, một câu. Danh sách prop đóng ở đúng một dòng: không kind, không role, không icon, không className.

Design tokens

FormError đọc --nf-component-field-radius, --nf-semantic-status-danger-border-subtle, -background, -foreground, -icon, cộng năm alias component.auth.banner* và component.auth.errorMarginBottom cho đệm, khoảng icon–chữ và lề dưới. Lỗ hổng đặt tên, ghi ra thay vì che: năm alias đó gọi tên "auth" trong khi composite này đã được ADR-UI-005 clause 5 xác định là chung — nhóm đúng là component.formBanner.*, theo dõi bằng dòng ledger W10.19. Cỡ chữ 0.8125rem là số trần trong file, không phải token.

Do / Don't

Nên dùng

Render composite sau khi lần nộp thất bại. Gắn lỗi của một field vào chính field đó. Một câu. Dịch mã lỗi ở host.

Tránh dùng

Render sẵn rồi bật/tắt bằng CSS — role="alert" không thông báo một phần tử đã có sẵn từ lúc tải trang. Dồn mọi lỗi lên một băng ở đầu biểu mẫu. Một danh sách lỗi, hay một nút "thử lại" bên trong. Truyền mã lỗi kỹ thuật thẳng vào children. Dùng FormError cho cảnh báo ambient.