feat: collapse sidebar categories with show more/less toggle

Show only the first 4 categories by default with a "N more" button
to expand the full list. Reduces sidebar clutter when many categories
exist.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-02-19 00:31:18 -05:00
parent c05e22dc6d
commit 086e959bad

View File

@@ -1,3 +1,5 @@
import { useState } from 'react'
import { ChevronDown, ChevronUp } from 'lucide-react'
import { cn } from '@/lib/utils'
interface CategoryItem {
@@ -13,16 +15,23 @@ interface CategoryListProps {
onSelect: (id: string | null) => void
}
const VISIBLE_COUNT = 4
export function CategoryList({ categories, activeId, onSelect }: CategoryListProps) {
const [expanded, setExpanded] = useState(false)
if (categories.length === 0) return null
const hasMore = categories.length > VISIBLE_COUNT
const visible = expanded ? categories : categories.slice(0, VISIBLE_COUNT)
return (
<div className="px-3 py-2">
<p className="mb-2 px-3 font-heading text-[0.6875rem] font-bold uppercase tracking-[0.04em] text-muted-foreground">
Categories
</p>
<div className="space-y-0.5">
{categories.map(cat => (
{visible.map(cat => (
<button
key={cat.id}
onClick={() => onSelect(activeId === cat.id ? null : cat.id)}
@@ -41,6 +50,24 @@ export function CategoryList({ categories, activeId, onSelect }: CategoryListPro
<span className="font-label text-[0.6875rem] text-[hsl(var(--text-dimmed))]">{cat.count}</span>
</button>
))}
{hasMore && (
<button
onClick={() => setExpanded(v => !v)}
className="flex w-full items-center gap-2.5 rounded-lg px-3 py-1.5 text-[0.8125rem] text-muted-foreground hover:bg-[hsl(var(--sidebar-hover))] hover:text-foreground transition-colors"
>
{expanded ? (
<>
<ChevronUp className="h-3.5 w-3.5" />
<span>Show less</span>
</>
) : (
<>
<ChevronDown className="h-3.5 w-3.5" />
<span>{categories.length - VISIBLE_COUNT} more</span>
</>
)}
</button>
)}
</div>
</div>
)