Prjgressbar
This commit is contained in:
parent
cc145c8804
commit
a69916b87a
@ -3,16 +3,17 @@
|
||||
import type React from "react"
|
||||
import { useHistory, useLocation } from "react-router-dom"
|
||||
|
||||
|
||||
const BottomNavigation: React.FC = () => {
|
||||
const history = useHistory()
|
||||
const location = useLocation()
|
||||
|
||||
// Define SVG icons directly within the component
|
||||
const HomeIcon = ({ active }: { active: boolean }) => (
|
||||
// Define SVG icons directly within the component, with active state styling
|
||||
const HomeIcon = ({ active, size = 24 }: { active: boolean; size?: number }) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox="0 0 24 24"
|
||||
fill={active ? "currentColor" : "none"}
|
||||
stroke={active ? "none" : "currentColor"}
|
||||
@ -25,11 +26,11 @@ const BottomNavigation: React.FC = () => {
|
||||
</svg>
|
||||
)
|
||||
|
||||
const CoursesIcon = ({ active }: { active: boolean }) => (
|
||||
const CoursesIcon = ({ active, size = 24 }: { active: boolean; size?: number }) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox="0 0 24 24"
|
||||
fill={active ? "currentColor" : "none"}
|
||||
stroke={active ? "none" : "currentColor"}
|
||||
@ -42,11 +43,11 @@ const BottomNavigation: React.FC = () => {
|
||||
</svg>
|
||||
)
|
||||
|
||||
const ExerciseIcon = ({ active }: { active: boolean }) => (
|
||||
const ExerciseIcon = ({ active, size = 24 }: { active: boolean; size?: number }) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox="0 0 24 24"
|
||||
fill={active ? "currentColor" : "none"}
|
||||
stroke={active ? "none" : "currentColor"}
|
||||
@ -60,11 +61,11 @@ const BottomNavigation: React.FC = () => {
|
||||
</svg>
|
||||
)
|
||||
|
||||
const SettingsIcon = ({ active }: { active: boolean }) => (
|
||||
const SettingsIcon = ({ active, size = 24 }: { active: boolean; size?: number }) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox="0 0 24 24"
|
||||
fill={active ? "currentColor" : "none"}
|
||||
stroke={active ? "none" : "currentColor"}
|
||||
@ -90,8 +91,8 @@ const BottomNavigation: React.FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="fixed bottom-0 left-0 right-0 bg-gradient-to-br from-[#3ABBC7] to-[#0D212C] p-4 z-50 shadow-lg">
|
||||
<div className="flex justify-around items-center max-w-md mx-auto">
|
||||
<div className="fixed bottom-0 left-0 right-0 bg-gradient-to-br from-[#3ABBC7] to-[#0D212C] p-4 z-50 shadow-lg rounded-t-3xl">
|
||||
<nav className="flex justify-around items-center max-w-md mx-auto">
|
||||
{navItems.map((item) => {
|
||||
const active = isActive(item.path)
|
||||
const IconComponent = item.icon
|
||||
@ -99,37 +100,36 @@ const BottomNavigation: React.FC = () => {
|
||||
<button
|
||||
key={item.path}
|
||||
onClick={() => history.push(item.path)}
|
||||
className="relative flex flex-col items-center justify-center w-24 h-24 overflow-hidden"
|
||||
className="relative flex flex-col items-center justify-center w-24 h-24 overflow-hidden group focus:outline-none focus-visible:ring-1 focus-visible:ring-white focus-visible:ring-offset-2 focus-visible:ring-offset-[#0D212C]"
|
||||
>
|
||||
{/* Active state background (glassmorphism rectangle) */}
|
||||
<div
|
||||
className={`absolute glass-morphism rounded-2xl shadow-md
|
||||
transition-all duration-300 ease-out
|
||||
${active ? "opacity-100 scale-100 w-20 h-20 -top-4" : "opacity-0 scale-0 w-0 h-0 top-0"}`}
|
||||
className={`absolute rounded-2xl shadow-md transition-all duration-300 ease-out bg-white/10 backdrop-blur-md border border-white/20 ${
|
||||
active ? "opacity-100 scale-100 w-20 h-20 top-0" : "opacity-0 scale-0 w-0 h-0 top-0"
|
||||
}`}
|
||||
/>
|
||||
|
||||
{/* Icon and Label container */}
|
||||
<div
|
||||
className={`relative z-10 flex flex-col items-center justify-center
|
||||
transition-all duration-300 ease-out
|
||||
${active ? "text-[#2BACBE] translate-y-[-24px]" : "text-white/70 translate-y-0 group-hover:text-white"}`}
|
||||
className={`relative z-10 flex flex-col items-center justify-center transition-all duration-300 ease-out ${
|
||||
active ? "text-[#2BACBE] translate-y-[-10px]" : "text-white/70 translate-y-0 group-hover:text-white"
|
||||
}`}
|
||||
>
|
||||
<div className="mb-1">
|
||||
<IconComponent active={active} />
|
||||
<IconComponent active={active} size={24} />
|
||||
</div>
|
||||
<span className="text-xs font-medium">{item.label}</span>
|
||||
<span className="sr-only">{item.label}</span>
|
||||
</div>
|
||||
|
||||
{/* Bottom circle with glow */}
|
||||
<div
|
||||
className={`absolute w-2 h-2 rounded-full border-2 border-white shadow-lg shadow-[#2BACBE]/50 animate-pulse
|
||||
transition-all duration-300 ease-out
|
||||
${active ? "opacity-100 scale-100 translate-y-[36px]" : "opacity-0 scale-0 translate-y-[0px]"}`}
|
||||
className={`absolute w-2 h-2 rounded-full border-2 border-white shadow-lg shadow-[#2BACBE]/50 animate-pulse transition-all duration-300 ease-out ${
|
||||
active ? "opacity-100 scale-100 translate-y-[32px]" : "opacity-0 scale-0 translate-y-[0px]"
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ const CircularProgressDisplay: React.FC<CircularProgressDisplayProps> = ({
|
||||
const exercisesStrokeDashoffset = circumference - (exercisesProgress / 100) * circumference
|
||||
|
||||
return (
|
||||
<div className="relative w-32 h-32 mx-auto flex items-center justify-center">
|
||||
<div className="relative w-40 h-40 mx-auto flex items-center justify-center">
|
||||
<svg className="w-full h-full" viewBox="0 0 100 100">
|
||||
{/* Overall Progress Background Circle */}
|
||||
<circle
|
||||
@ -36,9 +36,9 @@ const CircularProgressDisplay: React.FC<CircularProgressDisplayProps> = ({
|
||||
cy="50"
|
||||
/>
|
||||
|
||||
{/* Courses Ring (Blue) */}
|
||||
|
||||
<circle
|
||||
className="text-blue-500"
|
||||
className="text-orange-400"
|
||||
strokeWidth="8"
|
||||
strokeDasharray={circumference}
|
||||
strokeDashoffset={coursesStrokeDashoffset}
|
||||
@ -51,9 +51,9 @@ const CircularProgressDisplay: React.FC<CircularProgressDisplayProps> = ({
|
||||
transform="rotate(-90 50 50)"
|
||||
/>
|
||||
|
||||
{/* Exercises Ring (Green) */}
|
||||
|
||||
<circle
|
||||
className="text-green-500"
|
||||
className="text-cyan-400"
|
||||
strokeWidth="8"
|
||||
strokeDasharray={circumference}
|
||||
strokeDashoffset={exercisesStrokeDashoffset}
|
||||
@ -67,8 +67,8 @@ const CircularProgressDisplay: React.FC<CircularProgressDisplayProps> = ({
|
||||
/>
|
||||
</svg>
|
||||
<div className="absolute text-center">
|
||||
<div className="text-3xl font-black text-gray-800">{overallProgress}%</div>
|
||||
<div className="text-xs text-gray-600 font-semibold">Общий прогресс</div>
|
||||
<div className="text-3xl font-black text-gray-600">{overallProgress}%</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
24
src/components/Icons.tsx
Normal file
24
src/components/Icons.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import type React from "react"
|
||||
|
||||
// Your custom Home icon component
|
||||
export const CustomHomeIcon = ({ active, size = 24 }: { active: boolean; size?: number }) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox="0 0 24 24"
|
||||
fill={active ? "currentColor" : "none"} // Fill when active
|
||||
stroke={active ? "none" : "currentColor"} // Stroke when inactive
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
|
||||
<polyline points="9 22 9 12 15 12 15 22" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
// You can add other custom icons here if needed in the future
|
||||
// export const CustomAnotherIcon = ({ active, size = 24 }: { active: boolean; size?: number }) => (
|
||||
// <svg>...</svg>
|
||||
// );
|
Loading…
x
Reference in New Issue
Block a user