Skip to content

Commit

Permalink
feat(mobile): use native select for mobile setting
Browse files Browse the repository at this point in the history
  • Loading branch information
CatsJuice committed Dec 21, 2024
1 parent 3a82da0 commit aad4bb5
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const root = style({
display: 'flex',
alignItems: 'center',
gap: 8,
position: 'relative',
});
export const label = style([
bodyRegular,
Expand All @@ -15,3 +16,11 @@ export const icon = style({
fontSize: 24,
color: cssVarV2('icon/primary'),
});
export const nativeSelect = style({
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
opacity: 0,
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import {
type CSSProperties,
type HTMLAttributes,
type ReactNode,
useCallback,
useMemo,
useRef,
} from 'react';

import * as styles from './dropdown-select.css';
Expand All @@ -28,6 +30,7 @@ export interface SettingDropdownSelectProps<
) => void;
emitValue?: E;
menuOptions?: Omit<MenuProps, 'items' | 'children'>;
native?: boolean;
}

export const SettingDropdownSelect = <
Expand All @@ -40,12 +43,26 @@ export const SettingDropdownSelect = <
onChange,
className,
menuOptions,
native = true,
...attrs
}: SettingDropdownSelectProps<V, E>) => {
const selectedItem = useMemo(
() => options.find(opt => opt.value === value),
[options, value]
);

if (native) {
return (
<NativeSettingDropdownSelect
options={options}
value={value}
emitValue={emitValue as any}
onChange={onChange}
{...attrs}
/>
);
}

return (
<MobileMenu
items={options.map(opt => (
Expand Down Expand Up @@ -76,3 +93,58 @@ export const SettingDropdownSelect = <
</MobileMenu>
);
};

export const NativeSettingDropdownSelect = <
V extends string = string,
E extends boolean | undefined = true,
>({
options = [],
value,
emitValue = true,
onChange,
className,
...attrs
}: Omit<SettingDropdownSelectProps<V, E>, 'native'>) => {
const nativeSelectRef = useRef<HTMLSelectElement>(null);
const selectedItem = useMemo(
() => options.find(opt => opt.value === value),
[options, value]
);

const handleChange = useCallback(
(e: React.ChangeEvent<HTMLSelectElement>) => {
const value = e.target.value;
const opt = options.find(opt => opt.value === value);
if (emitValue) {
onChange?.(e.target.value as any);
} else {
onChange?.(opt as any);
}
},
[emitValue, onChange, options]
);

return (
<div
data-testid="dropdown-select-trigger"
className={clsx(styles.root, className)}
{...attrs}
>
<span className={styles.label}>{selectedItem?.label ?? ''}</span>

<ArrowDownSmallIcon className={styles.icon} />
<select
className={styles.nativeSelect}
ref={nativeSelectRef}
value={value}
onChange={handleChange}
>
{options.map(opt => (
<option key={opt.value} value={opt.value}>
{opt.label}
</option>
))}
</select>
</div>
);
};

0 comments on commit aad4bb5

Please sign in to comment.