Refactor homepage mobile content layout

This commit is contained in:
2026-03-22 23:15:45 +01:00
parent 115f12141d
commit 5e300c84fa
2 changed files with 280 additions and 40 deletions
+132
View File
@@ -632,6 +632,104 @@ img, picture { display: block; max-width: 100%; height: auto; }
} }
.hero-card__body { padding: 18px; display: grid; gap: 10px; } .hero-card__body { padding: 18px; display: grid; gap: 10px; }
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.discover-shell {
max-width: 1200px;
margin: 24px auto 40px;
display: grid;
grid-template-columns: minmax(0, 1.2fr) minmax(280px, 0.8fr);
gap: 24px;
align-items: stretch;
}
.discover-shell__main,
.tag-panel,
.empty-state,
.quick-start {
background: var(--surface);
border: 1px solid var(--stroke);
border-radius: var(--radius);
box-shadow: var(--shadow);
}
.discover-shell__main {
padding: 22px;
display: grid;
gap: 18px;
}
.section-header--stack {
flex-direction: column;
align-items: flex-start;
text-align: left;
}
.discover-search {
margin: 0;
}
.discover-stats {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 12px;
}
.discover-stat {
padding: 14px;
background: var(--panel);
border: 1px solid var(--stroke);
border-radius: 14px;
display: grid;
gap: 4px;
}
.discover-stat strong {
font-size: clamp(1.1rem, 2vw, 1.5rem);
}
.discover-stat span {
color: var(--muted);
font-size: 14px;
}
.tag-panel {
padding: 16px;
display: grid;
gap: 12px;
box-shadow: none;
border-radius: 16px;
}
.tag-panel__head {
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
}
.tag-panel__head h3 {
margin: 0;
}
.tag-row--panel {
margin-top: 0;
}
.quick-start {
max-width: 1200px;
margin: 0 auto 40px;
padding: 22px;
display: grid;
gap: 18px;
}
.empty-state {
padding: 22px;
display: grid;
gap: 12px;
text-align: center;
}
.empty-state h3,
.empty-state p {
margin: 0;
}
.section-header { .section-header {
max-width: 1200px; max-width: 1200px;
margin: 0 auto 12px; margin: 0 auto 12px;
@@ -824,6 +922,40 @@ img, picture { display: block; max-width: 100%; height: auto; }
#backToTop.show { opacity: 1; transform: translateY(0); } #backToTop.show { opacity: 1; transform: translateY(0); }
#backToTop:hover { background: var(--panel-2); } #backToTop:hover { background: var(--panel-2); }
@media (max-width: 900px) {
.discover-shell {
grid-template-columns: 1fr;
gap: 16px;
margin: 16px auto 32px;
}
.discover-shell__main,
.quick-start,
.coming-features,
.empty-state {
padding: 18px;
}
.discover-stats {
grid-template-columns: 1fr;
}
.tag-panel__head {
flex-direction: column;
align-items: flex-start;
}
}
@media (max-width: 480px) {
.discover-shell__main,
.quick-start,
.coming-features,
.empty-state,
.tag-panel {
padding: 14px;
}
}
/* ══════════════════════════════════════════════════════════════════ /* ══════════════════════════════════════════════════════════════════
RESPONSIVE RESPONSIVE
══════════════════════════════════════════════════════════════════ */ ══════════════════════════════════════════════════════════════════ */
+129 -21
View File
@@ -108,6 +108,46 @@ $navHome = $t['home'];
$navLatest = $t['latest']; $navLatest = $t['latest'];
$navBasics = $t['basics']; $navBasics = $t['basics'];
$quickStartRecipes = array_slice($recipes, 0, 3);
$latestRecipes = array_slice($recipes, 0, 6);
$recipeCount = count($recipes);
$totalMinutes = array_sum(array_map(fn($recipe) => (int) ($recipe['total_time'] ?? 0), $recipes));
$averageMinutes = $recipeCount > 0 ? (int) ceil($totalMinutes / $recipeCount) : 0;
$activeTag = $tag !== '' ? $tag : null;
$tagCount = count($allTags);
$copy['en'] += [
'discover_title' => 'Find your next easy favorite.',
'discover_text' => 'Everything below the landing area is simplified for smaller screens: search, tap a tag, and jump into a recipe without cramped text blocks.',
'browse_tags' => 'Browse tags',
'quick_start_title' => 'Quick start',
'quick_start_text' => 'Open one of the recipes with the shortest path from craving to plate.',
'library_title' => 'Recipe library',
'library_text' => 'Clean cards, shorter descriptions, and tap-friendly actions for mobile browsing.',
'stats_recipes' => 'live recipes',
'stats_average' => 'avg. total time',
'stats_tags' => 'browseable tags',
'empty_title' => 'No recipes found yet',
'empty_text' => 'Try another search term or clear the active tag to see every recipe again.',
'view_recipe' => 'View recipe',
];
$copy['de'] += [
'discover_title' => 'Finde schnell dein nächstes Lieblingsrezept.',
'discover_text' => 'Alles unterhalb der Landingpage ist für kleine Screens vereinfacht: suchen, Tag antippen und ohne gequetschte Textblöcke ins Rezept springen.',
'browse_tags' => 'Tags entdecken',
'quick_start_title' => 'Schnell starten',
'quick_start_text' => 'Öffne eines der Rezepte mit dem kürzesten Weg von Appetit zu Teller.',
'library_title' => 'Rezeptübersicht',
'library_text' => 'Saubere Karten, kürzere Beschreibungen und gut tappbare Aktionen für Mobile.',
'stats_recipes' => 'Rezepte online',
'stats_average' => 'Ø Gesamtzeit',
'stats_tags' => 'durchsuchbare Tags',
'empty_title' => 'Noch keine Rezepte gefunden',
'empty_text' => 'Probiere einen anderen Suchbegriff oder entferne den aktiven Tag, um wieder alle Rezepte zu sehen.',
'view_recipe' => 'Rezept ansehen',
];
$t = $copy[$lang];
// Small helpers for URLs // Small helpers for URLs
$langQuery = ['lang' => $lang]; $langQuery = ['lang' => $lang];
$recipeUrl = fn(array $recipe) => '/recipe.php?' . http_build_query(['slug' => $recipe['slug']] + $langQuery); $recipeUrl = fn(array $recipe) => '/recipe.php?' . http_build_query(['slug' => $recipe['slug']] + $langQuery);
@@ -197,30 +237,56 @@ document.getElementById('landingCta').addEventListener('click', function(e){
</div> </div>
<?php endif; ?> <?php endif; ?>
<section class="hero"> <section class="discover-shell" id="basics">
<div class="hero-copy"> <div class="discover-shell__main">
<p class="eyebrow"><?php echo e($t['eyebrow']); ?></p> <div class="section-header section-header--stack">
<h1><?php echo $t['headline']; ?></h1> <p class="eyebrow"><?php echo e($t['basics']); ?></p>
<p><?php echo e($t['subhead']); ?></p> <h2><?php echo e($t['discover_title']); ?></h2>
<form class="search" method="get" action="/index.php"> <p><?php echo e($t['discover_text']); ?></p>
</div>
<form class="search discover-search" method="get" action="/index.php">
<input type="hidden" name="lang" value="<?php echo e($lang); ?>"> <input type="hidden" name="lang" value="<?php echo e($lang); ?>">
<input type="text" name="q" placeholder="<?php echo e($t['search_placeholder']); ?>" value="<?php echo e($q); ?>"> <label class="sr-only" for="recipe-search"><?php echo e($t['search_placeholder']); ?></label>
<input id="recipe-search" type="text" name="q" placeholder="<?php echo e($t['search_placeholder']); ?>" value="<?php echo e($q); ?>">
<?php if ($tag): ?> <?php if ($tag): ?>
<input type="hidden" name="tag" value="<?php echo e($tag); ?>"> <input type="hidden" name="tag" value="<?php echo e($tag); ?>">
<?php endif; ?> <?php endif; ?>
<button type="submit"><?php echo e($t['search_button']); ?></button> <button type="submit"><?php echo e($t['search_button']); ?></button>
</form> </form>
<div class="tag-row">
<?php foreach ($allTags as $tTag): ?> <div class="discover-stats" aria-label="Recipe overview">
<a class="tag<?php echo strtolower($tTag) === strtolower($tag ?? '') ? ' active' : ''; ?>" href="<?php echo e($tagUrl($tTag)); ?>">#<?php echo e($tTag); ?></a> <div class="discover-stat">
<?php endforeach; ?> <strong><?php echo e((string) $recipeCount); ?></strong>
<?php if ($tag): ?> <span><?php echo e($t['stats_recipes']); ?></span>
</div>
<div class="discover-stat">
<strong><?php echo e(format_minutes($averageMinutes)); ?></strong>
<span><?php echo e($t['stats_average']); ?></span>
</div>
<div class="discover-stat">
<strong><?php echo e((string) $tagCount); ?></strong>
<span><?php echo e($t['stats_tags']); ?></span>
</div>
</div>
<div class="tag-panel">
<div class="tag-panel__head">
<h3><?php echo e($t['browse_tags']); ?></h3>
<?php if ($activeTag): ?>
<a class="tag clear" href="/index.php?lang=<?php echo e($lang); ?>"><?php echo e($t['tag_clear']); ?></a> <a class="tag clear" href="/index.php?lang=<?php echo e($lang); ?>"><?php echo e($t['tag_clear']); ?></a>
<?php endif; ?> <?php endif; ?>
</div> </div>
<div class="tag-row tag-row--panel">
<?php foreach ($allTags as $tTag): ?>
<a class="tag<?php echo strtolower($tTag) === strtolower($activeTag ?? '') ? ' active' : ''; ?>" href="<?php echo e($tagUrl($tTag)); ?>">#<?php echo e($tTag); ?></a>
<?php endforeach; ?>
</div> </div>
</div>
</div>
<?php if ($featured): ?> <?php if ($featured): ?>
<div class="hero-card"> <aside class="discover-shell__feature hero-card">
<img src="<?php echo e($featured['hero']); ?>" alt="<?php echo e($featured['title']); ?>"> <img src="<?php echo e($featured['hero']); ?>" alt="<?php echo e($featured['title']); ?>">
<div class="hero-card__body"> <div class="hero-card__body">
<p class="pill"><?php echo e($t['featured']); ?></p> <p class="pill"><?php echo e($t['featured']); ?></p>
@@ -232,21 +298,54 @@ document.getElementById('landingCta').addEventListener('click', function(e){
</div> </div>
<a class="button" href="<?php echo e($recipeUrl($featured)); ?>"><?php echo e($t['cook_it']); ?></a> <a class="button" href="<?php echo e($recipeUrl($featured)); ?>"><?php echo e($t['cook_it']); ?></a>
</div> </div>
</div> </aside>
<?php endif; ?> <?php endif; ?>
</section> </section>
<section class="latest" id="latest"> <section class="quick-start">
<div class="section-header"> <div class="section-header section-header--stack">
<h2><?php echo e($t['latest_drops']); ?></h2> <h2><?php echo e($t['quick_start_title']); ?></h2>
<p><?php echo count($recipes); ?><?php echo $q || $tag ? $t['count_suffix_filtered'] : $t['count_suffix_default']; ?></p> <p><?php echo e($t['quick_start_text']); ?></p>
</div> </div>
<div class="grid">
<?php foreach ($recipes as $recipe): ?> <div class="grid grid--tight">
<?php foreach ($quickStartRecipes as $recipe): ?>
<article class="card"> <article class="card">
<a href="<?php echo e($recipeUrl($recipe)); ?>" class="card__image"> <a href="<?php echo e($recipeUrl($recipe)); ?>" class="card__image">
<img src="<?php echo e($recipe['hero']); ?>" alt="<?php echo e($recipe['title']); ?>"> <img src="<?php echo e($recipe['hero']); ?>" alt="<?php echo e($recipe['title']); ?>">
<?php if (!empty($recipe['category'])): ?>
<span class="pill pill--ghost"><?php echo e($recipe['category']); ?></span> <span class="pill pill--ghost"><?php echo e($recipe['category']); ?></span>
<?php endif; ?>
</a>
<div class="card__body">
<h3><a href="<?php echo e($recipeUrl($recipe)); ?>"><?php echo e($recipe['title']); ?></a></h3>
<div class="meta">
<span>⏱ <?php echo format_minutes((int) ($recipe['total_time'] ?? 0)); ?></span>
<span>🙂 <?php echo e($recipe['difficulty']); ?></span>
</div>
<a class="button" href="<?php echo e($recipeUrl($recipe)); ?>"><?php echo e($t['view_recipe']); ?></a>
</div>
</article>
<?php endforeach; ?>
</div>
</section>
<section class="latest" id="latest">
<div class="section-header section-header--stack">
<h2><?php echo e($t['library_title']); ?></h2>
<p><?php echo e($t['library_text']); ?></p>
<p><?php echo $recipeCount; ?><?php echo $q || $tag ? $t['count_suffix_filtered'] : $t['count_suffix_default']; ?></p>
</div>
<?php if (!empty($latestRecipes)): ?>
<div class="grid">
<?php foreach ($latestRecipes as $recipe): ?>
<article class="card">
<a href="<?php echo e($recipeUrl($recipe)); ?>" class="card__image">
<img src="<?php echo e($recipe['hero']); ?>" alt="<?php echo e($recipe['title']); ?>">
<?php if (!empty($recipe['category'])): ?>
<span class="pill pill--ghost"><?php echo e($recipe['category']); ?></span>
<?php endif; ?>
</a> </a>
<div class="card__body"> <div class="card__body">
<h3><a href="<?php echo e($recipeUrl($recipe)); ?>"><?php echo e($recipe['title']); ?></a></h3> <h3><a href="<?php echo e($recipeUrl($recipe)); ?>"><?php echo e($recipe['title']); ?></a></h3>
@@ -255,19 +354,28 @@ document.getElementById('landingCta').addEventListener('click', function(e){
<span>⏱ <?php echo format_minutes((int) ($recipe['total_time'] ?? 0)); ?></span> <span>⏱ <?php echo format_minutes((int) ($recipe['total_time'] ?? 0)); ?></span>
<span>🙂 <?php echo e($recipe['difficulty']); ?></span> <span>🙂 <?php echo e($recipe['difficulty']); ?></span>
</div> </div>
<?php if (!empty($recipe['tags'])): ?>
<div class="tags"> <div class="tags">
<?php foreach ($recipe['tags'] as $tTag): ?> <?php foreach ($recipe['tags'] as $tTag): ?>
<a href="<?php echo e($tagUrl($tTag)); ?>" class="tag">#<?php echo e($tTag); ?></a> <a href="<?php echo e($tagUrl($tTag)); ?>" class="tag">#<?php echo e($tTag); ?></a>
<?php endforeach; ?> <?php endforeach; ?>
</div> </div>
<?php endif; ?>
</div> </div>
</article> </article>
<?php endforeach; ?> <?php endforeach; ?>
</div> </div>
<?php else: ?>
<article class="empty-state">
<h3><?php echo e($t['empty_title']); ?></h3>
<p><?php echo e($t['empty_text']); ?></p>
<a class="button" href="/index.php?lang=<?php echo e($lang); ?>"><?php echo e($t['tag_clear']); ?></a>
</article>
<?php endif; ?>
</section> </section>
<section class="coming-features" id="coming-features"> <section class="coming-features" id="coming-features">
<div class="section-header"> <div class="section-header section-header--stack">
<h2><?php echo e($t['coming_features']); ?></h2> <h2><?php echo e($t['coming_features']); ?></h2>
<p><?php echo e($t['coming_features_sub']); ?></p> <p><?php echo e($t['coming_features_sub']); ?></p>
</div> </div>