feat(skills): add discipline-specific content and tool assets

This commit is contained in:
2026-09-06 23:44:13 +03:30
parent 08af430122
commit 6c860db2d9
30 changed files with 244 additions and 98 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
public/images/tools/css.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
public/images/tools/sql.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -116,19 +116,12 @@
padding: 0.75rem 0.375rem; padding: 0.75rem 0.375rem;
box-sizing: border-box; box-sizing: border-box;
transition: transition:
opacity var(--motion-duration-default) ease,
filter var(--motion-duration-default) ease,
border-color var(--motion-duration-fast) ease, border-color var(--motion-duration-fast) ease,
box-shadow var(--motion-duration-default) ease, box-shadow var(--motion-duration-default) ease,
transform var(--motion-duration-default) var(--motion-ease-out); transform var(--motion-duration-default) var(--motion-ease-out);
cursor: default; cursor: default;
} }
.toolDimmed {
opacity: 0.35;
filter: grayscale(0.8);
}
.toolIconContainer { .toolIconContainer {
width: clamp(2.25rem, 42%, 3.5rem); width: clamp(2.25rem, 42%, 3.5rem);
height: clamp(2.25rem, 42%, 3.5rem); height: clamp(2.25rem, 42%, 3.5rem);

View File

@@ -4,9 +4,7 @@ import React, { useState } from 'react';
import Image from 'next/image'; import Image from 'next/image';
import { Code, BarChart2, Wand2 } from 'lucide-react'; import { Code, BarChart2, Wand2 } from 'lucide-react';
import { import {
skillCategories, skillsByDiscipline,
keywordBadges,
toolsList,
filterTabs, filterTabs,
FilterTab, FilterTab,
} from '@/data/skills'; } from '@/data/skills';
@@ -14,6 +12,7 @@ import styles from './SkillsSection.module.css';
export const SkillsSection: React.FC = () => { export const SkillsSection: React.FC = () => {
const [activeFilter, setActiveFilter] = useState<FilterTab['id']>('software-engineering'); const [activeFilter, setActiveFilter] = useState<FilterTab['id']>('software-engineering');
const activeDiscipline = skillsByDiscipline[activeFilter];
const getFilterIcon = (id: FilterTab['id']) => { const getFilterIcon = (id: FilterTab['id']) => {
switch (id) { switch (id) {
@@ -39,14 +38,14 @@ export const SkillsSection: React.FC = () => {
</div> </div>
{/* Main Card Container */} {/* Main Card Container */}
<div className={styles.mainCard}> <div className={styles.mainCard} aria-live="polite">
{/* Section: Skills */} {/* Section: Skills */}
<div className={styles.skillsBlock}> <div className={styles.skillsBlock}>
<span className={styles.cardEyebrow}>SKILLS</span> <span className={styles.cardEyebrow}>SKILLS</span>
{/* 8 Skill Meters Grid */} {/* Discipline-specific skill meters */}
<div className={styles.skillsGrid}> <div className={styles.skillsGrid}>
{skillCategories.map((skill) => ( {activeDiscipline.skills.map((skill) => (
<div key={skill.name} className={styles.skillItem}> <div key={skill.name} className={styles.skillItem}>
<div className={styles.skillName}>{skill.name}</div> <div className={styles.skillName}>{skill.name}</div>
<div className={styles.meterSegments}> <div className={styles.meterSegments}>
@@ -65,8 +64,8 @@ export const SkillsSection: React.FC = () => {
{/* Keyword Badges */} {/* Keyword Badges */}
<div className={styles.badgeCloud}> <div className={styles.badgeCloud}>
{keywordBadges.map((badge) => ( {activeDiscipline.keywords.map((badge, index) => (
<span key={badge} className={styles.badgePill}> <span key={`${badge}-${index}`} className={styles.badgePill}>
{badge} {badge}
</span> </span>
))} ))}
@@ -79,15 +78,8 @@ export const SkillsSection: React.FC = () => {
{/* 8-Column Grid */} {/* 8-Column Grid */}
<div className={styles.toolsGrid}> <div className={styles.toolsGrid}>
{toolsList.map((tool) => { {activeDiscipline.tools.map((tool) => (
const isMatching = tool.category.includes(activeFilter); <div key={tool.id} className={styles.toolTile}>
return (
<div
key={tool.id}
className={`${styles.toolTile} ${
!isMatching ? styles.toolDimmed : ''
}`}
>
<div className={styles.toolIconContainer}> <div className={styles.toolIconContainer}>
<Image <Image
src={tool.icon} src={tool.icon}
@@ -99,14 +91,13 @@ export const SkillsSection: React.FC = () => {
</div> </div>
<span className={styles.toolLabel}>{tool.name}</span> <span className={styles.toolLabel}>{tool.name}</span>
</div> </div>
); ))}
})}
</div> </div>
</div> </div>
</div> </div>
{/* Filter Tabs Under Card */} {/* Filter Tabs Under Card */}
<div className={styles.filterTabsRow} aria-label="Filter tools by discipline"> <div className={styles.filterTabsRow} aria-label="Choose skill discipline">
{filterTabs.map((tab) => { {filterTabs.map((tab) => {
const isActive = activeFilter === tab.id; const isActive = activeFilter === tab.id;
return ( return (

View File

@@ -1,27 +1,55 @@
export type DisciplineId =
| 'software-engineering'
| 'product-management'
| 'design-ux';
export interface SkillCategory { export interface SkillCategory {
name: string; name: string;
level: number; // 1 to 5 level: number;
} }
export interface ToolItem { export interface ToolItem {
id: string; id: string;
name: string; name: string;
icon: string; icon: string;
category: ('software-engineering' | 'product-management' | 'design-ux')[];
} }
export const skillCategories: SkillCategory[] = [ export interface SkillDiscipline {
skills: SkillCategory[];
keywords: string[];
tools: ToolItem[];
}
export interface FilterTab {
id: DisciplineId;
label: string;
}
const tool = (id: string, name: string, icon = id): ToolItem => ({
id,
name,
icon: `/images/tools/${icon}.png`,
});
const placeholderTool = (id: string, name: string): ToolItem => ({
id,
name,
icon: `/images/tools/${id}.png`,
});
export const skillsByDiscipline: Record<DisciplineId, SkillDiscipline> = {
'software-engineering': {
skills: [
{ name: 'Backend', level: 5 }, { name: 'Backend', level: 5 },
{ name: 'Databases', level: 4 }, { name: 'Databases', level: 4 },
{ name: 'Testing & Quality', level: 3 }, { name: 'Testing & Quality', level: 3 },
{ name: 'System Design', level: 3 }, { name: 'System Design', level: 3 },
{ name: 'Frontend', level: 5 }, { name: 'Frontend', level: 3 },
{ name: 'DevOps', level: 2 }, { name: 'DevOps', level: 2 },
{ name: 'Web Scraping', level: 3 }, { name: 'Web Scraping', level: 2 },
{ name: 'Version Control', level: 4 }, { name: 'Version Control', level: 4 },
]; ],
keywords: [
export const keywordBadges: string[] = [
'Documentation', 'Documentation',
'Authentication', 'Authentication',
'Authorization', 'Authorization',
@@ -37,42 +65,176 @@ export const keywordBadges: string[] = [
'Microservices', 'Microservices',
'Performance Optimization', 'Performance Optimization',
'Third-Party Integration', 'Third-Party Integration',
]; ],
tools: [
export const toolsList: ToolItem[] = [ tool('vscode', 'VS Code'),
// Row 1 tool('codex', 'Codex'),
{ id: 'vscode', name: 'VS Code', icon: '/images/tools/vscode.png', category: ['software-engineering'] }, tool('antigravity', 'Antigravity'),
{ id: 'codex', name: 'Codex', icon: '/images/tools/codex.png', category: ['software-engineering', 'product-management'] }, tool('git', 'Git'),
{ id: 'antigravity', name: 'Antigravity', icon: '/images/tools/antigravity.png', category: ['software-engineering', 'product-management'] }, tool('github', 'GitHub'),
{ id: 'git', name: 'Git', icon: '/images/tools/git.png', category: ['software-engineering'] }, tool('python', 'Python'),
{ id: 'github', name: 'GitHub', icon: '/images/tools/github.png', category: ['software-engineering', 'product-management'] }, tool('django', 'Django'),
{ id: 'python', name: 'Python', icon: '/images/tools/python.png', category: ['software-engineering'] }, tool('fastapi', 'FastAPI'),
{ id: 'django', name: 'Django', icon: '/images/tools/django.png', category: ['software-engineering'] }, tool('celery', 'Celery'),
{ id: 'fastapi', name: 'FastAPI', icon: '/images/tools/fastapi.png', category: ['software-engineering'] }, tool('postgresql', 'PostgreSQL'),
// Row 2 tool('redis', 'Redis'),
{ id: 'celery', name: 'Celery', icon: '/images/tools/celery.png', category: ['software-engineering'] }, tool('neo4j', 'Neo4j'),
{ id: 'postgresql', name: 'PostgreSQL', icon: '/images/tools/postgresql.png', category: ['software-engineering'] }, tool('mongodb', 'MongoDB'),
{ id: 'redis', name: 'Redis', icon: '/images/tools/redis.png', category: ['software-engineering'] }, tool('typescript', 'TypeScript'),
{ id: 'neo4j', name: 'Neo4j', icon: '/images/tools/neo4j.png', category: ['software-engineering'] }, tool('react', 'React'),
{ id: 'mongodb', name: 'MongoDB', icon: '/images/tools/mongodb.png', category: ['software-engineering'] }, tool('nextjs', 'Next.js'),
{ id: 'typescript', name: 'TypeScript', icon: '/images/tools/typescript.png', category: ['software-engineering'] }, tool('linux', 'Linux'),
{ id: 'react', name: 'React', icon: '/images/tools/react.png', category: ['software-engineering', 'design-ux'] }, tool('docker', 'Docker'),
{ id: 'nextjs', name: 'Next.js', icon: '/images/tools/nextjs.png', category: ['software-engineering', 'design-ux'] }, tool('nginx', 'Nginx'),
// Row 3 tool('caddy', 'Caddy'),
{ id: 'linux', name: 'Linux', icon: '/images/tools/linux.png', category: ['software-engineering'] }, tool('minio', 'MinIO'),
{ id: 'docker', name: 'Docker', icon: '/images/tools/docker.png', category: ['software-engineering'] }, tool('prometheus', 'Prometheus'),
{ id: 'nginx', name: 'Nginx', icon: '/images/tools/nginx.png', category: ['software-engineering'] }, tool('grafana', 'Grafana'),
{ id: 'caddy', name: 'Caddy', icon: '/images/tools/caddy.png', category: ['software-engineering'] }, tool('kubernetes', 'Kubernetes'),
{ id: 'minio', name: 'MinIO', icon: '/images/tools/minio.png', category: ['software-engineering'] }, ],
{ id: 'prometheus', name: 'Prometheus', icon: '/images/tools/prometheus.png', category: ['software-engineering'] }, },
{ id: 'grafana', name: 'Grafana', icon: '/images/tools/grafana.png', category: ['software-engineering', 'product-management'] }, 'product-management': {
{ id: 'kubernetes', name: 'Kubernetes', icon: '/images/tools/kubernetes.png', category: ['software-engineering'] }, skills: [
]; { name: 'Technical Product Management', level: 4 },
{ name: 'Product Strategy', level: 3 },
export interface FilterTab { { name: 'Product Analytics', level: 2 },
id: 'software-engineering' | 'product-management' | 'design-ux'; { name: 'Roadmapping & Prioritization', level: 3 },
label: string; { name: 'User Research', level: 3 },
} { name: 'Testing & Quality', level: 3 },
],
keywords: [
'Market Research',
'Competitive Analysis',
'Customer Segmentation',
'Personas',
'Jobs to Be Done',
'Value Proposition',
'Product-Market Fit',
'MVP Definition',
'RICE',
'MoSCoW',
'PRDs',
'Requirements Gathering',
'User Stories',
'Acceptance Criteria',
'Agile',
'Scrum',
'Sprint Planning',
'Kanban',
'Product Documentation',
'KPI Definition',
'OKRs',
'North Star Metrics',
'Funnel Analysis',
'Conversion Analysis',
'Retention Analysis',
'Churn Analysis',
'A/B Testing',
'Beta Testing',
'Usability Testing',
'Customer Interviews',
'Customer Journey Mapping',
'Engineering Collaboration',
'Design Collaboration',
'Go-to-Market',
'Technical Trade-offs',
'Technical Debt',
'Scalability',
'Performance',
],
tools: [
placeholderTool('notion', 'Notion'),
placeholderTool('mizito', 'Mizito'),
tool('github-projects', 'GitHub Projects', 'github'),
placeholderTool('jira', 'Jira'),
placeholderTool('porsline', 'Porsline'),
placeholderTool('mattermost', 'Mattermost'),
placeholderTool('figma', 'Figma'),
placeholderTool('figjam', 'Fig Jam'),
placeholderTool('sql', 'SQL'),
placeholderTool('power-bi', 'Power BI'),
placeholderTool('metabase', 'Metabase'),
placeholderTool('google-docs', 'Google Docs'),
placeholderTool('google-sheets', 'Google Sheets'),
placeholderTool('google-slides', 'Google Slides'),
placeholderTool('microsoft-office', 'Microsoft Office'),
placeholderTool('chatgpt', 'ChatGPT'),
placeholderTool('gemini', 'Gemini'),
placeholderTool('claude', 'Claude'),
],
},
'design-ux': {
skills: [
{ name: 'Visual Design', level: 4 },
{ name: 'UI Design', level: 3 },
{ name: 'UX Design', level: 2 },
{ name: 'User Research', level: 4 },
{ name: 'Product Thinking', level: 3 },
{ name: 'Prototyping', level: 3 },
{ name: 'Design Systems', level: 3 },
],
keywords: [
'Typography',
'Color Theory',
'Color Theory',
'Visual Hierarchy',
'Iconography & Imagery',
'Interface Patterns',
'Component Design',
'States',
'Interactions',
'Responsive Design',
'Design Consistency',
'User Flows',
'Information Architecture',
'Usability Principles',
'Accessibility',
'Surveys',
'Personas',
'User Segmentation',
'Problem Definition',
'Feature Prioritization',
'Success Metrics',
'Wireframing',
'Microinteractions',
'Motion & Transition Design',
'Component Libraries',
'Design Tokens',
'Pattern Documentation',
'Scalable Component Architecture',
'Design-Development Alignment',
'Usability Testing',
'A/B Testing',
'Storytelling',
'Design Collaboration',
'Go-to-Market',
'Technical Trade-offs',
'Technical Debt',
'Scalability',
'Performance',
],
tools: [
placeholderTool('figma', 'Figma'),
placeholderTool('figjam', 'Fig Jam'),
placeholderTool('framer', 'Framer'),
placeholderTool('adobe-illustrator', 'Adobe Illustrator'),
placeholderTool('adobe-photoshop', 'Adobe Photoshop'),
placeholderTool('adobe-xd', 'Adobe XD'),
placeholderTool('penpot', 'Penpot'),
placeholderTool('html', 'HTML'),
placeholderTool('css', 'CSS'),
placeholderTool('javascript', 'JavaScript'),
placeholderTool('tailwind', 'Tailwind'),
tool('vscode', 'VS Code'),
tool('github', 'GitHub'),
placeholderTool('chatgpt', 'ChatGPT'),
placeholderTool('gemini', 'Gemini'),
placeholderTool('claude-design', 'Claude Design'),
tool('codex', 'Codex'),
tool('antigravity', 'Antigravity'),
],
},
};
export const filterTabs: FilterTab[] = [ export const filterTabs: FilterTab[] = [
{ id: 'software-engineering', label: 'Software Engineering' }, { id: 'software-engineering', label: 'Software Engineering' },