From 0327a6623c28f1beee5a5bbcd1c113c51a286b3c Mon Sep 17 00:00:00 2001 From: Rhiley Epperson Date: Tue, 3 Jun 2025 09:49:08 -0400 Subject: [PATCH 1/7] (partial) issue 43: replace hardcoded values --- src/components/MultiSelect.tsx | 7 +++++-- src/components/Select.tsx | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/components/MultiSelect.tsx b/src/components/MultiSelect.tsx index 9335a54..12f7f0a 100644 --- a/src/components/MultiSelect.tsx +++ b/src/components/MultiSelect.tsx @@ -6,6 +6,9 @@ import SelectionList from './SelectionList'; /* Renders a multi-selector component. Takes in props defined in the MultiSelectProperties type. */ const MultiSelect = (props: MultiSelectProperties): React.JSX.Element => { + const defaultPlaceholderText = 'Click me'; + const disabledOpacity = .5; + const enabledOpacity = 1; const style = useThemeStyles(props.theme ?? 'system'); const ref = useRef(null); const [listDisplay, setListDisplay] = useState(false); @@ -42,7 +45,7 @@ const MultiSelect = (props: MultiSelectProperties): React.JSX.Element => { style={[ style.selectorBox, props.boxStyle, - {opacity: props.disabled ? .5 : 1}, + {opacity: props.disabled ? disabledOpacity : enabledOpacity}, ]} disabled={props.disabled} onPress={() => updatePos(true)} @@ -72,7 +75,7 @@ const MultiSelect = (props: MultiSelectProperties): React.JSX.Element => { : - {props.placeholderText ?? 'Click me'} + {props.placeholderText ?? defaultPlaceholderText} } { + const defaultPlaceholderText = 'Click me'; + const disabledOpacity = .5; + const enabledOpacity = 1; const style = useThemeStyles(props.theme ?? 'system'); const ref = useRef(null); const [listDisplay, setListDisplay] = useState(false); @@ -18,7 +21,7 @@ const Select = (props: SelectProperties): React.JSX.Element => { const [selected, setSelected] = useState( props.defaultValue && props.data.includes(props.defaultValue) ? props.defaultValue - : {label: props.placeholderText ?? 'Click me'} + : {label: props.placeholderText ?? defaultPlaceholderText} ); const updatePriorities = (data: Data[]) => [ ...data.filter((d: Data) => d.priority), @@ -42,7 +45,7 @@ const Select = (props: SelectProperties): React.JSX.Element => { style={[ style.selectorBox, props.boxStyle, - {opacity: props.disabled ? .5 : 1}, + {opacity: props.disabled ? disabledOpacity : enabledOpacity}, ]} disabled={props.disabled} onPress={updatePos} From ff607aad6a292866b1f6b462ba999bb62e32605f Mon Sep 17 00:00:00 2001 From: Rhiley Epperson Date: Tue, 3 Jun 2025 13:33:25 -0400 Subject: [PATCH 2/7] cleanup magic numbers in SelectionList --- src/components/SelectionList.tsx | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/components/SelectionList.tsx b/src/components/SelectionList.tsx index 096f150..cf33033 100644 --- a/src/components/SelectionList.tsx +++ b/src/components/SelectionList.tsx @@ -14,6 +14,11 @@ import type { Data, ListProperties } from '../types'; /* Renders a modal with a list of selectable items. Takes in props defined in the ListProperties type. */ const SelectionList = (props: ListProperties): React.JSX.Element => { + const sidewaysTopMargin = 40; + const sidewaysHorizontalMargin = 60; + const sidewaysBorderRadius = 10; + const sidewaysBorderRadiusBL = 0; + const sidewaysBorderRadiusBR = 0; const style = useThemeStyles(props.theme ?? 'system'); const windowWidth = Dimensions.get('window').width; const windowHeight = Dimensions.get('window').height; @@ -78,7 +83,7 @@ const SelectionList = (props: ListProperties): React.JSX.Element => { style.list, props.styles.list, windowHeight > windowWidth - ? { + ? {//phone is held vertical left: props.styles.list?.alignSelf === 'center' ? 0 : props.styles.list?.width @@ -97,13 +102,13 @@ const SelectionList = (props: ListProperties): React.JSX.Element => { : props.selectorRect.y + props.selectorRect.height, opacity: posReady ? 1 : 0, } - : { - height: windowHeight - 40, - marginTop: 40, - marginHorizontal: 60, - borderRadius: 10, - borderBottomLeftRadius: 0, - borderBottomRightRadius: 0, + : {//phone is held horizontal + height: windowHeight - sidewaysTopMargin, + marginTop: sidewaysTopMargin, + marginHorizontal: sidewaysHorizontalMargin, + borderRadius: sidewaysBorderRadius, + borderBottomLeftRadius: sidewaysBorderRadiusBL, + borderBottomRightRadius: sidewaysBorderRadiusBR, }, ]} > @@ -168,7 +173,7 @@ const SelectionList = (props: ListProperties): React.JSX.Element => { style.clearButton, props.styles.clearButton, windowHeight > windowWidth - ? { + ? {//phone upright top: listBottom < windowHeight ? props.selectorRect.y - 40 : props.selectorRect.y + props.selectorRect.height, @@ -176,9 +181,9 @@ const SelectionList = (props: ListProperties): React.JSX.Element => { marginLeft: props.selectorRect.width, opacity: keyboardHeight === 0 && posReady ? 1 : 0, } - : { - top: 40, - right: 10, + : {//phone sideways + top: sidewaysTopMargin, + right: sidewaysBorderRadius, } ]} From 53e65673fcf0d77054e1f3f6c2479ad20982c41a Mon Sep 17 00:00:00 2001 From: Rhiley Epperson Date: Wed, 4 Jun 2025 09:16:15 -0400 Subject: [PATCH 3/7] final magic number cleanup --- src/components/MultiSelect.tsx | 8 +++++--- src/components/Select.tsx | 8 +++++--- src/components/SelectionList.tsx | 9 +++++---- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/components/MultiSelect.tsx b/src/components/MultiSelect.tsx index 12f7f0a..16dc1b9 100644 --- a/src/components/MultiSelect.tsx +++ b/src/components/MultiSelect.tsx @@ -9,6 +9,8 @@ const MultiSelect = (props: MultiSelectProperties): React.JSX.Element => { const defaultPlaceholderText = 'Click me'; const disabledOpacity = .5; const enabledOpacity = 1; + const refRectYOffset = 5; + const defaultListHeight = 200; const style = useThemeStyles(props.theme ?? 'system'); const ref = useRef(null); const [listDisplay, setListDisplay] = useState(false); @@ -30,9 +32,9 @@ const MultiSelect = (props: MultiSelectProperties): React.JSX.Element => { ref.current?.measureInWindow((x, y, width, height) => { setRefRect({ x: x, - y: y - 5, + y: y - refRectYOffset, width: props.boxStyle?.width ?? width, - height: height + 10, + height: height + 2*refRectYOffset, }); if (display) setListDisplay(true); @@ -108,7 +110,7 @@ const MultiSelect = (props: MultiSelectProperties): React.JSX.Element => { } setSelected([]); }} - listHeight={props.listHeight ?? 200} + listHeight={props.listHeight ?? defaultListHeight} display={listDisplay} searchable={!!props.searchable} hide={() => setListDisplay(false)} diff --git a/src/components/Select.tsx b/src/components/Select.tsx index bb2fda9..b298d1e 100644 --- a/src/components/Select.tsx +++ b/src/components/Select.tsx @@ -9,6 +9,8 @@ const Select = (props: SelectProperties): React.JSX.Element => { const defaultPlaceholderText = 'Click me'; const disabledOpacity = .5; const enabledOpacity = 1; + const refRectYOffset = 5; + const defaultListHeight = 200; const style = useThemeStyles(props.theme ?? 'system'); const ref = useRef(null); const [listDisplay, setListDisplay] = useState(false); @@ -31,9 +33,9 @@ const Select = (props: SelectProperties): React.JSX.Element => { ref.current?.measureInWindow((x, y, width, height) => { setRefRect({ x: x, - y: y - 5, + y: y - refRectYOffset, width: props.boxStyle?.width ?? width, - height: height + 10, + height: height + 2*refRectYOffset, }); setListDisplay(true); }); @@ -77,7 +79,7 @@ const Select = (props: SelectProperties): React.JSX.Element => { onSelect={props.onSelect} selected={selected} setSelected={setSelected} - listHeight={props.listHeight ?? 200} + listHeight={props.listHeight ?? defaultListHeight} display={listDisplay} searchable={!!props.searchable} hide={() => setListDisplay(false)} diff --git a/src/components/SelectionList.tsx b/src/components/SelectionList.tsx index cf33033..13989d4 100644 --- a/src/components/SelectionList.tsx +++ b/src/components/SelectionList.tsx @@ -19,6 +19,7 @@ const SelectionList = (props: ListProperties): React.JSX.Element => { const sidewaysBorderRadius = 10; const sidewaysBorderRadiusBL = 0; const sidewaysBorderRadiusBR = 0; + const uprightTopMargin = 40; const style = useThemeStyles(props.theme ?? 'system'); const windowWidth = Dimensions.get('window').width; const windowHeight = Dimensions.get('window').height; @@ -170,14 +171,14 @@ const SelectionList = (props: ListProperties): React.JSX.Element => { {props.type === 'multi' && (props.selected as Data[]).length > 0 && windowWidth ? {//phone upright top: listBottom < windowHeight - ? props.selectorRect.y - 40 + ? props.selectorRect.y - uprightTopMargin : props.selectorRect.y + props.selectorRect.height, - left: props.selectorRect.x - 40, + left: props.selectorRect.x - style.clearButton.width, marginLeft: props.selectorRect.width, opacity: keyboardHeight === 0 && posReady ? 1 : 0, } @@ -195,7 +196,7 @@ const SelectionList = (props: ListProperties): React.JSX.Element => { style={{ ...style.clearIcon, color: props.styles.clearButtonIcon ?? style.clearIcon.color, - }} + }} > {'×'} From a28e4e01aa1129dba2e826eb8d6ef744b3109af2 Mon Sep 17 00:00:00 2001 From: Rhiley Epperson Date: Wed, 4 Jun 2025 09:20:38 -0400 Subject: [PATCH 4/7] it did not warn me about that --- src/components/SelectionList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SelectionList.tsx b/src/components/SelectionList.tsx index 13989d4..9fe91cb 100644 --- a/src/components/SelectionList.tsx +++ b/src/components/SelectionList.tsx @@ -178,7 +178,7 @@ const SelectionList = (props: ListProperties): React.JSX.Element => { top: listBottom < windowHeight ? props.selectorRect.y - uprightTopMargin : props.selectorRect.y + props.selectorRect.height, - left: props.selectorRect.x - style.clearButton.width, + left: props.selectorRect.x - (style.clearButton.width ?? uprightTopMargin), //clearbutton width is theoretically possible to be null so it needs a fallback marginLeft: props.selectorRect.width, opacity: keyboardHeight === 0 && posReady ? 1 : 0, } From b96bfe11a16fb7b6c9e5e3ca4e5ec24b69ed551e Mon Sep 17 00:00:00 2001 From: Rhiley Epperson Date: Wed, 4 Jun 2025 09:22:12 -0400 Subject: [PATCH 5/7] please? --- src/components/SelectionList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SelectionList.tsx b/src/components/SelectionList.tsx index 9fe91cb..b681944 100644 --- a/src/components/SelectionList.tsx +++ b/src/components/SelectionList.tsx @@ -178,7 +178,7 @@ const SelectionList = (props: ListProperties): React.JSX.Element => { top: listBottom < windowHeight ? props.selectorRect.y - uprightTopMargin : props.selectorRect.y + props.selectorRect.height, - left: props.selectorRect.x - (style.clearButton.width ?? uprightTopMargin), //clearbutton width is theoretically possible to be null so it needs a fallback + left: props.selectorRect.x - uprightTopMargin, marginLeft: props.selectorRect.width, opacity: keyboardHeight === 0 && posReady ? 1 : 0, } From f055747641dea185bdffb64b63363aaae2de28c5 Mon Sep 17 00:00:00 2001 From: Rhiley Epperson Date: Wed, 4 Jun 2025 13:24:30 -0400 Subject: [PATCH 6/7] issue 66: screen reader compatibility --- src/components/MultiSelect.tsx | 6 +++++- src/components/Select.tsx | 4 ++++ src/components/SelectionList.tsx | 11 ++++++++++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/components/MultiSelect.tsx b/src/components/MultiSelect.tsx index 16dc1b9..202262a 100644 --- a/src/components/MultiSelect.tsx +++ b/src/components/MultiSelect.tsx @@ -41,8 +41,12 @@ const MultiSelect = (props: MultiSelectProperties): React.JSX.Element => { }); return ( - + 0 ? selected.length + 'items selected' : 'no selection' )}} activeOpacity={1} style={[ style.selectorBox, diff --git a/src/components/Select.tsx b/src/components/Select.tsx index b298d1e..6447314 100644 --- a/src/components/Select.tsx +++ b/src/components/Select.tsx @@ -43,6 +43,10 @@ const Select = (props: SelectProperties): React.JSX.Element => { return ( { {props.searchable && @@ -161,7 +163,11 @@ const SelectionList = (props: ListProperties): React.JSX.Element => { ], ]} > - + {item.label} @@ -193,6 +199,9 @@ const SelectionList = (props: ListProperties): React.JSX.Element => { onPress={props.clearSelected} > Date: Thu, 5 Jun 2025 15:40:46 -0400 Subject: [PATCH 7/7] changelog update --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b84865..4b4b657 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add a plain multi selector to example app that toggles the `disabled` and `searchable` prop in all other selectors ([#28](https://github.com/rhventures/react-native-dropdown-selector/pull/28)). - Add pre-commit hooks to ensure code quality ([#53](https://github.com/rhventures/react-native-dropdown-selector/pull/53)). - Added a new string prop `theme` to allow explicit customization of `Select` and `MultiSelect` components. Options are `system`, `light`, and `dark` ([#55](https://github.com/rhventures/react-native-dropdown-selector/pull/55)). +- Added compatibility for IOS & Android's built-in screen readers ([#112]https://github.com/rhventures/react-native-dropdown-selector/pull/112). ### Changed