Files
smart-home-tablet/components/BottomNav.tsx
Cosmo 9044869fa4
All checks were successful
Deploy to Coolify / deploy (push) Successful in 44s
feat: initial smart home dashboard
- Next.js 14 + TypeScript + Tailwind CSS
- Glassmorphism design with ambient orbs
- Cards: Light x2, Temperature, AirPurifier, Tasks, Weather, Savings
- Home Assistant integration (demo mode if no token)
- Vikunja tasks API
- Pulse savings API
- wttr.in weather
- Framer Motion animations
- Dark/light theme toggle
- Bottom navigation
- Dockerfile for deployment
2026-04-22 10:00:41 +00:00

69 lines
2.1 KiB
TypeScript

"use client";
import { motion } from "framer-motion";
import { Home, Cpu, CheckSquare, Settings } from "lucide-react";
interface Props {
active: string;
onChange: (tab: string) => void;
}
const TABS = [
{ id: "home", label: "Главная", icon: Home },
{ id: "devices", label: "Устройства", icon: Cpu },
{ id: "tasks", label: "Задачи", icon: CheckSquare },
{ id: "settings", label: "Настройки", icon: Settings },
];
export default function BottomNav({ active, onChange }: Props) {
return (
<motion.div
className="glass-card px-4 py-2 flex items-center justify-around no-select"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
>
{TABS.map((tab) => {
const Icon = tab.icon;
const isActive = active === tab.id;
return (
<motion.button
key={tab.id}
onClick={() => onChange(tab.id)}
className="flex flex-col items-center gap-1 px-6 py-2 rounded-xl relative"
whileTap={{ scale: 0.88 }}
style={{
background: isActive
? "rgba(99,102,241,0.15)"
: "transparent",
}}
>
{isActive && (
<motion.div
className="absolute inset-0 rounded-xl"
style={{
background:
"linear-gradient(135deg, rgba(99,102,241,0.15), rgba(139,92,246,0.1))",
border: "1px solid rgba(99,102,241,0.3)",
}}
layoutId="navActive"
transition={{ type: "spring", stiffness: 400, damping: 30 }}
/>
)}
<Icon
size={22}
color={isActive ? "#6366f1" : "var(--text-secondary)"}
/>
<span
className="text-xs font-medium"
style={{ color: isActive ? "#6366f1" : "var(--text-secondary)" }}
>
{tab.label}
</span>
</motion.button>
);
})}
</motion.div>
);
}