From 5a6a165c1144ba072a3195ddae99f47c14d4b735 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2026 01:51:28 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20Add=20accessibility?= =?UTF-8?q?=20labels=20to=20password=20visibility=20toggles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: TargetMisser <52361977+TargetMisser@users.noreply.github.com> --- .jules/palette.md | 3 +++ src/i18n/translations.ts | 2 ++ src/screens/PasswordScreen.tsx | 8 ++++---- 3 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 .jules/palette.md diff --git a/.jules/palette.md b/.jules/palette.md new file mode 100644 index 0000000..ea2569f --- /dev/null +++ b/.jules/palette.md @@ -0,0 +1,3 @@ +## 2024-05-24 - Accessible Icon Buttons +**Learning:** Screen readers cannot infer the purpose of icon-only buttons without text content, making actions like "Delete note" inaccessible to visually impaired users. In this app, many utility buttons (like the trash icon in Notepad) relied solely on visual metaphors. +**Action:** Always add `accessible={true}`, `accessibilityRole="button"`, and a descriptive `accessibilityLabel` to `` components that only contain an icon, using existing translation keys when possible. diff --git a/src/i18n/translations.ts b/src/i18n/translations.ts index 8ccd1e2..a79e7bd 100644 --- a/src/i18n/translations.ts +++ b/src/i18n/translations.ts @@ -121,6 +121,7 @@ const it = { contactNoResults: 'Nessun risultato', // Password passwordTitle: 'Password', passwordAdd: 'Aggiungi', + passwordShow: 'Mostra password', passwordHide: 'Nascondi password', passwordModalNew: 'Nuova voce', passwordModalEdit: 'Modifica voce', passwordNameLabel: 'Nome *', passwordNamePh: 'es. Portale HR EasyJet', passwordUsernameLabel: 'Username / Email', passwordUsernamePh: 'es. mario.rossi@easyjet.com', @@ -279,6 +280,7 @@ const en: typeof it = { contactNoResults: 'No results', // Password passwordTitle: 'Password', passwordAdd: 'Add', + passwordShow: 'Show password', passwordHide: 'Hide password', passwordModalNew: 'New entry', passwordModalEdit: 'Edit entry', passwordNameLabel: 'Name *', passwordNamePh: 'e.g. EasyJet HR Portal', passwordUsernameLabel: 'Username / Email', passwordUsernamePh: 'e.g. mario.rossi@easyjet.com', diff --git a/src/screens/PasswordScreen.tsx b/src/screens/PasswordScreen.tsx index c5338f1..83c785d 100644 --- a/src/screens/PasswordScreen.tsx +++ b/src/screens/PasswordScreen.tsx @@ -51,7 +51,6 @@ const EMPTY_MODAL: ModalState = { // ─── PIN Overlay ───────────────────────────────────────────────────────────── function PinOverlay({ onUnlock, onCancel, title }: { onUnlock: (pin: string) => void; onCancel?: () => void; title: string }) { const { colors } = useAppTheme(); - const { t } = useLanguage(); const s = useMemo(() => makePinStyles(colors), [colors]); const [digits, setDigits] = useState(''); @@ -103,6 +102,7 @@ function PinOverlay({ onUnlock, onCancel, title }: { onUnlock: (pin: string) => // ─── Password Row ───────────────────────────────────────────────────────────── function PasswordRowComponent({ item, onEdit, onDelete }: { item: PasswordEntry; onEdit: () => void; onDelete: () => void }) { const { colors } = useAppTheme(); + const { t } = useLanguage(); const s = useMemo(() => makeRowStyles(colors), [colors]); const [revealed, setRevealed] = useState(false); @@ -113,7 +113,7 @@ function PasswordRowComponent({ item, onEdit, onDelete }: { item: PasswordEntry; {item.username ? {item.username} : null} {revealed ? item.password : '••••••••'} - setRevealed(r => !r)} style={s.eyeBtn}> + setRevealed(r => !r)} style={s.eyeBtn} accessible accessibilityRole="button" accessibilityLabel={revealed ? t('passwordHide') : t('passwordShow')}> @@ -136,8 +136,8 @@ const PasswordRow = React.memo(PasswordRowComponent); // ─── Main Screen ────────────────────────────────────────────────────────────── export default function PasswordScreen() { - const { colors } = useAppTheme(); const { t } = useLanguage(); + const { colors } = useAppTheme(); const s = useMemo(() => makeStyles(colors), [colors]); const [entries, setEntries] = useState([]); @@ -330,7 +330,7 @@ export default function PasswordScreen() { secureTextEntry={!showPw} autoCapitalize="none" /> - setShowPw(p => !p)} style={s.eyeModal}> + setShowPw(p => !p)} style={s.eyeModal} accessible accessibilityRole="button" accessibilityLabel={showPw ? t('passwordHide') : t('passwordShow')}>