11import { runRpc } from "@/util/ws" ;
2- import { useEffect , useState } from "react" ;
2+ import { useEffect , useMemo , useState } from "react" ;
3+ import {
4+ Label ,
5+ Listbox ,
6+ ListboxButton ,
7+ ListboxOption ,
8+ ListboxOptions ,
9+ } from "@headlessui/react" ;
10+ import { ChevronDownIcon } from "@heroicons/react/20/solid" ;
311
412export function SettingsSelect ( { setting } ) {
513 const [ value , setValue ] = useState ( 0 ) ;
614
15+ const selectedOption = useMemo ( ( ) => {
16+ return setting . options . find ( ( o ) => o . value === value . toString ( ) ) ;
17+ } , [ value , setting . options ] ) ;
18+
719 useEffect ( ( ) => {
820 runRpc ( "getcvar" , setting . cvar ) . then ( ( response ) => {
921 if ( response !== null && response . length > 0 ) {
@@ -19,16 +31,47 @@ export function SettingsSelect({ setting }) {
1931
2032 return (
2133 < div >
22- < label className = "block mb-2 text-white tf2-light text-xl" >
23- { setting . label }
24- </ label >
25- < select className = "px-4 py-2 mb-2 border text-white" value = { value } onChange = { ( ev ) => callback ( ev . target . value ) } >
26- { setting . options . map ( ( option ) => (
27- < option key = { option . value } value = { option . value } selected = { option . value === value } >
28- { option . label }
29- </ option >
30- ) ) }
31- </ select >
34+ < Listbox value = { value . toString ( ) } onChange = { callback } >
35+ < Label className = "block mb-2 text-white tf2-light text-xl" >
36+ { setting . label }
37+ </ Label >
38+ < div className = "relative mt-2" >
39+ < div className = "inline-flex divide-x divide-stone-700 outline-hidden dark:divide-stone-600" >
40+ < ListboxButton className = "cursor-default inline-flex items-center gap-x-4 bg-stone-600 px-3 py-2 text-white dark:bg-stone-500 hover:bg-stone-700 focus-visible:outline-1 focus-visible:outline-stone-400 dark:bg-stone-500 dark:hover:bg-stone-400 dark:focus-visible:outline-stone-400" >
41+ < p className = "text-lg tf2-light font-semibold" >
42+ { selectedOption ?. label ?? "\u00A0" }
43+ </ p >
44+ < ChevronDownIcon aria-hidden = "true" className = "size-5 text-white forced-colors:text-[Highlight]" />
45+ </ ListboxButton >
46+ </ div >
47+
48+ < ListboxOptions
49+ transition
50+ className = "tf2-light absolute mt-1 max-h-76 z-10 mt-2 origin-top-right divide-y divide-gray-200 overflow-y-auto overflow-x-hidden bg-white shadow-lg outline-1 outline-black/5 data-leave:transition data-leave:duration-100 data-leave:ease-in data-closed:data-leave:opacity-0 dark:divide-white/10 dark:bg-stone-800 dark:shadow-none dark:-outline-offset-1 dark:outline-white/10"
51+ >
52+ { setting . options . map ( ( option ) => (
53+ < ListboxOption
54+ key = { option . value }
55+ value = { option . value }
56+ className = "group cursor-default p-4 text-lg text-gray-900 select-none data-focus:bg-stone-600 data-focus:text-white dark:text-white dark:data-focus:bg-stone-500"
57+ >
58+ < div className = "flex flex-col" >
59+ < div className = "flex justify-between" >
60+ < p className = "font-normal group-data-selected:font-semibold" >
61+ { option . label }
62+ </ p >
63+ </ div >
64+ { option . tooltip && (
65+ < p className = "mt-2 text-gray-500 group-data-focus:text-stone-200 dark:text-gray-400 dark:group-data-focus:text-stone-100" >
66+ { option . tooltip }
67+ </ p >
68+ ) }
69+ </ div >
70+ </ ListboxOption >
71+ ) ) }
72+ </ ListboxOptions >
73+ </ div >
74+ </ Listbox >
3275 </ div >
3376 ) ;
3477}
0 commit comments