From 82437523c7720f11e8ad50f6bb9ed26e65e0c200 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 28 Jan 2026 14:10:22 +0700 Subject: [PATCH 01/10] fix: The Language dropdown has no role, name and state announced --- src/components/LocalePicker.tsx | 1 + src/components/Picker/BasePicker.tsx | 6 +++++- src/components/Picker/types.ts | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/LocalePicker.tsx b/src/components/LocalePicker.tsx index 2262b821e3389..2e83b68af7151 100644 --- a/src/components/LocalePicker.tsx +++ b/src/components/LocalePicker.tsx @@ -46,6 +46,7 @@ function LocalePicker({size = 'normal'}: LocalePickerProps) { value={preferredLocale} containerStyles={size === 'small' ? styles.pickerContainerSmall : {}} backgroundColor={theme.signInPage} + accessibilityLabel={translate('languagePage.language')} /> ); } diff --git a/src/components/Picker/BasePicker.tsx b/src/components/Picker/BasePicker.tsx index 462646b49123b..32bc843df9413 100644 --- a/src/components/Picker/BasePicker.tsx +++ b/src/components/Picker/BasePicker.tsx @@ -38,6 +38,7 @@ function BasePicker({ onBlur = () => {}, additionalPickerEvents = () => {}, ref, + accessibilityLabel, }: BasePickerProps) { const icons = useMemoizedLazyExpensifyIcons(['DownArrow']); const theme = useTheme(); @@ -204,15 +205,18 @@ function BasePicker({ onClose={disableHighlight} textInputProps={{ allowFontScaling: false, + accessibilityRole: CONST.ROLE.COMBOBOX, + accessibilityLabel, }} pickerProps={{ ref: picker, - tabIndex: -1, onFocus: enableHighlight, onBlur: () => { disableHighlight(); onBlur(); }, + accessibilityLabel, + accessibilityRole: CONST.ROLE.COMBOBOX, ...additionalPickerEvents(enableHighlight, (inputValue, index) => { onValueChange(inputValue, index); disableHighlight(); diff --git a/src/components/Picker/types.ts b/src/components/Picker/types.ts index 5741217d08b95..6801185f93c1a 100644 --- a/src/components/Picker/types.ts +++ b/src/components/Picker/types.ts @@ -101,6 +101,9 @@ type BasePickerProps = { /** Reference to the outer element */ ref?: ForwardedRef; + + /** Accessibility label for the picker */ + accessibilityLabel?: string; }; export type {BasePickerHandle, BasePickerProps, PickerSize, AdditionalPickerEvents, OnMouseDown, OnChange}; From 852ec5bcfb7d47ec29b2e82c74457376e62340b5 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 5 Feb 2026 09:42:01 +0700 Subject: [PATCH 02/10] fix lint --- src/components/Picker/BasePicker.tsx | 1 - src/components/Picker/types.ts | 3 --- 2 files changed, 4 deletions(-) diff --git a/src/components/Picker/BasePicker.tsx b/src/components/Picker/BasePicker.tsx index fe36a85ec9e31..8a01e3d7060c8 100644 --- a/src/components/Picker/BasePicker.tsx +++ b/src/components/Picker/BasePicker.tsx @@ -40,7 +40,6 @@ function BasePicker({ onBlur = () => {}, additionalPickerEvents = () => {}, ref, - accessibilityLabel, }: BasePickerProps) { const icons = useMemoizedLazyExpensifyIcons(['DownArrow']); const theme = useTheme(); diff --git a/src/components/Picker/types.ts b/src/components/Picker/types.ts index de3388d7df6cb..1ca1de570f7f1 100644 --- a/src/components/Picker/types.ts +++ b/src/components/Picker/types.ts @@ -104,9 +104,6 @@ type BasePickerProps = { /** Reference to the outer element */ ref?: ForwardedRef; - - /** Accessibility label for the picker */ - accessibilityLabel?: string; }; export type {BasePickerHandle, BasePickerProps, PickerSize, AdditionalPickerEvents, OnMouseDown, OnChange}; From 5097a9d9dca0885614122649995507e4b0efa32b Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 5 Feb 2026 09:56:37 +0700 Subject: [PATCH 03/10] fix lint --- src/components/LocalePicker.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/LocalePicker.tsx b/src/components/LocalePicker.tsx index f64c3643f072c..350066600dd69 100644 --- a/src/components/LocalePicker.tsx +++ b/src/components/LocalePicker.tsx @@ -47,7 +47,6 @@ function LocalePicker({size = 'normal'}: LocalePickerProps) { value={preferredLocale} containerStyles={size === 'small' ? styles.pickerContainerSmall : {}} backgroundColor={theme.signInPage} - accessibilityLabel={translate('languagePage.language')} /> ); } From e5d846b533a04d310e0ced6c61b4acd421bc7c47 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Sun, 22 Feb 2026 20:17:09 +0700 Subject: [PATCH 04/10] custom accessibility label --- src/components/Picker/BasePicker.tsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/components/Picker/BasePicker.tsx b/src/components/Picker/BasePicker.tsx index 8a01e3d7060c8..13aafbdfad5fb 100644 --- a/src/components/Picker/BasePicker.tsx +++ b/src/components/Picker/BasePicker.tsx @@ -164,6 +164,19 @@ function BasePicker({ // Disable Tab focus on mobile to prevent soft keyboard navigation jumping to picker (#25759) const pickerTabIndex = isMobile() ? -1 : 0; + const selectedItem = items.find((item) => item.value === value); + const selectedLabel = selectedItem?.label ?? ''; + const enhancedAccessibilityLabel = useMemo(() => { + const defaultAccessibilityLabel = accessibilityLabel ?? label; + if (!defaultAccessibilityLabel) { + return selectedLabel || ''; + } + if (selectedLabel) { + return `${defaultAccessibilityLabel}, ${selectedLabel}`; + } + return defaultAccessibilityLabel; + }, [accessibilityLabel, label, selectedLabel]); + if (isDisabled && shouldShowOnlyTextWhenDisabled) { return ( @@ -210,7 +223,7 @@ function BasePicker({ textInputProps={{ allowFontScaling: false, accessibilityRole: CONST.ROLE.COMBOBOX, - accessibilityLabel, + accessibilityLabel: enhancedAccessibilityLabel, }} pickerProps={{ ref: picker, @@ -220,7 +233,7 @@ function BasePicker({ disableHighlight(); onBlur(); }, - accessibilityLabel, + accessibilityLabel: enhancedAccessibilityLabel, accessibilityRole: CONST.ROLE.COMBOBOX, ...additionalPickerEvents(enableHighlight, (inputValue, index) => { onValueChange(inputValue, index); From a5cf4425d2f6cfcdffa3060592a60f96d1cadeb3 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 25 Feb 2026 16:14:42 +0700 Subject: [PATCH 05/10] update label with picker state --- src/components/Picker/BasePicker.tsx | 8 +++++--- src/languages/en.ts | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/Picker/BasePicker.tsx b/src/components/Picker/BasePicker.tsx index e4adf6326e284..238a2c0393a1f 100644 --- a/src/components/Picker/BasePicker.tsx +++ b/src/components/Picker/BasePicker.tsx @@ -9,6 +9,7 @@ import FormHelpMessage from '@components/FormHelpMessage'; import Icon from '@components/Icon'; import Text from '@components/Text'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; +import useLocalize from '@hooks/useLocalize'; import useScrollContext from '@hooks/useScrollContext'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -44,6 +45,7 @@ function BasePicker({ const icons = useMemoizedLazyExpensifyIcons(['DownArrow']); const theme = useTheme(); const styles = useThemeStyles(); + const {translate} = useLocalize(); const [isHighlighted, setIsHighlighted] = useState(false); @@ -172,10 +174,10 @@ function BasePicker({ return selectedLabel || ''; } if (selectedLabel) { - return `${defaultAccessibilityLabel}, ${selectedLabel}`; + return `${defaultAccessibilityLabel}, ${selectedLabel}, ${translate(isHighlighted ? 'common.expanded' : 'common.collapsed')}`; } return defaultAccessibilityLabel; - }, [accessibilityLabel, label, selectedLabel]); + }, [accessibilityLabel, label, selectedLabel, isHighlighted, translate]); if (isDisabled && shouldShowOnlyTextWhenDisabled) { return ( @@ -232,7 +234,7 @@ function BasePicker({ touchableWrapperProps={{ accessible: true, accessibilityRole: CONST.ROLE.COMBOBOX, - accessibilityLabel, + accessibilityLabel: enhancedAccessibilityLabel, accessibilityState: {disabled: isDisabled, expanded: isHighlighted}, }} pickerProps={{ diff --git a/src/languages/en.ts b/src/languages/en.ts index 2853a560de896..d8685566a75c0 100644 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -495,6 +495,8 @@ const translations = { downloadAsPDF: 'Download as PDF', downloadAsCSV: 'Download as CSV', help: 'Help', + collapsed: 'Collapsed', + expanded: 'Expanded', expenseReport: 'Expense Report', expenseReports: 'Expense Reports', // @context Rate as a noun, not a verb From 68e0053238413ba4895a06f8cfb38cfcbdb52ab6 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Tue, 3 Mar 2026 12:32:24 +0700 Subject: [PATCH 06/10] update translation --- src/languages/de.ts | 2 ++ src/languages/es.ts | 2 ++ src/languages/fr.ts | 2 ++ src/languages/it.ts | 2 ++ src/languages/ja.ts | 2 ++ src/languages/nl.ts | 2 ++ src/languages/pl.ts | 2 ++ src/languages/pt-BR.ts | 2 ++ src/languages/zh-hans.ts | 2 ++ 9 files changed, 18 insertions(+) diff --git a/src/languages/de.ts b/src/languages/de.ts index 0459976e55345..c87094a39b49b 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -476,6 +476,8 @@ const translations: TranslationDeepObject = { downloadAsPDF: 'Als PDF herunterladen', downloadAsCSV: 'Als CSV herunterladen', help: 'Hilfe', + collapsed: 'Eingeklappt', + expanded: 'Ausgeklappt', expenseReport: 'Spesenabrechnung', expenseReports: 'Spesenabrechnungen', rateOutOfPolicy: 'Satz außerhalb der Richtlinie', diff --git a/src/languages/es.ts b/src/languages/es.ts index 0b37985ac7978..c0483ba8bf850 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -340,6 +340,8 @@ const translations: TranslationDeepObject = { downloadAsPDF: 'Descargar como PDF', downloadAsCSV: 'Descargar como CSV', help: 'Ayuda', + collapsed: 'Contraído', + expanded: 'Expandido', expenseReport: 'Informe de Gastos', expenseReports: 'Informes de Gastos', rateOutOfPolicy: 'Tasa fuera de póliza', diff --git a/src/languages/fr.ts b/src/languages/fr.ts index 8612fe1f26ecf..f0d5b2740ccc9 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -476,6 +476,8 @@ const translations: TranslationDeepObject = { downloadAsPDF: 'Télécharger en PDF', downloadAsCSV: 'Télécharger au format CSV', help: 'Aide', + collapsed: 'Réduit', + expanded: 'Développé', expenseReport: 'Note de frais', expenseReports: 'Notes de frais', rateOutOfPolicy: 'Taux hors politique', diff --git a/src/languages/it.ts b/src/languages/it.ts index 7253602172d8e..d5f974a26a402 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -476,6 +476,8 @@ const translations: TranslationDeepObject = { downloadAsPDF: 'Scarica come PDF', downloadAsCSV: 'Scarica come CSV', help: 'Aiuto', + collapsed: 'Comprresso', + expanded: 'Espanso', expenseReport: 'Nota spese', expenseReports: 'Note spese', rateOutOfPolicy: 'Tariffa fuori policy', diff --git a/src/languages/ja.ts b/src/languages/ja.ts index f8950b35a817f..6d85296ecd5d8 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -475,6 +475,8 @@ const translations: TranslationDeepObject = { downloadAsPDF: 'PDFとしてダウンロード', downloadAsCSV: 'CSVとしてダウンロード', help: 'ヘルプ', + collapsed: '折りたたみ', + expanded: '展開', expenseReport: '経費精算書', expenseReports: '経費レポート', rateOutOfPolicy: 'ポリシー対象外のレート', diff --git a/src/languages/nl.ts b/src/languages/nl.ts index 22c816b73a52a..f490e98386b99 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -475,6 +475,8 @@ const translations: TranslationDeepObject = { downloadAsPDF: 'Downloaden als PDF', downloadAsCSV: 'Downloaden als CSV', help: 'Help', + collapsed: 'Ingeklapt', + expanded: 'Uitgeklapt', expenseReport: 'Declaratie', expenseReports: 'Declaraties', rateOutOfPolicy: 'Tarief buiten beleid', diff --git a/src/languages/pl.ts b/src/languages/pl.ts index 869ceec0257c7..5beb07daf238e 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -475,6 +475,8 @@ const translations: TranslationDeepObject = { downloadAsPDF: 'Pobierz jako PDF', downloadAsCSV: 'Pobierz jako CSV', help: 'Pomoc', + collapsed: 'Zwinięte', + expanded: 'Rozwinięte', expenseReport: 'Raport wydatków', expenseReports: 'Raporty wydatków', rateOutOfPolicy: 'Stawka poza zasadami', diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index 974de7916f180..98f3fdec8ebbc 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -475,6 +475,8 @@ const translations: TranslationDeepObject = { downloadAsPDF: 'Baixar como PDF', downloadAsCSV: 'Baixar como CSV', help: 'Ajuda', + collapsed: 'Recolhido', + expanded: 'Expandido', expenseReport: 'Relatório de despesas', expenseReports: 'Relatórios de despesas', rateOutOfPolicy: 'Taxa fora da política', diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index 585831782b4be..373fb603e2712 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -475,6 +475,8 @@ const translations: TranslationDeepObject = { downloadAsPDF: '下载为 PDF', downloadAsCSV: '下载为 CSV', help: '帮助', + collapsed: '已折叠', + expanded: '已展开', expenseReport: '报销报告', expenseReports: '报销报告', rateOutOfPolicy: '超出政策的费率', From ef75c9610374a76e4f7331661b8f64ad90f4cf54 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 11 Mar 2026 12:17:14 +0700 Subject: [PATCH 07/10] remove accessibilityState --- src/components/Picker/BasePicker.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/Picker/BasePicker.tsx b/src/components/Picker/BasePicker.tsx index 238a2c0393a1f..c2394ba0b4b33 100644 --- a/src/components/Picker/BasePicker.tsx +++ b/src/components/Picker/BasePicker.tsx @@ -235,7 +235,6 @@ function BasePicker({ accessible: true, accessibilityRole: CONST.ROLE.COMBOBOX, accessibilityLabel: enhancedAccessibilityLabel, - accessibilityState: {disabled: isDisabled, expanded: isHighlighted}, }} pickerProps={{ ref: picker, From 3884b1a8ee37adde7167442d86db35ac587475cf Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 13 Mar 2026 10:58:56 +0700 Subject: [PATCH 08/10] fix mweb issue --- src/components/Picker/BasePicker.tsx | 3 ++- .../Picker/shouldAnnounceSelectedLabel/index.native.ts | 4 ++++ src/components/Picker/shouldAnnounceSelectedLabel/index.ts | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 src/components/Picker/shouldAnnounceSelectedLabel/index.native.ts create mode 100644 src/components/Picker/shouldAnnounceSelectedLabel/index.ts diff --git a/src/components/Picker/BasePicker.tsx b/src/components/Picker/BasePicker.tsx index c2394ba0b4b33..86f31303ccd0c 100644 --- a/src/components/Picker/BasePicker.tsx +++ b/src/components/Picker/BasePicker.tsx @@ -16,6 +16,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import {isMobile} from '@libs/Browser'; import getOperatingSystem from '@libs/getOperatingSystem'; import CONST from '@src/CONST'; +import shouldAnnounceSelectedLabel from './shouldAnnounceSelectedLabel'; import type {BasePickerProps} from './types'; type IconToRender = () => ReactElement; @@ -174,7 +175,7 @@ function BasePicker({ return selectedLabel || ''; } if (selectedLabel) { - return `${defaultAccessibilityLabel}, ${selectedLabel}, ${translate(isHighlighted ? 'common.expanded' : 'common.collapsed')}`; + return `${defaultAccessibilityLabel}${shouldAnnounceSelectedLabel ? `, ${selectedLabel}` : ''}, ${translate(isHighlighted ? 'common.expanded' : 'common.collapsed')}`; } return defaultAccessibilityLabel; }, [accessibilityLabel, label, selectedLabel, isHighlighted, translate]); diff --git a/src/components/Picker/shouldAnnounceSelectedLabel/index.native.ts b/src/components/Picker/shouldAnnounceSelectedLabel/index.native.ts new file mode 100644 index 0000000000000..b0065c13d70db --- /dev/null +++ b/src/components/Picker/shouldAnnounceSelectedLabel/index.native.ts @@ -0,0 +1,4 @@ +// Native: we should explicitly include the selected label in the accessibility label. +const shouldAnnounceSelectedLabel = true; + +export default shouldAnnounceSelectedLabel; diff --git a/src/components/Picker/shouldAnnounceSelectedLabel/index.ts b/src/components/Picker/shouldAnnounceSelectedLabel/index.ts new file mode 100644 index 0000000000000..4d4e89163d104 --- /dev/null +++ b/src/components/Picker/shouldAnnounceSelectedLabel/index.ts @@ -0,0 +1,5 @@ +// Web: the picker uses the `value` attribute, which VoiceOver already announces. +// Avoid duplicating the selected label in the accessibility label. +const shouldAnnounceSelectedLabel = false; + +export default shouldAnnounceSelectedLabel; From 12f50b41c2d192f87e342ce45ea2622ba7b775e8 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 16 Mar 2026 16:44:17 +0700 Subject: [PATCH 09/10] update accessibilityLabel for web --- src/components/Picker/BasePicker.tsx | 16 +++++++++------- .../getAccessibilityLabelConfig/index.native.ts | 8 ++++++++ .../Picker/getAccessibilityLabelConfig/index.ts | 12 ++++++++++++ .../shouldAnnounceSelectedLabel/index.native.ts | 4 ---- .../Picker/shouldAnnounceSelectedLabel/index.ts | 5 ----- 5 files changed, 29 insertions(+), 16 deletions(-) create mode 100644 src/components/Picker/getAccessibilityLabelConfig/index.native.ts create mode 100644 src/components/Picker/getAccessibilityLabelConfig/index.ts delete mode 100644 src/components/Picker/shouldAnnounceSelectedLabel/index.native.ts delete mode 100644 src/components/Picker/shouldAnnounceSelectedLabel/index.ts diff --git a/src/components/Picker/BasePicker.tsx b/src/components/Picker/BasePicker.tsx index 86f31303ccd0c..888aca77695b6 100644 --- a/src/components/Picker/BasePicker.tsx +++ b/src/components/Picker/BasePicker.tsx @@ -16,7 +16,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import {isMobile} from '@libs/Browser'; import getOperatingSystem from '@libs/getOperatingSystem'; import CONST from '@src/CONST'; -import shouldAnnounceSelectedLabel from './shouldAnnounceSelectedLabel'; +import getAccessibilityLabelConfig from './getAccessibilityLabelConfig'; import type {BasePickerProps} from './types'; type IconToRender = () => ReactElement; @@ -47,7 +47,7 @@ function BasePicker({ const theme = useTheme(); const styles = useThemeStyles(); const {translate} = useLocalize(); - + const {shouldAnnounceSelectedLabel, shouldUseCustomAccessibilityLabel} = getAccessibilityLabelConfig(); const [isHighlighted, setIsHighlighted] = useState(false); // reference to the root View @@ -169,8 +169,8 @@ function BasePicker({ const selectedItem = items.find((item) => item.value === value); const selectedLabel = selectedItem?.label ?? ''; + const defaultAccessibilityLabel = accessibilityLabel ?? label ?? selectedLabel; const enhancedAccessibilityLabel = useMemo(() => { - const defaultAccessibilityLabel = accessibilityLabel ?? label; if (!defaultAccessibilityLabel) { return selectedLabel || ''; } @@ -178,7 +178,7 @@ function BasePicker({ return `${defaultAccessibilityLabel}${shouldAnnounceSelectedLabel ? `, ${selectedLabel}` : ''}, ${translate(isHighlighted ? 'common.expanded' : 'common.collapsed')}`; } return defaultAccessibilityLabel; - }, [accessibilityLabel, label, selectedLabel, isHighlighted, translate]); + }, [defaultAccessibilityLabel, selectedLabel, shouldAnnounceSelectedLabel, translate, isHighlighted]); if (isDisabled && shouldShowOnlyTextWhenDisabled) { return ( @@ -197,6 +197,8 @@ function BasePicker({ ); } + const actualAccessibilityLabel = shouldUseCustomAccessibilityLabel ? enhancedAccessibilityLabel : defaultAccessibilityLabel; + return ( <> ({ textInputProps={{ allowFontScaling: false, accessibilityRole: CONST.ROLE.COMBOBOX, - accessibilityLabel: enhancedAccessibilityLabel, + accessibilityLabel: actualAccessibilityLabel, importantForAccessibility: 'no-hide-descendants', }} touchableDoneProps={{ @@ -235,7 +237,7 @@ function BasePicker({ touchableWrapperProps={{ accessible: true, accessibilityRole: CONST.ROLE.COMBOBOX, - accessibilityLabel: enhancedAccessibilityLabel, + accessibilityLabel: actualAccessibilityLabel, }} pickerProps={{ ref: picker, @@ -245,7 +247,7 @@ function BasePicker({ disableHighlight(); onBlur(); }, - accessibilityLabel: enhancedAccessibilityLabel, + accessibilityLabel: actualAccessibilityLabel, accessibilityRole: CONST.ROLE.COMBOBOX, ...additionalPickerEvents(enableHighlight, (inputValue, index) => { onValueChange(inputValue, index); diff --git a/src/components/Picker/getAccessibilityLabelConfig/index.native.ts b/src/components/Picker/getAccessibilityLabelConfig/index.native.ts new file mode 100644 index 0000000000000..3ec9209934557 --- /dev/null +++ b/src/components/Picker/getAccessibilityLabelConfig/index.native.ts @@ -0,0 +1,8 @@ +const getAccessibilityLabelConfig = () => { + return { + shouldAnnounceSelectedLabel: true, + shouldUseCustomAccessibilityLabel: true, + }; +}; + +export default getAccessibilityLabelConfig; diff --git a/src/components/Picker/getAccessibilityLabelConfig/index.ts b/src/components/Picker/getAccessibilityLabelConfig/index.ts new file mode 100644 index 0000000000000..b76e9300425fa --- /dev/null +++ b/src/components/Picker/getAccessibilityLabelConfig/index.ts @@ -0,0 +1,12 @@ +import {isMobile} from '@libs/Browser'; + +const getAccessibilityLabelConfig = () => { + // Mobile Web: the picker uses the `value` attribute, which VoiceOver already announces. + // Avoid duplicating the selected label in the accessibility label. + return { + shouldAnnounceSelectedLabel: false, + shouldUseCustomAccessibilityLabel: isMobile(), + }; +}; + +export default getAccessibilityLabelConfig; diff --git a/src/components/Picker/shouldAnnounceSelectedLabel/index.native.ts b/src/components/Picker/shouldAnnounceSelectedLabel/index.native.ts deleted file mode 100644 index b0065c13d70db..0000000000000 --- a/src/components/Picker/shouldAnnounceSelectedLabel/index.native.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Native: we should explicitly include the selected label in the accessibility label. -const shouldAnnounceSelectedLabel = true; - -export default shouldAnnounceSelectedLabel; diff --git a/src/components/Picker/shouldAnnounceSelectedLabel/index.ts b/src/components/Picker/shouldAnnounceSelectedLabel/index.ts deleted file mode 100644 index 4d4e89163d104..0000000000000 --- a/src/components/Picker/shouldAnnounceSelectedLabel/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -// Web: the picker uses the `value` attribute, which VoiceOver already announces. -// Avoid duplicating the selected label in the accessibility label. -const shouldAnnounceSelectedLabel = false; - -export default shouldAnnounceSelectedLabel; From 3c5cbc2fb26dc99231a88b03a76e9e5b332faf6d Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Tue, 17 Mar 2026 16:33:06 +0700 Subject: [PATCH 10/10] fix lint error --- src/components/Picker/BasePicker.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/Picker/BasePicker.tsx b/src/components/Picker/BasePicker.tsx index b92a1bdc36200..031a0b7e85fd7 100644 --- a/src/components/Picker/BasePicker.tsx +++ b/src/components/Picker/BasePicker.tsx @@ -47,7 +47,6 @@ function BasePicker({ const {translate} = useLocalize(); const theme = useTheme(); const styles = useThemeStyles(); - const {translate} = useLocalize(); const {shouldAnnounceSelectedLabel, shouldUseCustomAccessibilityLabel} = getAccessibilityLabelConfig(); const [isHighlighted, setIsHighlighted] = useState(false);