Files
Portfolio/src/pages-vite/about/components/SkillBar.tsx
T
damjan_savicandClaude Opus 4.5 b1ec7b4d61 Migrate from Vite to Next.js 15 with SSR
- Replace Vite + React Router with Next.js 15 App Router
- Implement i18n with next-intl (URL-based: /de, /en, /sr)
- Add SSR/SSG for all pages (48 static pages generated)
- Setup Supabase SSR client for auth
- Migrate all pages: Home, About, Portfolio, Blog, Contact, Login, Dashboard, Imprint, Privacy, Terms
- Add Docker support with standalone output
- Replace i18next with next-intl JSON translations
- Use next/image for optimized images

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 01:00:33 +01:00

46 lines
1.4 KiB
TypeScript

// SkillBar.tsx
import React from 'react';
import { useTranslation } from 'react-i18next';
import { motion } from 'framer-motion';
interface SkillBarProps {
name: string;
level: number;
className?: string;
'aria-label'?: string;
}
const SkillBar: React.FC<SkillBarProps> = ({ name, level, className = '', 'aria-label': ariaLabel }) => {
const { t } = useTranslation();
return (
<div className={`space-y-2 ${className}`}>
<div className="flex justify-between items-center">
<span className="text-white text-sm">{name}</span>
<span className="text-white text-sm">
{level}%
</span>
</div>
<div
className="h-2 bg-zinc-800 rounded-full overflow-hidden"
role="progressbar"
aria-valuenow={level}
aria-valuemin={0}
aria-valuemax={100}
aria-label={ariaLabel || t('pages.about.skills.screenReader.skillProgress', {
skill: name,
level
})}
>
<motion.div
className="h-full bg-zinc-500 rounded-full"
initial={{ width: 0 }}
animate={{ width: `${level}%` }}
transition={{ duration: 0.5 }}
/>
</div>
</div>
);
};
export default SkillBar;