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:
@@ -1,3 +1,5 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
|
import { ChevronDown, ChevronUp } from 'lucide-react'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
interface CategoryItem {
|
interface CategoryItem {
|
||||||
@@ -13,16 +15,23 @@ interface CategoryListProps {
|
|||||||
onSelect: (id: string | null) => void
|
onSelect: (id: string | null) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const VISIBLE_COUNT = 4
|
||||||
|
|
||||||
export function CategoryList({ categories, activeId, onSelect }: CategoryListProps) {
|
export function CategoryList({ categories, activeId, onSelect }: CategoryListProps) {
|
||||||
|
const [expanded, setExpanded] = useState(false)
|
||||||
|
|
||||||
if (categories.length === 0) return null
|
if (categories.length === 0) return null
|
||||||
|
|
||||||
|
const hasMore = categories.length > VISIBLE_COUNT
|
||||||
|
const visible = expanded ? categories : categories.slice(0, VISIBLE_COUNT)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="px-3 py-2">
|
<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">
|
<p className="mb-2 px-3 font-heading text-[0.6875rem] font-bold uppercase tracking-[0.04em] text-muted-foreground">
|
||||||
Categories
|
Categories
|
||||||
</p>
|
</p>
|
||||||
<div className="space-y-0.5">
|
<div className="space-y-0.5">
|
||||||
{categories.map(cat => (
|
{visible.map(cat => (
|
||||||
<button
|
<button
|
||||||
key={cat.id}
|
key={cat.id}
|
||||||
onClick={() => onSelect(activeId === cat.id ? null : 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>
|
<span className="font-label text-[0.6875rem] text-[hsl(var(--text-dimmed))]">{cat.count}</span>
|
||||||
</button>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user