mirror of
https://github.com/R0m1k3/Menu.git
synced 2026-10-11 17:28:28 +02:00
feat: add IconPicker component and utility library for Lucide icon selection and color management
This commit is contained in:
1 parent
485aba96fd
commit
c3d141402f
5 files changed
+272
-66
No files matched your search
@@ -1,9 +1,9 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import Image from 'next/image';
|
||||
import { Globe } from 'lucide-react';
|
||||
import { ICON_MAP, parseIcon } from '@/lib/lucideIcons';
|
||||
import styles from './MenuButton.module.css';
|
||||
|
||||
interface MenuButtonProps {
|
||||
@@ -12,40 +12,18 @@ interface MenuButtonProps {
|
||||
icon?: string | null;
|
||||
}
|
||||
|
||||
function getDomain(url: string): string {
|
||||
try { return new URL(url).hostname; } catch { return url; }
|
||||
}
|
||||
|
||||
/**
|
||||
* MenuButton — displays emoji icon if set, falls back to Google favicon.
|
||||
* MenuButton — renders a Lucide icon (with color) if set,
|
||||
* otherwise falls back to the Globe icon.
|
||||
*/
|
||||
export const MenuButton: React.FC<MenuButtonProps> = ({ name, url, icon }) => {
|
||||
const domain = getDomain(url);
|
||||
const faviconUrl = `https://www.google.com/s2/favicons?domain=${domain}&sz=64`;
|
||||
const [faviconError, setFaviconError] = useState(false);
|
||||
const { name: iconName, color } = parseIcon(icon);
|
||||
const IconComponent = ICON_MAP[iconName] || Globe;
|
||||
|
||||
return (
|
||||
<Link href={url} target="_blank" rel="noopener noreferrer" className={styles.menuButton}>
|
||||
<div className={styles.faviconWrapper}>
|
||||
{icon ? (
|
||||
// Custom emoji icon
|
||||
<span style={{ fontSize: '2.2rem', lineHeight: 1 }}>{icon}</span>
|
||||
) : !faviconError ? (
|
||||
// Auto favicon from Google CDN
|
||||
<Image
|
||||
src={faviconUrl}
|
||||
alt={`${name} favicon`}
|
||||
width={48}
|
||||
height={48}
|
||||
className={styles.favicon}
|
||||
onError={() => setFaviconError(true)}
|
||||
unoptimized
|
||||
/>
|
||||
) : (
|
||||
<div className={styles.faviconFallback}>
|
||||
<Globe size={32} />
|
||||
</div>
|
||||
)}
|
||||
<IconComponent size={44} color={color} strokeWidth={1.6} />
|
||||
</div>
|
||||
<span className={styles.label}>{name}</span>
|
||||
</Link>
|
||||
|
||||
Reference in new issue
Block a user