feat(header): floating module header with cyclic nav and shared search
Replace the full-width top bar with a fixed floating header of glass pills: a fixed-position ModuleName (accent dot + label + prev/next cyclic module stepper) and a shared SearchBar. The header's left edge is anchored as if the nav rail and filter sidebar were both open, so it never shifts on collapse or module change; the right edge leaves a 10% margin. - ModuleName label width is measured live from the reachable modules' titles in the current language, recomputing on a language or account change. - Module names come from a shared moduleLabelKey (the same short labels as the nav rail); NavSidebar and the header now read from one source (lib/modules.ts). - The arrows step cyclically through moduleOrder(me) — dynamic, no hard-coded targets, wrapping at both ends. - Search is hoisted into the SearchBar for feed (YouTube search), plex, channels (including the Discovery tab) and playlists (new); Go button, Enter triggers it. - The Playlists left rail now reaches the top; header clearance via --hdr-h.
This commit is contained in:
@@ -12,7 +12,6 @@ import {
|
||||
Pencil,
|
||||
Plus,
|
||||
RefreshCw,
|
||||
Search,
|
||||
UserMinus,
|
||||
X,
|
||||
} from "lucide-react";
|
||||
@@ -44,6 +43,8 @@ const STATUS_FILTERS: { id: ChannelStatusFilter; labelKey: string }[] = [
|
||||
export default function Channels({
|
||||
canWrite,
|
||||
isAdmin,
|
||||
search,
|
||||
setSearch,
|
||||
onViewChannel,
|
||||
onFilterByTag,
|
||||
onFocusChannel,
|
||||
@@ -58,6 +59,9 @@ export default function Channels({
|
||||
}: {
|
||||
canWrite: boolean;
|
||||
isAdmin: boolean;
|
||||
// The channel-name filter, lifted to App so the shared top SearchBar drives it.
|
||||
search: string;
|
||||
setSearch: (q: string) => void;
|
||||
onViewChannel: (id: string, name: string) => void;
|
||||
onFilterByTag: (tagId: number, name: string) => void;
|
||||
onFocusChannel: (name: string) => void;
|
||||
@@ -190,9 +194,8 @@ export default function Channels({
|
||||
onError: (e) => notifyYouTubeActionError(e, t("channels.notify.fullHistoryFailed"), onOpenWizard),
|
||||
});
|
||||
|
||||
// Channel-name search + tag-chip filtering, applied client-side over the status-filtered list
|
||||
// (prominent controls instead of the DataTable's hidden per-column popovers).
|
||||
const [search, setSearch] = useState("");
|
||||
// Channel-name search (from the shared top SearchBar, via props) + tag-chip filtering, applied
|
||||
// client-side over the status-filtered list.
|
||||
const [tagFilter, setTagFilter] = useState<number[]>([]);
|
||||
// A focus-channel intent (header "without full history" / tag manager) seeds the search box.
|
||||
useEffect(() => {
|
||||
@@ -399,7 +402,12 @@ export default function Channels({
|
||||
return (
|
||||
<>
|
||||
{tabs}
|
||||
<ChannelDiscovery canWrite={canWrite} onOpenWizard={onOpenWizard} onViewChannel={onViewChannel} />
|
||||
<ChannelDiscovery
|
||||
canWrite={canWrite}
|
||||
search={search}
|
||||
onOpenWizard={onOpenWizard}
|
||||
onViewChannel={onViewChannel}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -482,25 +490,7 @@ export default function Channels({
|
||||
/>
|
||||
</p>
|
||||
|
||||
{/* Channel-name search */}
|
||||
<div className="relative mb-3 max-w-sm">
|
||||
<Search className="absolute left-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-muted pointer-events-none" />
|
||||
<input
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
placeholder={t("channels.searchPlaceholder")}
|
||||
className="w-full bg-card border border-border rounded-lg pl-8 pr-8 py-2 text-sm outline-none focus:border-accent"
|
||||
/>
|
||||
{search && (
|
||||
<button
|
||||
onClick={() => setSearch("")}
|
||||
aria-label={t("common.cancel")}
|
||||
className="absolute right-2 top-1/2 -translate-y-1/2 text-muted hover:text-fg"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{/* The channel-name search now lives in the shared top SearchBar (driven via props). */}
|
||||
|
||||
{/* Your tags — click a chip to filter the table by it (add/rename/delete live in the manager). */}
|
||||
<div className="flex flex-wrap items-center gap-1.5 mb-4">
|
||||
|
||||
Reference in New Issue
Block a user