make FilterPanel hideable and responsive across all library views
Adds a toggle button to show/hide the filter panel in Movies, Games, Mixed, and TV views. On mobile the layout stacks vertically (filter above content); on md+ it returns to the side-by-side layout. The toggle button highlights when filters are active so hidden filters remain discoverable. Also fixes a layout bug where items-start on the flex-col container caused MixedView thumbnails to collapse on narrow screens. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,7 @@ export default function TvView({ libraryId }: Props) {
|
||||
const [selectedTagIds, setSelectedTagIds] = useState<Set<string>>(new Set())
|
||||
const [assignments, setAssignments] = useState<Record<string, string[]>>({})
|
||||
const [filterRefreshKey, setFilterRefreshKey] = useState(0)
|
||||
const [showFilters, setShowFilters] = useState(true)
|
||||
const [menuOpen, setMenuOpen] = useState(false)
|
||||
const [confirming, setConfirming] = useState(false)
|
||||
const [deleting, setDeleting] = useState(false)
|
||||
@@ -123,6 +124,8 @@ export default function TvView({ libraryId }: Props) {
|
||||
.catch(() => setDeleting(false))
|
||||
}
|
||||
|
||||
const filtersActive = search !== '' || selectedTagIds.size > 0
|
||||
|
||||
const filteredSeries = series.filter((s) => {
|
||||
if (search && !s.title.toLowerCase().includes(search.toLowerCase())) return false
|
||||
if (selectedTagIds.size > 0) {
|
||||
@@ -179,19 +182,36 @@ export default function TvView({ libraryId }: Props) {
|
||||
</div>
|
||||
|
||||
{view === 'series' && (
|
||||
<div className="flex gap-6 items-start">
|
||||
<div className="w-52 flex-shrink-0">
|
||||
<FilterPanel
|
||||
libraryId={libraryId}
|
||||
assignments={assignments}
|
||||
search={search}
|
||||
onSearchChange={setSearch}
|
||||
selectedTagIds={selectedTagIds}
|
||||
onTagToggle={toggleTag}
|
||||
refreshKey={filterRefreshKey}
|
||||
/>
|
||||
<>
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<button
|
||||
onClick={() => setShowFilters((v) => !v)}
|
||||
className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium transition-colors"
|
||||
style={{
|
||||
backgroundColor: (showFilters || filtersActive) ? 'var(--accent)' : 'var(--surface)',
|
||||
color: (showFilters || filtersActive) ? '#fff' : 'var(--text-secondary)',
|
||||
border: '1px solid var(--border)',
|
||||
}}
|
||||
aria-label={showFilters ? 'Hide filters' : 'Show filters'}
|
||||
>
|
||||
Filters{filtersActive ? ' ●' : ''}
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex flex-col md:flex-row gap-6 md:items-start">
|
||||
{showFilters && (
|
||||
<div className="w-full md:w-52 md:flex-shrink-0">
|
||||
<FilterPanel
|
||||
libraryId={libraryId}
|
||||
assignments={assignments}
|
||||
search={search}
|
||||
onSearchChange={setSearch}
|
||||
selectedTagIds={selectedTagIds}
|
||||
onTagToggle={toggleTag}
|
||||
refreshKey={filterRefreshKey}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex-1 min-w-0">
|
||||
{loading ? (
|
||||
<SeriesLoadingGrid />
|
||||
) : error ? (
|
||||
@@ -238,8 +258,9 @@ export default function TvView({ libraryId }: Props) {
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{view === 'seasons' && selectedSeries && (
|
||||
|
||||
Reference in New Issue
Block a user