Move away from native dropdowns, it looks inconsistent across systems

This commit is contained in:
Lncvrt committed 2026-04-13 15:01:54 -07:00
1 parent d20c99651c
commit d18dc5afb7
7 files changed
+128 -30

No files matched your search

@@ -9,6 +9,7 @@ import { useRouter } from 'next/navigation'
import { platform } from '@tauri-apps/plugin-os'
import { fetch } from '@tauri-apps/plugin-http'
import { verifySignature } from '@/lib/util'
import Dropdown from '@/components/Dropdown'
interface BaseEntry {
id: number
@@ -165,21 +166,21 @@ export default function BerryDashLeaderboards () {
<div className='flex gap-2'>
{selected == 1 && (
<div className='flex justify-center'>
<select
className='bg-(--col2) border border-(--col4) rounded-md'
<Dropdown
value={selectedBerryOption}
onChange={e => setSelectedBerryOption(Number(e.target.value))}
>
<option value='0'>Normal Berry</option>
<option value='1'>Poison Berry</option>
<option value='2'>Slow Berry</option>
<option value='3'>Ultra Berry</option>
<option value='4'>Speedy Berry</option>
<option value='5'>Coin Berry</option>
<option value='6'>Random Berry</option>
<option value='7'>Anti Berry</option>
<option value='8'>Golden Berry</option>
</select>
options={[
{ label: 'Normal Berry', value: 0 },
{ label: 'Poison Berry', value: 1 },
{ label: 'Slow Berry', value: 2 },
{ label: 'Ultra Berry', value: 3 },
{ label: 'Speedy Berry', value: 4 },
{ label: 'Coin Berry', value: 5 },
{ label: 'Random Berry', value: 6 },
{ label: 'Anti Berry', value: 7 },
{ label: 'Golden Berry', value: 8 }
]}
onChange={e => setSelectedBerryOption(Number(e))}
/>
</div>
)}
<button
+19 -13
View File
@@ -4,6 +4,7 @@ import { Setting } from '@/components/Setting'
import { useGlobal } from '@/providers/GlobalProvider'
import { copyToClipboard } from '@/lib/clipboard'
import { platform } from '@tauri-apps/plugin-os'
import Dropdown from '@/components/Dropdown'
export default function Settings () {
const {
@@ -57,20 +58,25 @@ export default function Settings () {
className='input-field my-1'
hidden={!(platform() == 'linux' && linuxUseWine)}
></input>
<div title='The theme you want the launcher to use.'>
<label className='text-lg'>Theme:</label>
<select
className='ml-2 bg-(--col2) border border-(--col4) rounded-md'
value={theme}
onChange={async e => {
await settings?.set('theme', e.target.value)
}}
<div className='flex flex-row gap-2 items-center'>
<p
title='The theme you want the launcher to use.'
className='text-lg'
>
<option value={'dark'}>Dark</option>
<option value={'red'}>Red</option>
<option value={'blue'}>Blue</option>
<option value={'purple'}>Purple</option>
</select>
Theme:
</p>
<Dropdown
value={theme}
options={[
{ label: 'Dark', value: 'dark' },
{ label: 'Red', value: 'red' },
{ label: 'Blue', value: 'blue' },
{ label: 'Purple', value: 'purple' }
]}
onChange={async val => {
await settings?.set('theme', val)
}}
/>
</div>
</div>
<p
+62
View File
@@ -0,0 +1,62 @@
import { useState, useRef, useEffect } from 'react'
import '@/styles/dropdown.css'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faChevronDown } from '@fortawesome/free-solid-svg-icons'
type Option = {
label: string
value: string | number
}
type Props = {
value: string | number
options: Option[]
onChange: (value: string | number) => void | Promise<void>
}
export default function Dropdown ({ value, options, onChange }: Props) {
const [open, setOpen] = useState(false)
const ref = useRef<HTMLDivElement>(null)
const selected = options.find(o => o.value === value)
useEffect(() => {
const handleClick = (e: MouseEvent) => {
if (!ref.current?.contains(e.target as Node)) {
setOpen(false)
}
}
window.addEventListener('mousedown', handleClick)
return () => window.removeEventListener('mousedown', handleClick)
}, [])
return (
<div ref={ref} className='dropdown'>
<button className='dropdown-btn' onClick={() => setOpen(o => !o)}>
<span>{selected?.label ?? 'Select...'}</span>
<FontAwesomeIcon
icon={faChevronDown}
className={`dropdown-arrow ${open ? 'open' : ''}`}
/>
</button>
{open && (
<div className='dropdown-menu'>
{options.map(option => (
<div
key={option.value}
className={`dropdown-item ${
option.value === value ? 'active' : ''
}`}
onClick={async () => {
await onChange(option.value)
setOpen(false)
}}
>
{option.label}
</div>
))}
</div>
)}
</div>
)
}
+29
View File
@@ -0,0 +1,29 @@
@import 'tailwindcss';
.dropdown {
@apply relative w-40;
}
.dropdown-btn {
@apply w-full flex items-center justify-between px-3 py-1.5 rounded-md cursor-pointer bg-(--col2) hover:bg-(--col3) border border-(--col4) hover:border-(--col5) text-white;
}
.dropdown-arrow {
@apply w-4 h-4 transition-transform stroke-current stroke-2 fill-none;
}
.dropdown-arrow.open {
@apply rotate-180;
}
.dropdown-menu {
@apply absolute z-50 mt-1 w-full rounded-md shadow-lg overflow-hidden bg-(--col2) border border-(--col4) divide-y divide-(--col4);
}
.dropdown-item {
@apply px-3 py-1.5 cursor-pointer transition-colors hover:bg-(--col3);
}
.dropdown-item.active {
@apply bg-(--col3) hover:bg-(--col4);
}