refactor(admin): improve icons page sidebar layout and category display
- store first icon reference alongside count in category map - add hasSidebar flag to conditionally adjust layout classes - make sidebar full-width on mobile with horizontal scrolling category list - reduce icon size and spacing to accommodate sidebar presence - adjust grid columns breakpoints when sidebar is visible
This commit is contained in:
@@ -16,7 +16,9 @@ export default function IconsPage() {
|
|||||||
const map = new Map();
|
const map = new Map();
|
||||||
for (const [, Icon] of ALL_ICONS) {
|
for (const [, Icon] of ALL_ICONS) {
|
||||||
const cat = Icon.category;
|
const cat = Icon.category;
|
||||||
if (cat) map.set(cat, (map.get(cat) ?? 0) + 1);
|
if (!cat) continue;
|
||||||
|
if (!map.has(cat)) map.set(cat, { count: 0, FirstIcon: Icon });
|
||||||
|
map.get(cat).count += 1;
|
||||||
}
|
}
|
||||||
return Array.from(map.entries()).sort(([a], [b]) => a.localeCompare(b));
|
return Array.from(map.entries()).sort(([a], [b]) => a.localeCompare(b));
|
||||||
}, []);
|
}, []);
|
||||||
@@ -37,6 +39,8 @@ export default function IconsPage() {
|
|||||||
toast.success(`${name} copié`);
|
toast.success(`${name} copié`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const hasSidebar = categories.length > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-6">
|
<div className="flex flex-col gap-6">
|
||||||
<AdminHeader
|
<AdminHeader
|
||||||
@@ -44,7 +48,7 @@ export default function IconsPage() {
|
|||||||
description={`${ALL_ICONS.length} icônes disponibles`}
|
description={`${ALL_ICONS.length} icônes disponibles`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex gap-4 items-start">
|
<div className={`flex gap-4 items-start ${hasSidebar ? 'flex-col sm:flex-row' : ''}`}>
|
||||||
<div className="flex-1 min-w-0 flex flex-col gap-6">
|
<div className="flex-1 min-w-0 flex flex-col gap-6">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<input
|
<input
|
||||||
@@ -69,16 +73,20 @@ export default function IconsPage() {
|
|||||||
Aucune icône trouvée pour “{query}”
|
Aucune icône trouvée pour “{query}”
|
||||||
</p>
|
</p>
|
||||||
) : (
|
) : (
|
||||||
<div className="grid grid-cols-4 sm:grid-cols-6 md:grid-cols-8 lg:grid-cols-10 xl:grid-cols-12 2xl:grid-cols-[repeat(16,minmax(0,1fr))] gap-2">
|
<div className={`grid gap-2 ${
|
||||||
|
hasSidebar
|
||||||
|
? 'grid-cols-4 sm:grid-cols-4 md:grid-cols-6 lg:grid-cols-8 xl:grid-cols-10 2xl:grid-cols-[repeat(13,minmax(0,1fr))]'
|
||||||
|
: 'grid-cols-4 sm:grid-cols-6 md:grid-cols-8 lg:grid-cols-10 xl:grid-cols-12 2xl:grid-cols-[repeat(16,minmax(0,1fr))]'
|
||||||
|
}`}>
|
||||||
{filtered.map(([name, IconComponent]) => (
|
{filtered.map(([name, IconComponent]) => (
|
||||||
<button
|
<button
|
||||||
key={name}
|
key={name}
|
||||||
onClick={() => handleCopy(name)}
|
onClick={() => handleCopy(name)}
|
||||||
title={name}
|
title={name}
|
||||||
className="aspect-square flex flex-col items-center justify-center gap-2 rounded-lg border border-neutral-200 dark:border-neutral-800 bg-neutral-100 dark:bg-neutral-900 hover:border-blue-500 dark:hover:border-blue-500 transition-colors duration-100 group cursor-pointer p-2"
|
className="aspect-square flex flex-col items-center justify-center gap-1.5 rounded-lg border border-neutral-200 dark:border-neutral-800 bg-neutral-100 dark:bg-neutral-900 hover:border-blue-500 dark:hover:border-blue-500 transition-colors duration-100 group cursor-pointer p-2"
|
||||||
>
|
>
|
||||||
<IconComponent className="w-7 h-7 text-black dark:text-white" />
|
<IconComponent className="w-6 h-6 text-black dark:text-white" />
|
||||||
<span className="text-[9px] text-neutral-500 dark:text-neutral-400 leading-tight text-center break-all line-clamp-2 group-hover:text-neutral-600 dark:group-hover:text-neutral-300 w-full px-1">
|
<span className="text-[9px] text-neutral-500 dark:text-neutral-400 leading-tight text-center break-all line-clamp-2 group-hover:text-neutral-600 dark:group-hover:text-neutral-300 w-full px-0.5">
|
||||||
{name.replace('Icon', '')}
|
{name.replace('Icon', '')}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
@@ -87,39 +95,40 @@ export default function IconsPage() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{categories.length > 0 && (
|
{hasSidebar && (
|
||||||
<div className="w-[185px] shrink-0 sticky top-4 rounded-lg border border-neutral-200 dark:border-neutral-800 bg-white dark:bg-neutral-900 overflow-hidden">
|
<div className="w-full sm:w-[200px] sm:shrink-0 sm:sticky sm:top-4 rounded-lg border border-neutral-200 dark:border-neutral-800 bg-white dark:bg-neutral-900 overflow-hidden order-first sm:order-none">
|
||||||
<div className="px-3 py-2.5 border-b border-neutral-200 dark:border-neutral-800">
|
<div className="px-3 py-2.5 border-b border-neutral-200 dark:border-neutral-800">
|
||||||
<span className="text-xs font-medium text-neutral-500 dark:text-neutral-400 uppercase tracking-wide">Catégories</span>
|
<span className="text-xs font-medium text-neutral-500 dark:text-neutral-400 uppercase tracking-wide">Catégories</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="py-1">
|
<div className="py-1 flex sm:flex-col flex-row flex-wrap sm:flex-nowrap gap-0">
|
||||||
<button
|
<button
|
||||||
onClick={() => setSelectedCategory(null)}
|
onClick={() => setSelectedCategory(null)}
|
||||||
className={`w-full flex items-center justify-between px-3 py-1.5 text-sm rounded-md mx-1 transition-colors ${
|
className={`flex items-center justify-between px-3 py-1.5 text-sm rounded-md m-1 sm:mx-1 sm:my-0 sm:w-[calc(100%-8px)] transition-colors ${
|
||||||
selectedCategory === null
|
selectedCategory === null
|
||||||
? 'bg-blue-50 dark:bg-blue-950 text-blue-700 dark:text-blue-300 font-medium'
|
? 'bg-neutral-100 dark:bg-neutral-800 text-neutral-900 dark:text-white'
|
||||||
: 'text-neutral-700 dark:text-neutral-300 hover:bg-neutral-100 dark:hover:bg-neutral-800'
|
: 'text-neutral-600 dark:text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-800 hover:text-neutral-900 dark:hover:text-white'
|
||||||
}`}
|
}`}
|
||||||
style={{ width: 'calc(100% - 8px)' }}
|
|
||||||
>
|
>
|
||||||
<span>Tout</span>
|
<span className="truncate">Tout</span>
|
||||||
<span className={`text-xs tabular-nums ${selectedCategory === null ? 'text-blue-500 dark:text-blue-400' : 'text-neutral-400 dark:text-neutral-500'}`}>
|
<span className="text-xs tabular-nums shrink-0 ml-2 text-neutral-400 dark:text-neutral-500">
|
||||||
{ALL_ICONS.length}
|
{ALL_ICONS.length}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
{categories.map(([cat, count]) => (
|
{categories.map(([cat, { count, FirstIcon }]) => (
|
||||||
<button
|
<button
|
||||||
key={cat}
|
key={cat}
|
||||||
onClick={() => setSelectedCategory(cat)}
|
onClick={() => setSelectedCategory(cat)}
|
||||||
className={`w-full flex items-center justify-between px-3 py-1.5 text-sm rounded-md mx-1 transition-colors ${
|
className={`flex items-center justify-between px-3 py-1.5 text-sm rounded-md m-1 sm:mx-1 sm:my-0 sm:w-[calc(100%-8px)] transition-colors ${
|
||||||
selectedCategory === cat
|
selectedCategory === cat
|
||||||
? 'bg-blue-50 dark:bg-blue-950 text-blue-700 dark:text-blue-300 font-medium'
|
? 'bg-neutral-100 dark:bg-neutral-800 text-neutral-900 dark:text-white'
|
||||||
: 'text-neutral-700 dark:text-neutral-300 hover:bg-neutral-100 dark:hover:bg-neutral-800'
|
: 'text-neutral-600 dark:text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-800 hover:text-neutral-900 dark:hover:text-white'
|
||||||
}`}
|
}`}
|
||||||
style={{ width: 'calc(100% - 8px)' }}
|
|
||||||
>
|
>
|
||||||
<span className="truncate text-left">{cat}</span>
|
<span className="flex items-center gap-2 min-w-0">
|
||||||
<span className={`text-xs tabular-nums shrink-0 ml-1 ${selectedCategory === cat ? 'text-blue-500 dark:text-blue-400' : 'text-neutral-400 dark:text-neutral-500'}`}>
|
<FirstIcon className="w-4 h-4 shrink-0 text-neutral-500 dark:text-neutral-400" />
|
||||||
|
<span className="truncate">{cat}</span>
|
||||||
|
</span>
|
||||||
|
<span className="text-xs tabular-nums shrink-0 ml-2 text-neutral-400 dark:text-neutral-500">
|
||||||
{count}
|
{count}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user