From ae10c8f0496e4f33bff0624d6d21453c3e36a1ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Veikko=20Lintuj=C3=A4rvi?= Date: Fri, 7 Aug 2026 20:06:34 +0300 Subject: [PATCH] Project page touch up --- src/components/Projects.jsx | 43 +++++++--- src/styles/components/Projects.module.scss | 93 ++++++++++++++++++---- 2 files changed, 108 insertions(+), 28 deletions(-) diff --git a/src/components/Projects.jsx b/src/components/Projects.jsx index ab7ba34..47d8b38 100644 --- a/src/components/Projects.jsx +++ b/src/components/Projects.jsx @@ -2,28 +2,41 @@ import styles from '../styles/components/Projects.module.scss'; const PROJECTS = [ { - name: 'Klapi - Unified Control Panel', + name: 'Klapi - Unified content management panel', desc: 'Web interface to view and manage data held by Livonsaaren Tietokonepaja. Easy to customize serving various customer solutions.', tags: ['.NET', 'React', 'SQLite'], href: 'https://klapi.tietokonepaja.fi/', - star: false, + sourceHref: 'https://github.com', }, { - name: 'Hattara - Online office', + name: 'Hattara - Shared online office', desc: 'Why to code your own when there is working open source solution to host on your own server? Hattara is a self-hosted cloud office solution for small teams and individuals.', tags: ['Apache2', 'Ubuntu Server', 'NextCloud'], href: 'https://hattara.tietokonepaja.fi/', - star: false, + sourceHref: 'https://github.com', }, { - name: 'Runosaari festival website - Pro bono', + name: 'Runosaari festival website - Pro bono project', desc: "Supporting local culture initiatives have always been close to my heart. I'm proudly helping Runosaari festival with their website and online presence already for the sixth year!", tags: ['React', 'Vite', 'Apache2', 'Ubuntu Server'], href: 'https://www.runosaari.fi/', - star: false, + sourceHref: 'https://github.com', }, ]; +const getTagColor = (tag) => { + const colorMap = { + '.NET': 'tagDotnet', + React: 'tagReact', + SQLite: 'tagSqlite', + Apache2: 'tagApache', + 'Ubuntu Server': 'tagUbuntu', + NextCloud: 'tagNextcloud', + Vite: 'tagVite', + }; + return colorMap[tag] || 'tagDefault'; +}; + export default function Projects() { return (
@@ -36,19 +49,25 @@ export default function Projects() {
{PROJECTS.map((p) => ( -
- {p.star && Featured} + diff --git a/src/styles/components/Projects.module.scss b/src/styles/components/Projects.module.scss index 2165d9b..f18afd6 100644 --- a/src/styles/components/Projects.module.scss +++ b/src/styles/components/Projects.module.scss @@ -66,6 +66,29 @@ } } +.cardTop { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: $space-2; +} + +.cardLinks { + display: flex; + gap: $space-2; +} + +.sourceLink { + font-size: $text-xl; + color: $color-text-muted; + transition: color $transition-fast, transform $transition-fast; + + &:hover { + color: $color-accent; + transform: translate(2px, -2px); + } +} + .featuredBadge { position: absolute; top: $space-4; @@ -79,13 +102,6 @@ padding: 2px $space-3; } -.cardTop { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: $space-2; -} - .folderIcon { font-size: $text-2xl; color: $color-accent; @@ -121,13 +137,58 @@ flex-wrap: wrap; gap: $space-2; margin-top: $space-2; - - li { - font-family: $font-mono; - font-size: $text-xs; - color: $color-text-dim; - background: rgb(var(--color-primary) / 0.15); - border-radius: $radius-sm; - padding: 2px $space-3; - } + padding: 0; +} + +.tagItem { + list-style: none; +} + +.tagPill { + font-family: $font-mono; + font-size: $text-xs; + border-radius: $radius-sm; + padding: 2px $space-3; + display: inline-block; +} + +// Tag color variants +.tagReact { + background: rgb(97, 218, 251); + color: rgb(0, 0, 0); +} + +.tagDotnet { + background: rgb(102, 51, 153); + color: rgb(255, 255, 255); +} + +.tagSqlite { + background: rgb(70, 130, 180); + color: rgb(255, 255, 255); +} + +.tagApache { + background: rgb(204, 102, 51); + color: rgb(255, 255, 255); +} + +.tagUbuntu { + background: rgb(220, 100, 40); + color: rgb(255, 255, 255); +} + +.tagNextcloud { + background: rgb(0, 150, 200); + color: rgb(255, 255, 255); +} + +.tagVite { + background: rgb(150, 50, 200); + color: rgb(255, 255, 255); +} + +.tagDefault { + background: rgb(var(--color-primary) / 0.15); + color: $color-text-dim; }