Files
core/src/features/admin/devkit/IconsPage.client.js
T

74 lines
2.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { useState, useMemo } from 'react';
import * as Icons from '@zen/core/shared/icons';
import { useToast } from '@zen/core/toast';
import AdminHeader from '../components/AdminHeader.js';
const ALL_ICONS = Object.entries(Icons);
export default function IconsPage() {
const [query, setQuery] = useState('');
const toast = useToast();
const filtered = useMemo(() => {
if (!query.trim()) return ALL_ICONS;
const q = query.trim().toLowerCase();
return ALL_ICONS.filter(([name]) => name.toLowerCase().includes(q));
}, [query]);
const handleCopy = (name) => {
navigator.clipboard.writeText(`<${name} className="w-5 h-5" />`);
toast.success(`${name} copié`);
};
return (
<div className="flex flex-col gap-6">
<AdminHeader
title="Icônes"
description={`${ALL_ICONS.length} icônes disponibles`}
/>
<div className="relative">
<input
type="text"
value={query}
onChange={e => setQuery(e.target.value)}
placeholder="Rechercher une icône..."
className="w-full rounded-lg border border-neutral-200 dark:border-neutral-800 bg-white dark:bg-neutral-900 px-4 py-2.5 text-sm text-neutral-900 dark:text-white placeholder-neutral-400 dark:placeholder-neutral-500 focus:outline-none focus:ring-2 focus:ring-blue-700/40"
/>
{query && (
<button
onClick={() => setQuery('')}
className="absolute right-3 top-1/2 -translate-y-1/2 text-neutral-400 hover:text-neutral-600 dark:hover:text-neutral-200 text-lg leading-none"
>
×
</button>
)}
</div>
{filtered.length === 0 ? (
<p className="text-sm text-neutral-500 dark:text-neutral-400 text-center py-12">
Aucune icône trouvée pour &ldquo;{query}&rdquo;
</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">
{filtered.map(([name, IconComponent]) => (
<button
key={name}
onClick={() => handleCopy(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"
>
<IconComponent className="w-7 h-7 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">
{name.replace('Icon', '')}
</span>
</button>
))}
</div>
)}
</div>
);
}