feat(ui): Slider mit Vor-/Zurück-Buttons und Touch/Mouse-Drag für Warengruppen
All checks were successful
Build and Deploy / build (push) Successful in 54s

This commit is contained in:
DanielS
2026-09-22 23:07:58 +02:00
parent f59923fb57
commit 8fb76690fe

View File

@@ -154,20 +154,54 @@
display: none;
}
/* Swipebar Kategorien */
.category-swipe-wrapper {
/* Interaktiver Slider / Swipe Container */
.slider-nav-container {
position: relative;
display: flex;
align-items: center;
margin: 0 -16px;
padding: 0 16px;
padding: 0 8px;
}
.slider-arrow {
background: var(--card-bg);
border: 1px solid var(--card-border);
color: var(--text);
width: 32px;
height: 32px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-size: 14px;
z-index: 2;
flex-shrink: 0;
backdrop-filter: blur(10px);
transition: all 0.2s;
}
.slider-arrow:hover {
background: var(--primary);
color: var(--bg);
border-color: var(--primary);
}
.category-swipe {
display: flex;
gap: 8px;
overflow-x: auto;
padding-bottom: 4px;
scroll-behavior: smooth;
padding: 6px 8px;
scrollbar-width: none;
-webkit-overflow-scrolling: touch;
flex: 1;
cursor: grab;
user-select: none;
}
.category-swipe:active {
cursor: grabbing;
}
.category-swipe::-webkit-scrollbar {
@@ -176,7 +210,7 @@
.category-pill {
flex: 0 0 auto;
padding: 8px 16px;
padding: 8px 18px;
border-radius: 999px;
font-size: 13px;
font-weight: 600;
@@ -185,20 +219,24 @@
border: 1px solid var(--card-border);
cursor: pointer;
white-space: nowrap;
transition: all 0.2s ease;
user-select: none;
transition: all 0.25s ease;
display: inline-flex;
align-items: center;
gap: 6px;
}
.category-pill:hover {
color: var(--text);
border-color: rgba(255, 255, 255, 0.2);
transform: translateY(-1px);
}
.category-pill.active {
background: var(--primary);
color: var(--bg);
border-color: var(--primary);
box-shadow: 0 0 12px var(--primary-glow);
box-shadow: 0 0 14px var(--primary-glow);
transform: scale(1.03);
}
.section-title {
@@ -320,11 +358,13 @@
<button id="clear-search" class="clear-search">✕</button>
</div>
<!-- Swipebar Warengruppen -->
<div class="category-swipe-wrapper">
<!-- Warengruppen Slider mit Pfeilen & Touch Drag -->
<div class="slider-nav-container">
<button id="slide-left" class="slider-arrow" aria-label="Zurück">‹</button>
<div id="category-swipe" class="category-swipe">
<button class="category-pill active" data-id="all">Alle Artikel</button>
</div>
<button id="slide-right" class="slider-arrow" aria-label="Weiter">›</button>
</div>
<!-- Getränkeliste -->
@@ -351,12 +391,12 @@
const data = await res.json();
allCategories = data.categories || [];
// Globale Texte & Theme anwenden
if (data.settings) {
applySettings(data.settings);
}
renderCategoryPills();
initSliderControls();
renderMenu();
} catch (err) {
container.innerHTML = '<div class="card" style="color:#ef4444; text-align:center;">Fehler beim Laden der Speisekarte.</div>';
@@ -372,7 +412,6 @@
if (s.site_badge) document.getElementById('site-badge').textContent = s.site_badge;
if (s.site_footer) document.getElementById('site-footer').textContent = s.site_footer;
// Theme CSS Variablen dynamisch setzen
const root = document.documentElement;
if (s.theme_bg) root.style.setProperty('--bg', s.theme_bg);
if (s.theme_card_bg) root.style.setProperty('--card-bg', s.theme_card_bg);
@@ -399,7 +438,7 @@
swipeEl.innerHTML = pillsHtml;
swipeEl.querySelectorAll('.category-pill').forEach(btn => {
btn.addEventListener('click', (e) => {
btn.addEventListener('click', () => {
swipeEl.querySelectorAll('.category-pill').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
activeCategoryId = btn.dataset.id;
@@ -409,6 +448,43 @@
});
}
// Slider Controls (Pfeile + Mouse Drag)
function initSliderControls() {
const slider = document.getElementById('category-swipe');
const btnLeft = document.getElementById('slide-left');
const btnRight = document.getElementById('slide-right');
btnLeft.addEventListener('click', () => {
slider.scrollBy({ left: -160, behavior: 'smooth' });
});
btnRight.addEventListener('click', () => {
slider.scrollBy({ left: 160, behavior: 'smooth' });
});
// Mouse Drag Unterstützung am Desktop
let isDown = false;
let startX;
let scrollLeft;
slider.addEventListener('mousedown', (e) => {
isDown = true;
startX = e.pageX - slider.offsetLeft;
scrollLeft = slider.scrollLeft;
});
slider.addEventListener('mouseleave', () => { isDown = false; });
slider.addEventListener('mouseup', () => { isDown = false; });
slider.addEventListener('mousemove', (e) => {
if (!isDown) return;
e.preventDefault();
const x = e.pageX - slider.offsetLeft;
const walk = (x - startX) * 1.5;
slider.scrollLeft = scrollLeft - walk;
});
}
function renderMenu() {
const container = document.getElementById('menu-container');
const query = searchQuery.trim().toLowerCase();