Refactor Settings component to replace native select elements with custom Select components for improved UI consistency and usability

This commit is contained in:
ecwu
2024-12-21 14:10:12 +08:00
parent 685ef3c9d6
commit 5535706a26

View File

@@ -49,11 +49,14 @@ import {
CardTitle, CardTitle,
} from "@/components/ui/card"; } from "@/components/ui/card";
import { import {
Tooltip, Select,
TooltipContent, SelectContent,
TooltipProvider, SelectGroup,
TooltipTrigger, SelectItem,
} from "@/components/ui/tooltip"; SelectLabel,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@@ -152,11 +155,9 @@ const SelectModel = (props: {
}} }}
/> />
) : ( ) : (
<select <Select
className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
value={props.chatStore.model} value={props.chatStore.model}
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => { onValueChange={(model: string) => {
const model = e.target.value;
props.chatStore.model = model; props.chatStore.model = model;
props.chatStore.maxTokens = getDefaultParams( props.chatStore.maxTokens = getDefaultParams(
"max", "max",
@@ -165,12 +166,20 @@ const SelectModel = (props: {
props.setChatStore({ ...props.chatStore }); props.setChatStore({ ...props.chatStore });
}} }}
> >
<SelectTrigger className="w-full">
<SelectValue placeholder="Select a model" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Models</SelectLabel>
{Object.keys(models).map((opt) => ( {Object.keys(models).map((opt) => (
<option key={opt} value={opt}> <SelectItem key={opt} value={opt}>
{opt} {opt}
</option> </SelectItem>
))} ))}
</select> </SelectGroup>
</SelectContent>
</Select>
)} )}
</div> </div>
); );
@@ -679,22 +688,21 @@ export default (props: {
<div className="space-y-4"> <div className="space-y-4">
<div className="space-y-2"> <div className="space-y-2">
<Label>Language</Label> <Label>Language</Label>
<select <Select value={langCode} onValueChange={setLangCode}>
className="w-full p-2 rounded-md border border-input" <SelectTrigger className="w-full">
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => <SelectValue placeholder="Select language" />
setLangCode(e.target.value) </SelectTrigger>
} <SelectContent>
> <SelectGroup>
<SelectLabel>Languages</SelectLabel>
{Object.keys(LANG_OPTIONS).map((opt) => ( {Object.keys(LANG_OPTIONS).map((opt) => (
<option <SelectItem key={opt} value={opt}>
key={opt}
value={opt}
selected={opt === langCode}
>
{LANG_OPTIONS[opt].name} {LANG_OPTIONS[opt].name}
</option> </SelectItem>
))} ))}
</select> </SelectGroup>
</SelectContent>
</Select>
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
@@ -1055,22 +1063,27 @@ export default (props: {
</DialogContent> </DialogContent>
</Dialog> </Dialog>
</Label> </Label>
<select <Select
className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
value={props.chatStore.tts_voice} value={props.chatStore.tts_voice}
onChange={( onValueChange={(value) => {
event: React.ChangeEvent<HTMLSelectElement> props.chatStore.tts_voice = value;
) => {
props.chatStore.tts_voice = event.target.value;
props.setChatStore({ ...props.chatStore }); props.setChatStore({ ...props.chatStore });
}} }}
> >
<SelectTrigger className="w-full">
<SelectValue placeholder="Select a voice" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Voices</SelectLabel>
{TTS_VOICES.map((opt) => ( {TTS_VOICES.map((opt) => (
<option key={opt} value={opt}> <SelectItem key={opt} value={opt}>
{opt} {opt}
</option> </SelectItem>
))} ))}
</select> </SelectGroup>
</SelectContent>
</Select>
</div> </div>
<Slicer <Slicer
@@ -1100,22 +1113,27 @@ export default (props: {
</DialogContent> </DialogContent>
</Dialog> </Dialog>
</Label> </Label>
<select <Select
className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
value={props.chatStore.tts_format} value={props.chatStore.tts_format}
onChange={( onValueChange={(value) => {
event: React.ChangeEvent<HTMLSelectElement> props.chatStore.tts_format = value;
) => {
props.chatStore.tts_format = event.target.value;
props.setChatStore({ ...props.chatStore }); props.setChatStore({ ...props.chatStore });
}} }}
> >
<SelectTrigger className="w-full">
<SelectValue placeholder="Select a format" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Formats</SelectLabel>
{TTS_FORMAT.map((opt) => ( {TTS_FORMAT.map((opt) => (
<option key={opt} value={opt}> <SelectItem key={opt} value={opt}>
{opt} {opt}
</option> </SelectItem>
))} ))}
</select> </SelectGroup>
</SelectContent>
</Select>
</div> </div>
</div> </div>
</AccordionContent> </AccordionContent>