refactor(ui): consolidate dropdowns into one shared Dropdown

ThemedDropdown, Toolbar''s local SortDropdown, and FolderScopeDropdown
were three hand-rolled implementations of the same select pattern. They
are replaced by a single generic Dropdown (src/components/menu/) built
on MenuPanel/MenuItem, with solid/ghost/compact trigger variants and
Object.is value comparison so number|null folder scopes work alongside
string unions. Call sites drop their `value as X` casts.

MenuItem gains an `active` state plus stable menu-panel/menu-item class
hooks, and the subtle-light CSS that previously dressed only the folder
scope dropdown (feature-scope-*) now themes every menu surface --
dropdowns, context menus, and submenus alike.
This commit is contained in:
2026-07-04 07:22:22 +01:00
parent 54016df830
commit 053a2bd846
11 changed files with 243 additions and 297 deletions
+5 -5
View File
@@ -2,8 +2,7 @@ import { useEffect, useMemo, useRef, useState } from "react";
import { Reorder, useDragControls } from "framer-motion";
import { open } from "@tauri-apps/plugin-dialog";
import { useGalleryStore, Folder, Album, IndexProgress } from "../store";
import { ThemedDropdown } from "./ThemedDropdown";
import { ContextMenu, MenuItem, MenuSeparator } from "./menu";
import { ContextMenu, Dropdown, MenuItem, MenuSeparator } from "./menu";
import { mediaSrc } from "../lib/mediaSrc";
import { Tooltip } from "./Tooltip";
@@ -788,11 +787,12 @@ export function Sidebar() {
{folders.length > 0 && (
<div className="flex items-center justify-between gap-2 px-5 pt-3 pb-1">
<span className="text-[10px] font-semibold uppercase tracking-[0.15em] text-gray-600">Libraries</span>
<ThemedDropdown
<Dropdown
value={librarySort}
onChange={(value) => setLibrarySort(value as LibrarySort)}
onChange={setLibrarySort}
ariaLabel="Library order"
compact
trigger="compact"
panelClassName="min-w-0"
options={[
{ value: "az", label: "A-Z" },
{ value: "za", label: "Z-A" },