Fix styling of landing page

This commit is contained in:
2025-11-15 18:37:00 +02:00
parent 5cc90dc654
commit a6b446a101
8 changed files with 362 additions and 11 deletions

View File

@@ -1,14 +1,25 @@
<script setup lang="ts">
import { RouterLink, RouterView } from 'vue-router'
import WelcomeText from './components/WelcomeText.vue'
import ThemeToggle from './components/ThemeToggle.vue'
import LogoSvg from './components/icons/IconLogo.vue'
</script>
<template>
<ThemeToggle />
<header>
<img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125" />
<div class="wrapper">
<WelcomeText msg="Livonsaaren Tietokonepaja" />
<div class="title-section">
<div class="greetings">
<div class="title-with-logo">
<LogoSvg alt="Tietokonepajan logo" class="logo" />
<h1>Livonsaaren Tietokonepaja</h1>
</div>
<h3>
Tervetuloa Livonsaaren Tietokonepajan verkkosivuille! Tarjoamme kattavia IT-palveluita,
laitehuoltoja, kotisivuratkaisuja ja Linux-tukea. Tutustu palveluihimme ja ota yhteyttä!
</h3>
</div>
</div>
<nav>
<RouterLink to="/">Etusivu</RouterLink>
@@ -26,9 +37,44 @@ header {
max-height: 100vh;
}
.title-section {
display: flex;
align-items: center;
gap: 1.5rem;
margin-bottom: 2rem;
}
.title-with-logo {
display: flex;
align-items: center;
gap: 1rem;
justify-content: center;
margin-bottom: 1rem;
flex-direction: column;
}
.logo {
display: block;
margin: 0 auto 2rem;
height: 100%;
width: auto;
max-height: 120px;
flex-shrink: 0;
}
.greetings h1 {
font-weight: 500;
font-size: 2.6rem;
position: relative;
margin: 0;
}
.greetings h3 {
font-size: 1.2rem;
margin: 0;
}
.greetings h1,
.greetings h3 {
text-align: center;
}
nav {
@@ -63,8 +109,27 @@ nav a:first-of-type {
padding-right: calc(var(--section-gap) / 2);
}
.title-section {
flex-direction: row;
align-items: center;
margin-bottom: 0;
}
.title-with-logo {
justify-content: flex-start;
flex-direction: row;
}
.logo {
margin: 0 2rem 0 0;
height: 100%;
width: auto;
max-height: 100px;
margin-right: 0.5rem;
}
.greetings h1,
.greetings h3 {
text-align: left;
}
header .wrapper {

View File

@@ -33,11 +33,50 @@
--color-heading: var(--vt-c-text-light-1);
--color-text: var(--vt-c-text-light-1);
/* SVG/Icon colors */
--color-svg-fill: #000000;
--color-svg-stroke: #000000;
--section-gap: 160px;
}
/* Dark theme - manual toggle */
html.dark {
--color-background: var(--vt-c-black);
--color-background-soft: var(--vt-c-black-soft);
--color-background-mute: var(--vt-c-black-mute);
--color-border: var(--vt-c-divider-dark-2);
--color-border-hover: var(--vt-c-divider-dark-1);
--color-heading: var(--vt-c-text-dark-1);
--color-text: var(--vt-c-text-dark-2);
/* SVG/Icon colors for dark theme */
--color-svg-fill: #ffffff;
--color-svg-stroke: #ffffff;
}
/* Light theme - manual toggle */
html.light {
--color-background: var(--vt-c-white);
--color-background-soft: var(--vt-c-white-soft);
--color-background-mute: var(--vt-c-white-mute);
--color-border: var(--vt-c-divider-light-2);
--color-border-hover: var(--vt-c-divider-light-1);
--color-heading: var(--vt-c-text-light-1);
--color-text: var(--vt-c-text-light-1);
/* SVG/Icon colors for light theme */
--color-svg-fill: #000000;
--color-svg-stroke: #000000;
}
/* System preference fallback - only when no manual preference is set */
@media (prefers-color-scheme: dark) {
:root {
html:not(.light):not(.dark) {
--color-background: var(--vt-c-black);
--color-background-soft: var(--vt-c-black-soft);
--color-background-mute: var(--vt-c-black-mute);
@@ -47,6 +86,10 @@
--color-heading: var(--vt-c-text-dark-1);
--color-text: var(--vt-c-text-dark-2);
/* SVG/Icon colors for dark theme */
--color-svg-fill: #ffffff;
--color-svg-stroke: #ffffff;
}
}
@@ -84,3 +127,36 @@ body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* Global SVG theming */
svg {
transition:
fill 0.3s ease,
stroke 0.3s ease;
}
svg[fill='#000000'],
svg[fill='#000'] {
fill: var(--color-svg-fill) !important;
}
svg[stroke='#000000'],
svg[stroke='#000'] {
stroke: var(--color-svg-stroke) !important;
}
/* Target paths and other SVG elements with black fill/stroke */
svg path[fill='#000000'],
svg path[fill='#000'] {
fill: var(--color-svg-fill) !important;
}
svg path[stroke='#000000'],
svg path[stroke='#000'] {
stroke: var(--color-svg-stroke) !important;
}
/* Target specific attribute values commonly used */
svg g[fill='#000000'] {
fill: var(--color-svg-fill) !important;
}

View File

@@ -0,0 +1,128 @@
<template>
<button
@click="toggleTheme"
class="theme-toggle"
:aria-label="isDark ? 'Switch to light mode' : 'Switch to dark mode'"
title="Toggle theme"
>
<svg v-if="isDark" class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<!-- Sun icon -->
<circle cx="12" cy="12" r="5" />
<line x1="12" y1="1" x2="12" y2="3" />
<line x1="12" y1="21" x2="12" y2="23" />
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64" />
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78" />
<line x1="1" y1="12" x2="3" y2="12" />
<line x1="21" y1="12" x2="23" y2="12" />
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36" />
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22" />
</svg>
<svg v-else class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<!-- Moon icon -->
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
</svg>
</button>
</template>
<script setup lang="ts">
import { ref, onMounted, watch } from 'vue'
const isDark = ref(false)
const toggleTheme = () => {
isDark.value = !isDark.value
updateTheme()
localStorage.setItem('theme', isDark.value ? 'dark' : 'light')
}
const updateTheme = () => {
if (isDark.value) {
document.documentElement.classList.add('dark')
document.documentElement.classList.remove('light')
} else {
document.documentElement.classList.add('light')
document.documentElement.classList.remove('dark')
}
}
const initTheme = () => {
const savedTheme = localStorage.getItem('theme')
if (savedTheme) {
isDark.value = savedTheme === 'dark'
} else {
// Check system preference as fallback
isDark.value = window.matchMedia('(prefers-color-scheme: dark)').matches
}
updateTheme()
}
onMounted(() => {
initTheme()
})
// Watch for system theme changes when no preference is saved
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
mediaQuery.addEventListener('change', (e) => {
if (!localStorage.getItem('theme')) {
isDark.value = e.matches
updateTheme()
}
})
</script>
<style scoped>
.theme-toggle {
position: fixed;
top: 20px;
right: 20px;
z-index: 1000;
background: var(--color-background-soft);
border: 1px solid var(--color-border);
border-radius: 50%;
width: 48px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.theme-toggle:hover {
background: var(--color-background-mute);
border-color: var(--color-border-hover);
transform: scale(1.05);
}
.theme-toggle:active {
transform: scale(0.95);
}
.icon {
width: 20px;
height: 20px;
color: var(--color-text);
stroke-width: 2;
transition: transform 0.3s ease;
}
.theme-toggle:hover .icon {
transform: rotate(15deg);
}
/* Ensure the button works well on mobile */
@media (max-width: 768px) {
.theme-toggle {
top: 15px;
right: 15px;
width: 44px;
height: 44px;
}
.icon {
width: 18px;
height: 18px;
}
}
</style>

View File

@@ -23,3 +23,9 @@
</g>
</svg>
</template>
<style scoped>
.st0 {
fill: var(--color-svg-fill);
}
</style>

View File

@@ -1,6 +1,6 @@
<template>
<svg
fill="#000000"
fill="var(--color-svg-fill)"
width="800px"
height="800px"
viewBox="0 0 1920 1920"

View File

@@ -1,6 +1,6 @@
<template>
<svg
fill="#000000"
fill="var(--color-svg-fill)"
width="800px"
height="800px"
viewBox="0 0 32 32"

View File

@@ -0,0 +1,76 @@
<template>
<svg
version="1.0"
xmlns="http://www.w3.org/2000/svg"
:width="width"
:height="height"
viewBox="0 0 222.000000 222.000000"
preserveAspectRatio="xMidYMid meet"
class="logo-svg"
>
<g
transform="translate(0.000000,222.000000) scale(0.100000,-0.100000)"
fill="var(--color-svg-fill)"
stroke="none"
>
<path
d="M0 1110 l0 -1110 1110 0 1110 0 0 1110 0 1110 -1110 0 -1110 0 0
-1110z m2180 0 l0 -1070 -612 0 -613 0 222 222 c265 266 282 294 251 402 -10
35 -66 96 -362 394 -193 195 -368 362 -388 373 -45 23 -115 25 -166 3 -24 -9
-115 -93 -254 -232 l-218 -216 0 597 0 597 1070 0 1070 0 0 -1070z"
/>
<path
d="M124 2086 c-16 -13 -17 -18 -6 -35 9 -17 10 -25 0 -40 -9 -15 -9 -23
1 -35 11 -13 11 -19 0 -32 -10 -12 -10 -20 -1 -35 10 -15 9 -23 0 -39 -11 -17
-10 -22 2 -30 12 -7 12 -12 0 -35 -12 -23 -12 -28 0 -35 12 -7 12 -12 0 -35
-12 -23 -12 -28 0 -35 12 -7 12 -12 0 -35 -12 -23 -12 -28 0 -35 8 -6 103 -10
210 -10 209 0 236 6 203 42 -14 16 -33 18 -143 18 -70 0 -130 3 -133 7 -4 3
-1 13 6 21 9 12 9 16 0 19 -15 5 -17 39 -3 48 6 4 5 13 -3 25 -9 15 -9 25 -1
38 8 12 8 22 0 35 -8 12 -8 22 0 35 8 12 8 22 0 35 -8 12 -8 22 0 34 8 13 8
23 0 35 -8 13 -8 23 1 37 10 15 9 22 -6 35 -22 20 -100 21 -127 2z"
/>
<path
d="M1199 1843 c-64 -32 -369 -325 -369 -355 0 -51 34 -29 193 130 200
199 250 226 343 187 38 -16 355 -322 399 -385 15 -21 29 -56 32 -78 10 -76 -9
-105 -190 -289 -167 -169 -190 -203 -139 -203 30 0 338 320 364 377 29 64 28
135 -1 193 -30 59 -371 400 -428 429 -61 30 -135 28 -204 -6z"
/>
<path
d="M1198 1571 c-56 -57 -98 -107 -98 -118 0 -25 40 -63 66 -63 19 0 224
197 224 214 0 12 -22 51 -34 58 -34 23 -62 7 -158 -91z"
/>
<path
d="M1479 1302 c-74 -73 -99 -104 -99 -123 0 -27 37 -69 60 -69 7 0 59
46 116 102 110 108 122 130 84 168 -36 36 -57 25 -161 -78z"
/>
<path
d="M1675 546 c-33 -24 -3 -46 60 -46 67 0 89 -8 75 -25 -8 -10 -8 -19 1
-33 10 -16 10 -23 0 -35 -10 -12 -10 -19 0 -35 10 -16 10 -23 0 -35 -10 -12
-10 -19 0 -35 10 -16 10 -23 0 -35 -10 -12 -10 -19 0 -35 10 -16 10 -23 0 -36
-11 -13 -11 -19 0 -32 10 -13 10 -20 0 -36 -20 -32 2 -48 69 -48 67 0 89 16
69 48 -10 16 -10 23 0 35 10 12 10 19 0 35 -10 16 -10 23 0 35 10 12 10 19 0
35 -10 16 -10 23 0 35 10 12 10 19 0 35 -10 16 -10 23 0 35 10 12 10 19 0 35
-10 16 -10 23 0 36 10 12 11 19 2 30 -16 19 5 26 74 26 63 0 93 22 60 46 -27
20 -383 20 -410 0z"
/>
</g>
</svg>
</template>
<script setup lang="ts">
interface Props {
width?: string | number
height?: string | number
}
withDefaults(defineProps<Props>(), {
width: 125,
height: 125,
})
</script>
<style scoped>
.logo-svg {
transition: fill 0.3s ease;
}
</style>

View File

@@ -10,7 +10,7 @@
>
<path
fill="none"
stroke="#000000"
stroke="var(--color-svg-stroke)"
stroke-width="2"
stroke-miterlimit="10"
d="M22.2,12.8l-3-3l5-5C23.3,4.3,22.2,4,21,4