Skip to content

Commit 2b5e544

Browse files
committed
chore: Make model selector on par with the rest of the apps
1 parent 50e868e commit 2b5e544

File tree

1 file changed

+49
-7
lines changed

1 file changed

+49
-7
lines changed

apps/text-embeddings/components/ModelPicker.tsx

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import React, { useEffect, useState } from 'react';
1+
import React, { useEffect, useRef, useState } from 'react';
22
import {
3-
View,
3+
Dimensions,
4+
ScrollView,
45
StyleSheet,
56
Text,
67
TouchableOpacity,
7-
ScrollView,
8+
View,
89
} from 'react-native';
910

1011
export type ModelOption<T> = {
@@ -20,6 +21,8 @@ type Props<T> = {
2021
disabled?: boolean;
2122
};
2223

24+
const DROPDOWN_MAX_HEIGHT = 200;
25+
2326
export function ModelPicker<T>({
2427
models,
2528
selectedModel,
@@ -28,18 +31,44 @@ export function ModelPicker<T>({
2831
disabled,
2932
}: Props<T>) {
3033
const [open, setOpen] = useState(false);
34+
const [triggerHeight, setTriggerHeight] = useState(0);
35+
const [expandUp, setExpandUp] = useState(false);
36+
const triggerRef = useRef<React.ComponentRef<typeof TouchableOpacity>>(null);
3137
const selected = models.find((m) => m.value === selectedModel);
3238

3339
useEffect(() => {
3440
if (disabled) setOpen(false);
3541
}, [disabled]);
3642

43+
const handleLayout = () => {
44+
triggerRef.current?.measure(
45+
(
46+
_x: number,
47+
_y: number,
48+
_width: number,
49+
height: number,
50+
_pageX: number,
51+
pageY: number
52+
) => {
53+
setTriggerHeight(height);
54+
const spaceBelow = Dimensions.get('window').height - (pageY + height);
55+
setExpandUp(spaceBelow < DROPDOWN_MAX_HEIGHT);
56+
}
57+
);
58+
};
59+
60+
const dropdownPosition = expandUp
61+
? { bottom: triggerHeight + 2 }
62+
: { top: triggerHeight + 2 };
63+
3764
return (
3865
<View style={styles.container}>
3966
<TouchableOpacity
67+
ref={triggerRef}
4068
style={[styles.trigger, disabled && styles.triggerDisabled]}
4169
onPress={() => !disabled && setOpen((v) => !v)}
4270
activeOpacity={disabled ? 1 : 0.7}
71+
onLayout={handleLayout}
4372
>
4473
{label && <Text style={styles.label}>{label}</Text>}
4574
<Text style={styles.triggerText}>{selected?.label ?? '—'}</Text>
@@ -48,7 +77,7 @@ export function ModelPicker<T>({
4877

4978
{open && (
5079
<ScrollView
51-
style={styles.dropdown}
80+
style={[styles.dropdown, dropdownPosition]}
5281
nestedScrollEnabled
5382
keyboardShouldPersistTaps="handled"
5483
>
@@ -81,7 +110,12 @@ export function ModelPicker<T>({
81110
}
82111

83112
const styles = StyleSheet.create({
84-
container: { marginHorizontal: 12, marginVertical: 4, alignSelf: 'stretch' },
113+
container: {
114+
marginHorizontal: 12,
115+
marginVertical: 4,
116+
alignSelf: 'stretch',
117+
zIndex: 100,
118+
},
85119
trigger: {
86120
flexDirection: 'row',
87121
alignItems: 'center',
@@ -112,12 +146,20 @@ const styles = StyleSheet.create({
112146
marginLeft: 6,
113147
},
114148
dropdown: {
149+
position: 'absolute',
150+
left: 0,
151+
right: 0,
115152
borderWidth: 1,
116153
borderColor: '#C1C6E5',
117154
borderRadius: 8,
118155
backgroundColor: '#fff',
119-
maxHeight: 200,
120-
marginTop: 2,
156+
maxHeight: DROPDOWN_MAX_HEIGHT,
157+
zIndex: 100,
158+
elevation: 4,
159+
shadowColor: '#000',
160+
shadowOffset: { width: 0, height: 2 },
161+
shadowOpacity: 0.1,
162+
shadowRadius: 4,
121163
},
122164
option: {
123165
paddingHorizontal: 12,

0 commit comments

Comments
 (0)