Một dấu ba chấm ở góc card có thể đủ dễ hiểu khi nhìn màn hình. Khi dùng screen reader, người dùng cần biết phần tử đó làm gì, có bấm được không và có liên quan đến card nào. Icon hiển thị đẹp chưa tự cung cấp đầy đủ thông tin đó.
Bài này xây một nút mở tùy chọn cho ứng dụng React Native và một bộ kiểm tra ngắn trên VoiceOver, TalkBack. Các API được đối chiếu tài liệu React Native ngày 23/10/2026. Ví dụ dùng component tích hợp, chưa build hoặc kiểm thử screen reader trên thiết bị trong lượt biên tập; hãy đối chiếu thêm tài liệu của version trong package.json dự án.
Tách tên, vai trò và trạng thái
accessibilityLabel đặt tên mà screen reader có thể đọc. accessibilityRole diễn đạt chức năng, chẳng hạn button. accessibilityState mô tả trạng thái hiện tại. Một label “ba chấm” chỉ nói hình vẽ, còn “Tùy chọn cho bài viết về Flutter” cho người dùng biết mục tiêu của hành động.
Thông thường không cần thêm từ “nút” vào label khi đã khai báo role button, vì công nghệ hỗ trợ có thể đọc vai trò riêng. Khi các card có nút giống nhau, đưa ngữ cảnh cần phân biệt vào tên, nhưng tránh lặp toàn bộ một đoạn nội dung dài mỗi lần người dùng chuyển focus.
accessibilityHint có thể giải thích kết quả thao tác khi tên chưa đủ rõ. Đừng đặt thông tin bắt buộc chỉ trong hint: cách hỗ trợ và tùy chọn đọc hint khác nhau theo nền tảng và cài đặt người dùng.
Một component nhỏ có hợp đồng rõ ràng
Nút dưới đây nhận label và callback từ màn hình sử dụng. Callback thực tế phải mở menu tương ứng; component chỉ phụ trách tương tác và biểu diễn. Giá trị 48 là kích thước tối thiểu được chọn cho ví dụ thiết kế, không phải chứng nhận toàn bộ màn hình đáp ứng một tiêu chuẩn accessibility.
import React from 'react';
import { Pressable, StyleSheet, Text } from 'react-native';
type Props = {
label: string;
disabled?: boolean;
onPress: () => void;
};
export function MoreButton({ label, disabled = false, onPress }: Props) {
return (
<Pressable
accessible
accessibilityRole="button"
accessibilityLabel={label}
accessibilityHint="Mở menu các thao tác cho mục này"
accessibilityState={{ disabled }}
disabled={disabled}
onPress={onPress}
hitSlop={8}
style={({ pressed }) => [
styles.button,
pressed && !disabled && styles.pressed,
disabled && styles.disabled,
]}
>
<Text accessible={false} style={styles.icon}>⋯</Text>
</Pressable>
);
}
const styles = StyleSheet.create({
button: {
minWidth: 48,
minHeight: 48,
alignItems: 'center',
justifyContent: 'center',
borderRadius: 12,
backgroundColor: '#e8edf5',
},
icon: { fontSize: 28, color: '#10203a' },
pressed: { backgroundColor: '#ced9eb' },
disabled: { opacity: 0.5 },
});
Trạng thái disabled có hai phần: ngăn thao tác qua prop tương tác và mô tả trạng thái cho công nghệ hỗ trợ. Chỉ giảm opacity không làm nút ngừng hoạt động; chỉ bỏ callback cũng không truyền đạt đầy đủ lý do người dùng không bấm được.
Nếu nút bị vô hiệu hóa vì một tác vụ đang chạy, giao diện còn cần phản hồi về tiến trình và kết quả ở nơi phù hợp. Không tự thêm trạng thái busy vào mọi nút disabled: hãy mô tả đúng trạng thái thực tế của sản phẩm.
Vùng chạm còn phụ thuộc bố cục xung quanh
hitSlop mở rộng vùng có thể bắt đầu thao tác chạm quanh phần tử. Tài liệu Pressable lưu ý vùng chạm không vượt ra ngoài giới hạn view cha và thứ tự lớp của view anh em vẫn có tác dụng khi vùng chồng nhau.
Vì thế, thêm hitSlop vào một icon nằm trong container rất nhỏ chưa chắc giải quyết được vấn đề. Kiểm tra kích thước container, khoảng cách tới nút kế bên và khả năng chạm đúng từng thao tác. Tránh dùng hai vùng chạm chồng lên nhau rồi suy luận chỉ từ kích thước icon đang hiển thị.
Trong card có thể bấm toàn bộ, cần thiết kế riêng hành vi giữa card và nút con. Lồng nhiều phần tử accessible có thể ảnh hưởng cách screen reader nhóm và di chuyển focus; kiểm tra trên cả hai nền tảng thay vì mặc định rằng cây JSX sẽ được đọc theo đúng hình dạng trực quan.
Kiểm tra bằng một luồng sử dụng thật
Bật VoiceOver trên iOS và TalkBack trên Android. Di chuyển focus qua màn hình: người dùng phải nhận ra tên có ngữ cảnh và vai trò của nút, không bị kẹt ở một ký tự trang trí riêng. Kích hoạt nút để mở đúng menu, đóng menu rồi kiểm tra focus trở về vị trí có thể tiếp tục công việc.
Chuyển nút sang disabled và xác nhận thao tác không thực hiện, đồng thời trạng thái được truyền đạt. Câu đọc cụ thể có thể khác nhau theo ngôn ngữ, phiên bản hệ điều hành và screen reader; hãy kiểm tra ý nghĩa chứ không yêu cầu hai nền tảng đọc cùng một chuỗi từng ký tự.
Sau đó tăng cỡ chữ, đổi ngôn ngữ sang label dài hơn và thử màn hình hẹp. Cỡ icon, vùng chạm và nhãn có thể cần điều chỉnh theo bố cục; giảm opacity cũng cần được xem lại trong ngữ cảnh độ tương phản của màn hình thật.
Tự động hóa phần có thể quan sát
Test component có thể xác nhận label, role, disabled và callback theo tương tác mô phỏng. Tuy nhiên, assertion trên props không chứng minh thứ tự focus native, cách menu thông báo hay thao tác bằng công nghệ hỗ trợ sẽ đúng. Giữ các bước kiểm tra thiết bị trong checklist release, nhất là khi thay component hoặc cấu trúc card.
Một nút icon dễ sử dụng bắt đầu bằng tên có nghĩa và trạng thái nhất quán. Việc kiểm tra toàn bộ hành động mở, dùng và đóng menu mới cho biết người dùng có hoàn thành được công việc hay không.




