2025-07-31 12:25:44 +03:00

177 lines
6.0 KiB
TypeScript
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 } from "react"
type TabType = "home" | "courses" | "profile"
interface FooterProps {
onTabChange?: (tab: TabType) => void
activeTab?: TabType
}
// Строгие и аккуратные SVG иконки
const HomeIcon = ({ filled = false, className = "" }) => (
<svg
className={className}
fill={filled ? "currentColor" : "none"}
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={filled ? 0 : 1.5}
>
{filled ? (
<path d="M11.47 3.841a.75.75 0 011.06 0l8.69 8.69a.75.75 0 101.06-1.061l-8.689-8.69a2.25 2.25 0 00-3.182 0l-8.69 8.69a.75.75 0 001.061 1.06l8.69-8.689z" />
) : (
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
/>
)}
</svg>
)
const BookIcon = ({ filled = false, className = "" }) => (
<svg
className={className}
fill={filled ? "currentColor" : "none"}
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={filled ? 0 : 1.5}
>
{filled ? (
<path d="M11.25 4.533A9.707 9.707 0 006 3a9.735 9.735 0 00-3.25.555.75.75 0 00-.5.707v14.25a.75.75 0 001 .707A8.237 8.237 0 016 18.75c1.995 0 3.823.707 5.25 1.886V4.533zM12.75 20.636A8.214 8.214 0 0118 18.75c.966 0 1.89.166 2.75.47a.75.75 0 001-.708V4.262a.75.75 0 00-.5-.707A9.735 9.735 0 0018 3a9.707 9.707 0 00-5.25 1.533v16.103z" />
) : (
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M12 6.042A9.02 9.02 0 016 3.75c-1.052 0-2.062.18-3 .512v14.25A8.998 8.998 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a9.02 9.02 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.998 8.998 0 0018 18a8.998 8.998 0 00-6 2.292m0-14.25v14.25"
/>
)}
</svg>
)
const UserIcon = ({ filled = false, className = "" }) => (
<svg
className={className}
fill={filled ? "currentColor" : "none"}
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={filled ? 0 : 1.5}
>
{filled ? (
<path
fillRule="evenodd"
d="M7.5 6a4.5 4.5 0 119 0 4.5 4.5 0 01-9 0zM3.751 20.105a8.25 8.25 0 0116.498 0 .75.75 0 01-.437.695A18.683 18.683 0 0112 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 01-.437-.695z"
clipRule="evenodd"
/>
) : (
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z"
/>
)}
</svg>
)
function Footer({ onTabChange, activeTab: controlledActiveTab }: FooterProps) {
const [internalActiveTab, setInternalActiveTab] = useState<TabType>("home")
const activeTab = controlledActiveTab || internalActiveTab
const handleTabChange = (tab: TabType) => {
if (!controlledActiveTab) {
setInternalActiveTab(tab)
}
onTabChange?.(tab)
}
const tabs = [
{
id: "home" as TabType,
label: "Главная",
icon: HomeIcon,
},
{
id: "courses" as TabType,
label: "Курсы",
icon: BookIcon,
},
{
id: "profile" as TabType,
label: "Профиль",
icon: UserIcon,
},
]
return (
<div className="fixed bottom-0 left-0 right-0 z-50">
{/* Основной контейнер */}
<div className="relative">
{/* Фон с размытием */}
<div className="absolute inset-0 bg-slate-900/95 backdrop-blur-2xl border-t border-teal-700/30" />
{/* Тонкая верхняя линия */}
<div className="absolute top-0 left-0 right-0 h-px bg-gradient-to-r from-transparent via-teal-500/60 to-transparent" />
{/* Контент */}
<div className="relative px-8 py-4">
<div className="flex justify-center items-center max-w-sm mx-auto">
<div className="flex space-x-12">
{tabs.map((tab) => {
const isActive = activeTab === tab.id
const Icon = tab.icon
return (
<button
key={tab.id}
onClick={() => handleTabChange(tab.id)}
className={`
group relative flex flex-col items-center justify-center
transition-all duration-200 ease-out
focus:outline-none focus:ring-2 focus:ring-teal-400/50 focus:ring-offset-2 focus:ring-offset-slate-900
rounded-lg p-2 min-w-[56px]
${isActive ? "" : "hover:bg-teal-900/20"}
`}
>
{/* Активный индикатор */}
{isActive && (
<div className="absolute -top-1 left-1/2 transform -translate-x-1/2 w-8 h-0.5 bg-gradient-to-r from-teal-400 to-cyan-400 rounded-full" />
)}
{/* Иконка */}
<div className="mb-1">
<Icon
filled={isActive}
className={`
w-6 h-6 transition-colors duration-200
${isActive ? "text-teal-300" : "text-slate-400 group-hover:text-teal-400"}
`}
/>
</div>
{/* Подпись */}
<span
className={`
text-xs font-medium transition-colors duration-200
${isActive ? "text-teal-200" : "text-slate-500 group-hover:text-teal-300"}
`}
>
{tab.label}
</span>
</button>
)
})}
</div>
</div>
</div>
{/* Нижний отступ для мобильных устройств */}
<div className="h-2 bg-slate-900/95 sm:h-0" />
</div>
</div>
)
}
export default Footer