Turnen: Tab-Navigation für Gruppen mit vielen Trainingszeiten

group-schedule um eine Tab-Leiste (group-tabs) erweitert: bei Disziplinen mit
vielen Gruppen (z. B. Eltern-Kind-Turnen) werden die Gruppen als Tabs gruppiert
statt endlos gestapelt. JS (group-tabs.js) als progressive enhancement — ohne JS
bleiben alle Panels sichtbar. Begleitend Feinschliff an group-card/-list/schedule-row.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HGzc6GhWhmLJt1jC2q1SRZ
This commit is contained in:
2026-06-20 20:48:39 +02:00
parent 1552f974aa
commit b40f36aee6
4 changed files with 208 additions and 37 deletions

View File

@@ -2074,6 +2074,72 @@
/* === group-list (Turn-Gruppen einer Disziplin) === */
.group-list__title {
margin-bottom: 1.5rem;
text-align: center;
}
/* === group-tabs (Tab-Navigation für rich Gruppen) === */
.group-tabs__bar {
display: flex;
justify-content: center;
overflow-x: auto;
scrollbar-width: none;
margin-bottom: 2rem;
gap: 0;
}
.group-tabs__bar::-webkit-scrollbar { display: none; }
.group-tabs__tab {
flex-shrink: 0;
padding: 0.7rem 1.4rem;
background: none;
border: none;
box-shadow: inset 0 -2px 0 var(--clr-glass-border);
font-family: var(--ff-body);
font-size: var(--fs-500);
color: var(--clr-text-muted);
cursor: pointer;
white-space: nowrap;
transition: color var(--transition), box-shadow var(--transition);
}
.group-tabs__tab:hover {
color: var(--clr-text);
}
.group-tabs__tab[aria-selected="true"] {
color: var(--clr-text);
box-shadow: inset 0 -2px 0 var(--clr-accent);
}
.group-tabs__tab:focus-visible {
outline: 2px solid var(--clr-accent);
outline-offset: -2px;
}
/* Panel-Karte übernimmt das bestehende group-card--stacked-Layout */
.group-tabs__panel {
display: grid;
grid-template-columns: 1.6fr 1fr;
gap: 3rem;
align-items: start;
padding: 2.25rem 2.5rem;
background: var(--clr-glass-bg);
border: 1px solid var(--clr-glass-border);
border-radius: var(--radius-card);
}
/* display:grid überschreibt den UA-Stil [hidden]{display:none} — explizit korrigieren */
.group-tabs__panel[hidden] {
display: none;
}
@media (max-width: 768px) {
.group-tabs__panel {
grid-template-columns: 1fr;
gap: 1.75rem;
padding: 1.6rem 1.75rem;
}
}
/* Schlichte Gruppen (z. B. Kurse) als Raster, beschreibende Gruppen gestapelt. */
@@ -2086,7 +2152,7 @@
.group-list--stacked {
display: flex;
flex-direction: column;
gap: 1.25rem;
gap: 2.75rem;
}
.group-card {
@@ -2100,15 +2166,15 @@
.group-list--stacked .group-card {
display: grid;
grid-template-columns: 1.6fr 1fr;
gap: 2.5rem;
gap: 3rem;
align-items: start;
padding: 2rem 2.25rem;
padding: 2.25rem 2.5rem;
}
@media (max-width: 768px) {
.group-list--stacked .group-card {
grid-template-columns: 1fr;
gap: 1.5rem;
gap: 1.75rem;
padding: 1.6rem 1.75rem 1.75rem;
}
}
@@ -2118,47 +2184,69 @@
max-width: 64ch;
}
/* Name links, Level-Chip rechts vertikal zentriert */
.group-card__header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
flex-wrap: wrap;
}
.group-card__name {
font-size: clamp(1.9rem, 1.5rem + 1.2vw, 2.3rem);
font-size: clamp(2.2rem, 1.7rem + 1.5vw, 2.8rem);
line-height: var(--lh-heading);
}
.group-card__level {
margin: -0.15rem 0 0;
font-size: var(--fs-500);
flex-shrink: 0;
padding: 0.15rem 0.5rem;
font-size: var(--fs-400);
text-transform: uppercase;
letter-spacing: 0.06em;
letter-spacing: 0.07em;
color: var(--clr-text-muted);
border: 1px solid var(--clr-glass-border-strong);
border-radius: 999px;
white-space: nowrap;
}
/* Intro = Lead-Paragraph, deutlich abgesetzt vom Level-Chip */
.group-card__intro {
margin: 0.85rem 0 0;
margin: 1.25rem 0 0;
font-size: var(--fs-600);
line-height: 1.65;
color: var(--clr-text);
}
/* Detail-Abschnitte: Akzent-Randstrich links als visueller Anker */
.group-card__detail-heading {
margin: 1.6rem 0 0;
/* Body-Schrift (Abel) als Eyebrow — Coolvetica wäre in dieser Größe unleserlich. */
margin: 2.25rem 0 0;
padding-left: 0.7rem;
border-left: 2px solid var(--clr-accent);
font-family: var(--ff-body);
font-size: var(--fs-500);
font-weight: 400;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--clr-accent);
letter-spacing: 0.07em;
color: var(--clr-text);
}
.group-card__detail-text {
margin: 0.4rem 0 0;
line-height: 1.65;
margin: 0.6rem 0 0;
padding-left: 0.7rem;
font-size: var(--fs-600);
line-height: 1.72;
color: var(--clr-text);
}
.group-card__recommendation {
margin: 1.6rem 0 0;
padding-top: 1.1rem;
margin: 2rem 0 0;
padding: 1rem 1rem 0;
border-top: 1px solid var(--clr-glass-border);
font-size: var(--fs-500);
font-style: italic;
line-height: 1.6;
color: var(--clr-text-muted);
}
/* Trainingszeiten-Panel in der Karte. */
@@ -2166,20 +2254,23 @@
margin-top: 1.25rem;
}
.group-list--stacked .group-card__schedule {
.group-list--stacked .group-card__schedule,
.group-tabs .group-card__schedule {
margin-top: 0;
padding: 1.5rem 1.6rem;
padding: 1.75rem;
background: var(--clr-bg);
border: 1px solid var(--clr-glass-border);
border-radius: var(--radius-card);
border-top: 2px solid var(--clr-accent);
}
.group-card__schedule-title {
display: flex;
align-items: center;
gap: 0.5rem;
margin: 0 0 0.85rem;
font-size: var(--fs-600);
margin: 0 0 1.1rem;
font-size: var(--fs-650);
letter-spacing: 0.01em;
}
.group-card__schedule-icon {
@@ -2188,7 +2279,9 @@
}
.group-card__trainers {
margin: 0.85rem 0 0;
margin: 1rem 0 0;
padding-top: 0.75rem;
border-top: 1px solid var(--clr-glass-border);
font-size: var(--fs-500);
line-height: 1.5;
}
@@ -2206,7 +2299,7 @@
}
.schedule-row {
padding: 0.7rem 0;
padding: 0.85rem 0;
border-bottom: 1px solid var(--clr-glass-border);
}
@@ -2215,9 +2308,12 @@
.schedule-row__label {
display: block;
margin-bottom: 0.2rem;
font-size: var(--fs-600);
color: var(--clr-text);
margin-bottom: 0.3rem;
font-size: var(--fs-500);
text-transform: uppercase;
letter-spacing: 0.07em;
color: var(--clr-accent);
font-family: var(--ff-body);
}
.schedule-row__when {
@@ -2227,28 +2323,32 @@
gap: 1rem;
}
.schedule-row__day {
font-size: var(--fs-600);
color: var(--clr-text);
}
.schedule-row__time {
font-size: var(--fs-600);
text-align: right;
white-space: nowrap;
color: var(--clr-text);
}
.schedule-row__note {
display: block;
margin-top: 0.15rem;
margin-top: 0.2rem;
font-size: var(--fs-500);
color: var(--clr-text-muted);
}
.schedule-row__trainers {
display: block;
margin-top: 0.25rem;
margin-top: 0.3rem;
font-size: var(--fs-500);
line-height: 1.5;
color: var(--clr-text-muted);
}
.schedule-row__trainers-label {
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--clr-text-muted);
}

View File

@@ -0,0 +1,31 @@
(function () {
'use strict';
function init(el) {
const buttons = [...el.querySelectorAll('[role="tab"]')];
const panels = [...el.querySelectorAll('[role="tabpanel"]')];
// Alle außer dem ersten verstecken
panels.forEach(function (p, i) { if (i > 0) p.hidden = true; });
buttons.forEach(function (btn, i) {
btn.addEventListener('click', function () { activate(i); });
btn.addEventListener('keydown', function (e) {
if (e.key === 'ArrowRight') { e.preventDefault(); activate((i + 1) % buttons.length); }
if (e.key === 'ArrowLeft') { e.preventDefault(); activate((i - 1 + buttons.length) % buttons.length); }
if (e.key === 'Home') { e.preventDefault(); activate(0); }
if (e.key === 'End') { e.preventDefault(); activate(buttons.length - 1); }
});
});
function activate(index) {
buttons.forEach(function (b, i) {
b.setAttribute('aria-selected', i === index ? 'true' : 'false');
});
panels.forEach(function (p, i) { p.hidden = i !== index; });
buttons[index].focus();
}
}
document.querySelectorAll('[data-group-tabs]').forEach(init);
}());