import { useState, type ReactNode } from "react"; import { ArrowDown, ArrowUp, Check, ChevronDown } from "lucide-react"; import { pickSort, type SortOption, type SortState } from "../lib/columnSort"; import { PopoverItem, PopoverSurface, useAnchoredPopover } from "./AnchoredPopover"; // The one sort control for every content surface (YT feed, Plex library, channel manager + its card // view, channel discovery, playlists): a labeled dropdown pill matching FilterSelect — `Label: key ↓ ▾` // — that opens a listbox of `SortOption`s with an asc/desc segment in the panel footer. Two-dimensional // (key + direction) unlike FilterSelect, so it stays its own component. Driven by the shared `SortState`. // `defaultLabel` opts a view into a "no sort" choice (tables); omit it for always-sorted views // (feed/Plex). `trailing` is an adornment slot (the feed's reshuffle, playlists' dirty-first toggle) // rendered in the footer beside the direction segment. // // Direction lives in the footer, not on the trigger, on purpose: the trigger stays a single plain // {/* One exclusive choice of sort key (radios), scoped by a group so AT announces which is checked — the surface is a menu (see the mode above), never a listbox with orphaned options. */}
{defaultLabel !== undefined && ( { onChange(null); setOpen(false); // "no sort" is a final choice — nothing left to direct }} label={defaultLabel} className={`flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm transition ${ active === null ? "text-fg" : "text-muted" }`} > {defaultLabel} )} {options.map((o) => { const on = active?.key === o.key; return ( onChange(pickSort(options, active, o.key))} // keep open to set direction label={o.label} className={`flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm transition ${ on ? "text-fg" : "text-muted" }`} > {o.label} ); })}
{((showArrow && active) || trailing) && (
{showArrow && active && (
)} {trailing}
)}
); }