feat: implement MenuButton component and home page layout with global glassmorphism styles

This commit is contained in:
Michael committed 2026-04-10 10:47:02 +02:00
1 parent 5ff4784596
commit ca99378348
6 files changed
+198 -302

No files matched your search

+20 -34
View File
@@ -3,8 +3,7 @@
import React, { useState } from 'react';
import Link from 'next/link';
import Image from 'next/image';
import { ArrowUpRight, Globe } from 'lucide-react';
import { GlassCard } from './GlassCard';
import { Globe } from 'lucide-react';
import styles from './MenuButton.module.css';
interface MenuButtonProps {
@@ -12,22 +11,14 @@ interface MenuButtonProps {
url: string;
}
/**
* Extract base domain from URL for favicon fetch.
*/
function getDomain(url: string): string {
try {
const { hostname } = new URL(url);
return hostname;
return new URL(url).hostname;
} catch {
return url;
}
}
/**
* MenuButton component displaying a favicon and app name.
* Favicons are fetched from Google's favicon CDN.
*/
export const MenuButton: React.FC<MenuButtonProps> = ({ name, url }) => {
const domain = getDomain(url);
const faviconUrl = `https://www.google.com/s2/favicons?domain=${domain}&sz=64`;
@@ -35,29 +26,24 @@ export const MenuButton: React.FC<MenuButtonProps> = ({ name, url }) => {
return (
<Link href={url} target="_blank" rel="noopener noreferrer" className={styles.menuButton}>
<GlassCard hoverable className={styles.menuButton}>
<ArrowUpRight size={16} className={styles.arrowIcon} />
<div className={styles.faviconWrapper}>
{!faviconError ? (
<Image
src={faviconUrl}
alt={`${name} icon`}
width={40}
height={40}
className={styles.favicon}
onError={() => setFaviconError(true)}
unoptimized
/>
) : (
<div className={styles.faviconFallback}>
<Globe size={28} />
</div>
)}
</div>
<span className={styles.label}>{name}</span>
</GlassCard>
<div className={styles.faviconWrapper}>
{!faviconError ? (
<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>
)}
</div>
<span className={styles.label}>{name}</span>
</Link>
);
};