Redesign: richer visual language inspired by Magic UI

- Body: radial gradient orbs (teal + green) + dot grid overlay + grain
- Header: dark mesh gradient, shimmer logo animation, animated gradient
  tagline, frosted glass lang-switcher pill
- CategorySection: glow-ring emoji badge, gradient top line, frosted
  glass card container, teal/gold decorative divider
- MenuItemRow: gradient emoji circle, magic-card CSS hover spotlight,
  price pill with green gradient border
- BottomTabBar: blur/glass tabbar, active emoji glow + scale + pill bg
- Page: welcome strip with teal gradient border, hero fade from header

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mstfyldz
2026-06-03 02:41:37 +03:00
co-authored by Claude Sonnet 4.6
parent 718e0a6228
commit bc8bd747ff
6 changed files with 414 additions and 108 deletions
+42 -17
View File
@@ -22,9 +22,7 @@ export default function BottomTabBar({ categories, lang }: Props) {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setActiveId(cat.id)
}
if (entry.isIntersecting) setActiveId(cat.id)
})
},
{ rootMargin: '-20% 0px -75% 0px', threshold: 0 }
@@ -34,35 +32,62 @@ export default function BottomTabBar({ categories, lang }: Props) {
observers.push(observer)
})
return () => {
observers.forEach((obs) => obs.disconnect())
}
return () => observers.forEach((o) => o.disconnect())
}, [categories])
return (
<nav
className="fixed bottom-0 left-0 right-0 z-40 bg-coffee border-t border-coffee-light"
className="tabbar-glass fixed bottom-0 left-0 right-0 z-40"
style={{ height: 'var(--tabbar-h)' }}
>
<div className="flex items-start justify-around pt-2.5 h-full">
<div className="flex items-start justify-around pt-2 h-full px-1">
{categories.map((cat) => {
const isActive = activeId === cat.id
return (
<a
key={cat.id}
href={`#${cat.id}`}
className={`tab-item flex flex-col items-center gap-0.5 flex-1 py-0.5 ${
isActive ? 'text-teal' : 'text-cream/35'
}`}
className="tab-item flex flex-col items-center gap-0.5 flex-1 py-1 rounded-lg relative"
>
<span className="text-lg leading-none">{cat.emoji}</span>
<span className="font-body text-[0.55rem] font-medium leading-none tracking-wide text-center px-0.5 truncate w-full text-center">
{/* Active pill background */}
{isActive && (
<span
className="tab-pill absolute inset-x-1 inset-y-0"
aria-hidden="true"
/>
)}
{/* Emoji */}
<span
className="relative text-lg leading-none transition-transform duration-200"
style={{
filter: isActive
? 'drop-shadow(0 0 6px rgba(74,175,168,0.60))'
: 'none',
transform: isActive ? 'scale(1.15)' : 'scale(1)',
}}
>
{cat.emoji}
</span>
{/* Label */}
<span
className="relative font-body font-medium leading-none tracking-wide text-center truncate w-full text-center transition-colors duration-200"
style={{
fontSize: '0.5rem',
color: isActive ? '#4AAFA8' : 'rgba(245,240,232,0.32)',
}}
>
{cat.label[l]}
</span>
<div
className="tab-active-dot"
style={{ opacity: isActive ? 1 : 0 }}
/>
{/* Active dot */}
{isActive && (
<span
className="relative w-1 h-1 rounded-full bg-teal"
aria-hidden="true"
/>
)}
</a>
)
})}
+94 -20
View File
@@ -9,29 +9,103 @@ type Props = {
export default function CategorySection({ category, lang, currency }: Props) {
const l = lang as 'tr' | 'en'
return (
<section id={category.id} className="category-section px-4 pt-8 pb-2">
{/* Category heading */}
<div className="flex items-center gap-2.5 mb-4">
<span className="text-xl">{category.emoji}</span>
<h2 className="font-display text-coffee text-lg font-semibold italic">
{category.label[l]}
</h2>
{/* Decorative line */}
<div className="flex-1 h-px bg-beige-dark" />
<section id={category.id} className="category-section category-reveal px-4 pt-9 pb-1">
{/* Category header */}
<div className="mb-4">
<div className="flex items-center gap-3 mb-2">
{/* Emoji badge with gradient ring */}
<div className="relative flex-shrink-0">
{/* Outer glow ring */}
<div
className="absolute inset-0 rounded-2xl blur-sm opacity-60"
style={{
background: 'linear-gradient(135deg, #4AAFA8, #5C8A5C)',
transform: 'scale(1.15)',
}}
/>
<div
className="relative w-11 h-11 rounded-2xl flex items-center justify-center text-xl"
style={{
background: 'linear-gradient(135deg, rgba(74,175,168,0.18), rgba(92,138,92,0.12))',
border: '1px solid rgba(74,175,168,0.30)',
}}
>
{category.emoji}
</div>
</div>
{/* Title */}
<div className="flex-1 min-w-0">
<h2
className="font-display font-semibold italic text-coffee leading-tight"
style={{ fontSize: '1.2rem' }}
>
{category.label[l]}
</h2>
</div>
{/* Item count badge */}
<span
className="flex-shrink-0 font-body text-[0.6rem] font-semibold tracking-widest uppercase rounded-full px-2.5 py-0.5"
style={{
color: '#8A7265',
background: 'rgba(61,43,31,0.07)',
border: '1px solid rgba(61,43,31,0.10)',
}}
>
{category.items.length}
</span>
</div>
{/* Decorative divider */}
<div className="flex items-center gap-2 ml-1">
<div className="w-1.5 h-1.5 rounded-full bg-teal opacity-70" />
<div
className="flex-1 h-px"
style={{
background:
'linear-gradient(90deg, rgba(74,175,168,0.40) 0%, rgba(212,200,176,0.40) 60%, transparent 100%)',
}}
/>
<div className="w-1 h-1 rounded-full bg-gold opacity-50" />
</div>
</div>
{/* Items */}
<div>
{category.items.map((item, i) => (
<MenuItemRow
key={item.id}
item={item}
lang={lang}
currency={currency}
index={i}
/>
))}
{/* Items card */}
<div
className="rounded-2xl overflow-hidden"
style={{
background: 'rgba(253,250,245,0.72)',
border: '1px solid rgba(212,200,176,0.60)',
backdropFilter: 'blur(8px)',
WebkitBackdropFilter: 'blur(8px)',
boxShadow:
'0 2px 16px rgba(61,43,31,0.06), 0 1px 3px rgba(61,43,31,0.04)',
}}
>
{/* Thin top gradient line */}
<div
className="h-px w-full"
style={{
background:
'linear-gradient(90deg, transparent, rgba(74,175,168,0.35), transparent)',
}}
/>
<div className="px-4 pb-1 pt-0.5">
{category.items.map((item, i) => (
<MenuItemRow
key={item.id}
item={item}
lang={lang}
currency={currency}
index={i}
isLast={i === category.items.length - 1}
/>
))}
</div>
</div>
</section>
)
+59 -15
View File
@@ -8,34 +8,78 @@ type Dict = {
export default function Header({ dict }: { dict: Dict }) {
return (
<header
className="fixed top-0 left-0 right-0 z-40 bg-coffee"
className="fixed top-0 left-0 right-0 z-40"
style={{ height: 'var(--header-h)' }}
>
{/* Thin teal accent line at bottom */}
<div className="absolute bottom-0 left-0 right-0 h-px bg-teal opacity-40" />
{/* Background with mesh gradient */}
<div
className="absolute inset-0"
style={{
background:
'linear-gradient(160deg, #1F140A 0%, #2E1C10 50%, #3D2B1F 100%)',
}}
/>
<div className="flex items-center justify-between h-full px-5">
{/* Logo */}
<div className="flex flex-col leading-none">
<span className="font-display text-cream text-xl font-semibold tracking-[0.18em] uppercase">
{/* Subtle noise texture on header */}
<div
className="absolute inset-0 opacity-[0.04]"
style={{
backgroundImage:
"url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)'/%3E%3C/svg%3E\")",
}}
/>
{/* Animated gradient accent line at bottom */}
<div className="header-line absolute bottom-0 left-0 right-0 h-[1.5px]" />
<div className="relative flex items-center justify-between h-full px-5">
{/* Logo block */}
<div className="flex flex-col leading-none gap-0.5">
{/* KOZMOS with shimmer */}
<span
className="logo-shimmer font-display font-semibold tracking-[0.2em] uppercase"
style={{ fontSize: '1.25rem' }}
>
KOZMOS
</span>
<span className="font-body text-teal text-[0.6rem] font-medium tracking-[0.22em] uppercase mt-0.5">
{dict.header.tagline}
</span>
{/* Tagline with gradient */}
<div className="flex items-center gap-1.5">
<span
className="font-body font-medium tracking-[0.28em] uppercase"
style={{
fontSize: '0.55rem',
background: 'linear-gradient(90deg, #4AAFA8, #C8A850, #5C8A5C)',
backgroundClip: 'text',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
}}
>
{dict.header.tagline}
</span>
</div>
</div>
{/* Language switcher */}
{/* Language switcher pill */}
<Link
href={dict.langSwitch.otherHref}
className="flex items-center gap-1.5 group"
className="group relative flex items-center gap-1 px-3 py-1.5 rounded-full overflow-hidden"
style={{
background: 'rgba(74,175,168,0.10)',
border: '1px solid rgba(74,175,168,0.22)',
}}
aria-label={`Switch to ${dict.langSwitch.other}`}
>
<span className="font-body text-xs font-semibold text-cream/40 tracking-wider">
{/* Hover glow */}
<span
className="absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity duration-300"
style={{ background: 'rgba(74,175,168,0.15)' }}
/>
<span className="relative font-body text-[0.65rem] font-semibold tracking-widest text-white/35">
{dict.langSwitch.current}
</span>
<span className="font-body text-xs text-cream/20">·</span>
<span className="font-body text-xs font-semibold text-teal tracking-wider group-hover:text-cream transition-colors duration-200">
<span className="relative font-body text-[0.55rem] text-white/20">·</span>
<span className="relative font-body text-[0.65rem] font-semibold tracking-widest text-teal group-hover:text-white transition-colors duration-200">
{dict.langSwitch.other}
</span>
</Link>
+26 -8
View File
@@ -5,32 +5,50 @@ type Props = {
lang: string
currency: string
index: number
isLast?: boolean
}
export default function MenuItemRow({ item, lang, currency, index }: Props) {
export default function MenuItemRow({ item, lang, currency, index, isLast }: Props) {
const l = lang as 'tr' | 'en'
return (
<div
className="menu-item-row flex items-center gap-3.5 py-3.5 border-b border-dashed border-beige last:border-0"
className={`menu-item-row flex items-center gap-3.5 py-3.5 rounded-xl px-2 -mx-2 ${
!isLast ? 'border-b border-dashed border-beige' : ''
}`}
style={{ '--item-index': index } as React.CSSProperties}
>
{/* Emoji circle */}
<div className="w-10 h-10 rounded-full bg-beige flex items-center justify-center flex-shrink-0 text-lg">
{/* Emoji circle with gradient */}
<div
className="w-11 h-11 rounded-xl flex items-center justify-center flex-shrink-0 text-[1.2rem]"
style={{
background:
'linear-gradient(135deg, #F0E8D8 0%, #E8DCC8 100%)',
border: '1px solid rgba(212,200,176,0.80)',
boxShadow: 'inset 0 1px 2px rgba(255,255,255,0.8)',
}}
>
{item.emoji}
</div>
{/* Text */}
<div className="flex-1 min-w-0">
<p className="font-display text-coffee text-sm font-semibold leading-snug">
<p
className="font-display text-coffee font-semibold leading-snug"
style={{ fontSize: '0.9rem' }}
>
{item.name[l]}
</p>
<p className="font-body text-muted text-xs leading-relaxed mt-0.5 line-clamp-2">
<p
className="font-body text-muted leading-relaxed mt-0.5 line-clamp-2"
style={{ fontSize: '0.72rem' }}
>
{item.description[l]}
</p>
</div>
{/* Price */}
<span className="font-body text-green text-sm font-semibold flex-shrink-0 pl-2">
{/* Price pill */}
<span className="price-pill flex-shrink-0">
{currency}{item.price}
</span>
</div>