Középre kerül, ami belépő pont, és sötéten indul a site

A facelift mindent balra igazított, pedig nem minden olvasnivaló. A szabály
mostantól: középre az kerül, ami tájékozódási pont és nem szöveg — az
oldalak hero-ja, a magányos állapotblokkok, és a lista végén álló egyetlen
vissza-link. Balra marad minden, amit olvasnak vagy pásztáznak: törzsszöveg,
listák, táblázatok, kártyák, vezérlők, lábléc.

A részletoldalak kivételek: a blogbejegyzés és a katalógus-részlet hero-ja
balra marad, mert ott a cím már a tartalom első sora, nem belépő pont.

Az alapértelmezett téma a sötét lett; süti nélkül az indul, és a világosat
az választja, aki kéri. Retro módban pedig eltűnik a téma-kapcsoló: ott a
retro palettája írja felül a tokeneket, a gomb nem csinált volna semmit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-20 13:02:28 +02:00
co-authored by Claude Opus 5
parent ebe3684d44
commit 02ffedbca2
17 changed files with 62 additions and 44 deletions
+1 -4
View File
@@ -8,12 +8,9 @@
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<title>Teletype Games</title>
<script>
/* A témát a bundle betöltése ELŐTT tesszük a gyökérre, különben minden
sötét témás oldalbetöltés villan egy világosat. A sütit ezután az
ui.store tartja karban; süti nélkül az alapértelmezés a világos. */
(function () {
var m = document.cookie.match(/(?:^|; )theme=([^;]*)/)
var theme = m && decodeURIComponent(m[1]) === 'dark' ? 'dark' : 'light'
var theme = m && decodeURIComponent(m[1]) === 'light' ? 'light' : 'dark'
document.documentElement.setAttribute('data-theme', theme)
var r = document.cookie.match(/(?:^|; )retro-mode=([^;]*)/)
document.documentElement.setAttribute('data-retro', r && r[1] === '1' ? '1' : '0')
+1 -1
View File
@@ -18,7 +18,7 @@
<button :class="localeBtnClass('hu')" class="locale-btn" @click="switchLocale('hu')">HU</button>
</div>
<button class="icon-btn" :aria-label="t('nav.theme')" :title="t('nav.theme')" @click="toggleTheme">
<button v-if="!isRetroMode" class="icon-btn" :aria-label="t('nav.theme')" :title="t('nav.theme')" @click="toggleTheme">
<Sun v-if="theme === 'dark'" v-bind="ICON_CONTROL" />
<Moon v-else v-bind="ICON_CONTROL" />
</button>
@@ -46,12 +46,22 @@ describe('AppLayout', () => {
it('switches the theme from the header, and writes it to the root element', async () => {
const wrapper = await mountLayout()
expect(document.documentElement.getAttribute('data-theme')).toBe('light')
expect(document.documentElement.getAttribute('data-theme')).toBe('dark')
await wrapper.findAll('.icon-btn')[0].trigger('click')
expect(document.documentElement.getAttribute('data-theme')).toBe('dark')
expect(document.cookie).toContain('theme=dark')
expect(document.documentElement.getAttribute('data-theme')).toBe('light')
expect(document.cookie).toContain('theme=light')
})
it('drops the theme switch in retro mode, where it would do nothing', async () => {
const wrapper = await mountLayout()
expect(wrapper.findAll('.icon-btn')).toHaveLength(2)
await wrapper.get('.retro-toggle-btn').trigger('click')
expect(wrapper.findAll('.icon-btn')).toHaveLength(1)
expect(wrapper.get('.icon-btn').attributes('aria-label')).toBe('Menu')
})
it('marks retro mode on the root element too, so the page background follows', async () => {
@@ -1,7 +1,7 @@
<template>
<div class="blog-container">
<header class="hero-section">
<div class="hero-container">
<div class="hero-container hero-centered">
<p class="hero-badge">{{ t('blog.badge') }}</p>
<h1 class="hero-title">{{ t('blog.title') }}</h1>
<p class="hero-subtitle">{{ t('blog.subtitle') }}</p>
@@ -1,6 +1,6 @@
<template>
<header class="hero-section">
<div class="hero-container">
<div class="hero-container hero-centered">
<h1 class="hero-title">{{ t('builds.title') }}</h1>
<p class="hero-subtitle">{{ t('builds.subtitle') }}</p>
</div>
@@ -72,7 +72,7 @@
</div>
</div>
<div class="builds-back">
<div class="focus-row">
<RouterLink to="/catalog" class="link text-sm">{{ t('catalogShow.back') }}</RouterLink>
</div>
</main>
@@ -202,7 +202,4 @@ onMounted(() => store.fetch())
.builds-card-kind {
@apply flex items-center gap-1.5 text-sm text-fg-muted;
}
.builds-back {
@apply mt-8;
}
</style>
@@ -1,6 +1,6 @@
<template>
<header class="hero-section">
<div class="hero-container">
<div class="hero-container hero-centered">
<h1 class="hero-title">{{ t('catalog.title') }}</h1>
<p class="hero-subtitle">{{ t('catalog.subtitle') }}</p>
<div class="hero-actions">
@@ -133,7 +133,7 @@
</main>
<main v-else class="main-container">
<p class="text-fg-muted">{{ error || t('catalogShow.loading') }}</p>
<p class="state-message">{{ error || t('catalogShow.loading') }}</p>
</main>
<ImageLightbox
@@ -1,6 +1,6 @@
<template>
<header class="hero-section">
<div class="hero-container">
<div class="hero-container hero-centered">
<h1 class="hero-title">{{ t('code.title') }}</h1>
<p class="hero-subtitle">{{ t('code.subtitle') }}</p>
<div class="hero-actions">
@@ -1,6 +1,6 @@
<template>
<header class="hero-section">
<div class="hero-container">
<div class="hero-container hero-centered">
<h1 class="hero-title">{{ t('contact.title') }}</h1>
<p class="hero-subtitle">{{ t('contact.subtitle') }}</p>
<div class="hero-actions">
@@ -1,7 +1,7 @@
<template>
<div class="engines-container">
<header class="hero-section">
<div class="hero-container">
<div class="hero-container hero-centered">
<p class="hero-badge">{{ t('engines.badge') }}</p>
<h1 class="hero-title">{{ t('engines.titleLead') }} {{ t('engines.titleAccent') }}</h1>
<p class="hero-subtitle">{{ t('engines.subtitle') }}</p>
+1 -1
View File
@@ -1,7 +1,7 @@
<template>
<div class="home-container">
<header class="hero-section">
<div class="hero-container">
<div class="hero-container hero-centered">
<p class="hero-badge">{{ t('home.welcomeTo') }}</p>
<h1 class="hero-title">Teletype <span class="text-accent">Games</span></h1>
<p class="hero-subtitle">{{ t('home.subtitle') }}</p>
@@ -1,7 +1,7 @@
<template>
<div class="howtos-container">
<header class="hero-section">
<div class="hero-container">
<div class="hero-container hero-centered">
<p class="hero-badge">{{ t('howtos.badge') }}</p>
<h1 class="hero-title">{{ t('howtos.title') }}</h1>
<p class="hero-subtitle">{{ t('howtos.subtitle') }}</p>
@@ -49,7 +49,7 @@
</a>
</div>
<div v-if="!error && recentPages.length > 0" class="howtos-footer">
<div v-if="!error && recentPages.length > 0" class="focus-row">
<a :href="WIKI_BASE" target="_blank" rel="noopener noreferrer" class="link text-sm">
{{ t('howtos.browseWiki') }}
</a>
@@ -101,7 +101,4 @@ onMounted(() => store.fetch())
.howto-card-footer {
@apply mt-auto truncate border-t border-line pt-3 font-mono text-xs text-fg-subtle;
}
.howtos-footer {
@apply mt-10;
}
</style>
@@ -1,6 +1,6 @@
<template>
<header class="hero-section">
<div class="hero-container">
<div class="hero-container hero-centered">
<h1 class="hero-title">{{ t('stores.title') }}</h1>
<p class="hero-subtitle">{{ t('stores.subtitle') }}</p>
</div>
@@ -105,7 +105,7 @@
</section>
</template>
<div class="st-back">
<div class="focus-row">
<RouterLink to="/catalog" class="link text-sm">{{ t('catalogShow.back') }}</RouterLink>
</div>
</main>
@@ -280,7 +280,4 @@ const platforms = [
.st-platform-ext {
@apply rounded border border-line bg-surface px-2 py-0.5 text-xs text-accent;
}
.st-back {
@apply mt-8;
}
</style>
@@ -1,6 +1,6 @@
<template>
<header class="hero-section">
<div class="hero-container">
<div class="hero-container hero-centered">
<h1 class="hero-title">{{ t('team.title') }}</h1>
<p class="hero-subtitle">{{ t('team.subtitle') }}</p>
</div>
@@ -23,28 +23,28 @@ describe('useUiStore', () => {
expect(store.isRetroMode).toBe(false)
})
it('starts in the light theme when no cookie is set', () => {
it('starts in the dark theme when no cookie is set', () => {
const store = useUiStore()
expect(store.theme).toBe('dark')
expect(document.documentElement.getAttribute('data-theme')).toBe('dark')
})
it('reads the theme back from the cookie', () => {
document.cookie = 'theme=light;path=/'
const store = useUiStore()
expect(store.theme).toBe('light')
expect(document.documentElement.getAttribute('data-theme')).toBe('light')
})
it('reads the theme back from the cookie', () => {
document.cookie = 'theme=dark;path=/'
const store = useUiStore()
expect(store.theme).toBe('dark')
expect(document.documentElement.getAttribute('data-theme')).toBe('dark')
})
it('toggling the theme writes the cookie and the root attribute', () => {
const store = useUiStore()
store.toggleTheme()
expect(store.theme).toBe('dark')
expect(document.cookie).toContain('theme=dark')
expect(document.documentElement.getAttribute('data-theme')).toBe('dark')
store.toggleTheme()
expect(store.theme).toBe('light')
expect(document.cookie).toContain('theme=light')
expect(document.documentElement.getAttribute('data-theme')).toBe('light')
store.toggleTheme()
expect(store.theme).toBe('dark')
expect(document.cookie).toContain('theme=dark')
})
it('toggles menu', () => {
+1 -1
View File
@@ -7,7 +7,7 @@ export type Theme = 'light' | 'dark'
const THEME_COOKIE = 'theme'
function readTheme(): Theme {
return getCookie(THEME_COOKIE) === 'dark' ? 'dark' : 'light'
return getCookie(THEME_COOKIE) === 'light' ? 'light' : 'dark'
}
function applyTheme(theme: Theme) {
+20
View File
@@ -65,6 +65,26 @@ button:focus-visible {
@apply mt-6 flex flex-wrap items-center gap-3;
}
.hero-centered {
@apply text-center;
}
.hero-centered .hero-subtitle {
@apply mx-auto;
}
.hero-centered .hero-actions {
@apply justify-center;
}
.focus-row {
@apply mt-8 text-center;
}
.state-message {
@apply py-16 text-center text-fg-muted;
}
.card {
@apply rounded-card border border-line bg-surface p-5 md:p-6;
}