-
Notifications
You must be signed in to change notification settings - Fork 0
🎨 Palette: Add accessibility labels to icon-only buttons in PasswordScreen #45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| ## 2025-03-09 - Accessible Icon Buttons in React Native | ||
| **Learning:** In this React Native application, several icon-only components (like `<TouchableOpacity>` containing only a `<MaterialIcons>`) lacked inherent meaning for screen readers. Using standard ARIA attributes directly isn't perfectly 1-to-1 with React Native. | ||
| **Action:** Next time, when adding accessibility to interactive elements in React Native, ensure `<TouchableOpacity>` (or similar) is given the props `accessible={true}`, `accessibilityRole="button"`, and a descriptive `accessibilityLabel` (ideally translated) to provide context for screen readers. |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -80,7 +80,15 @@ function PinOverlay({ onUnlock, onCancel, title }: { onUnlock: (pin: string) => | |||||
| {keys.map((k, i) => ( | ||||||
| k === '' ? <View key={i} style={s.keyEmpty} /> : | ||||||
| k === '⌫' ? ( | ||||||
| <TouchableOpacity key={i} style={s.key} onPress={del} activeOpacity={0.7}> | ||||||
| <TouchableOpacity | ||||||
| key={i} | ||||||
| style={s.key} | ||||||
| onPress={del} | ||||||
| activeOpacity={0.7} | ||||||
| accessible={true} | ||||||
| accessibilityRole="button" | ||||||
| accessibilityLabel="Cancella ultima cifra" | ||||||
| > | ||||||
| <MaterialIcons name="backspace" size={20} color={colors.text} /> | ||||||
| </TouchableOpacity> | ||||||
| ) : ( | ||||||
|
|
@@ -113,17 +121,35 @@ function PasswordRow({ item, onEdit, onDelete }: { item: PasswordEntry; onEdit: | |||||
| {item.username ? <Text style={s.username}>{item.username}</Text> : null} | ||||||
| <View style={s.pwRow}> | ||||||
| <Text style={s.pw}>{revealed ? item.password : '••••••••'}</Text> | ||||||
| <TouchableOpacity onPress={() => setRevealed(r => !r)} style={s.eyeBtn}> | ||||||
| <TouchableOpacity | ||||||
| onPress={() => setRevealed(r => !r)} | ||||||
| style={s.eyeBtn} | ||||||
| accessible={true} | ||||||
| accessibilityRole="button" | ||||||
| accessibilityLabel={revealed ? "Nascondi password" : "Mostra password"} | ||||||
| > | ||||||
|
Comment on lines
+124
to
+130
|
||||||
| <MaterialIcons name={revealed ? 'visibility-off' : 'visibility'} size={16} color={colors.textSub} /> | ||||||
| </TouchableOpacity> | ||||||
| </View> | ||||||
| {item.notes ? <Text style={s.notes}>{item.notes}</Text> : null} | ||||||
| </View> | ||||||
| <View style={s.actions}> | ||||||
| <TouchableOpacity style={s.editBtn} onPress={onEdit}> | ||||||
| <TouchableOpacity | ||||||
| style={s.editBtn} | ||||||
| onPress={onEdit} | ||||||
| accessible={true} | ||||||
| accessibilityRole="button" | ||||||
| accessibilityLabel="Modifica password" | ||||||
| > | ||||||
| <MaterialIcons name="edit" size={17} color={colors.primary} /> | ||||||
| </TouchableOpacity> | ||||||
| <TouchableOpacity style={s.delBtn} onPress={onDelete}> | ||||||
| <TouchableOpacity | ||||||
| style={s.delBtn} | ||||||
| onPress={onDelete} | ||||||
| accessible={true} | ||||||
| accessibilityRole="button" | ||||||
| accessibilityLabel="Elimina password" | ||||||
| > | ||||||
|
Comment on lines
+137
to
+152
|
||||||
| <MaterialIcons name="delete-outline" size={17} color="#EF4444" /> | ||||||
| </TouchableOpacity> | ||||||
| </View> | ||||||
|
|
@@ -327,7 +353,13 @@ export default function PasswordScreen() { | |||||
| secureTextEntry={!showPw} | ||||||
| autoCapitalize="none" | ||||||
| /> | ||||||
| <TouchableOpacity onPress={() => setShowPw(p => !p)} style={s.eyeModal}> | ||||||
| <TouchableOpacity | ||||||
| onPress={() => setShowPw(p => !p)} | ||||||
| style={s.eyeModal} | ||||||
| accessible={true} | ||||||
| accessibilityRole="button" | ||||||
| accessibilityLabel={showPw ? "Nascondi password" : "Mostra password"} | ||||||
|
||||||
| accessibilityLabel={showPw ? "Nascondi password" : "Mostra password"} | |
| accessibilityLabel={t(showPw ? 'hidePassword' : 'showPassword')} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
accessibilityLabelis hardcoded in Italian, but the app supports multiple languages viauseLanguage()/translations.ts. Screen-reader labels should be localized (e.g., add a translation key for the PIN backspace/delete action and uset(...)here) so English users don't get Italian announcements.