tablet: fix cart scroll — flex-end + overflow-y:auto doesn't scroll in WebKit
Follow-up to the #39 fix in d274275, which mara reports still doesn't
scroll in practice.
The bug: overflow-y: auto and justify-content: flex-end on the *same* flex
column is a known WebKit/Safari interop gap — the flex-end-justified
overflow gets clipped at the container bounds instead of becoming a
scrollable region, so nothing actually changed from the user's side despite
the CSS being 'correct' per spec. This app targets iOS Safari 12+
(vite.config.ts legacy targets), squarely in the affected range.
Fix: split the concerns onto two elements. .cart-items is now a plain
overflow-y: auto scroll container with no alignment property. The new
inner .cart-items-inner wrapper carries display:flex/flex-direction:column/
justify-content:flex-end, with min-height: 100% (a floor, not a fixed
height) so it still bottom-anchors a short list but grows past 100% and
scrolls normally in the outer container once content overflows it.
Build clean.
This commit is contained in:
parent
1d99881e88
commit
cb316d16d1
2 changed files with 48 additions and 32 deletions
|
|
@ -213,11 +213,25 @@ button.danger { background: #5a2a2a; border-color: #7a3a3a; color: #fff; }
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
/* #39 follow-up: overflow-y: auto directly on a flex column that also has
|
||||||
|
justify-content: flex-end doesn't reliably scroll in WebKit/Safari (the
|
||||||
|
iOS 12+ targets this app builds for) — the flex-end-justified overflow
|
||||||
|
gets clipped instead of becoming a scrollable region, so from the user's
|
||||||
|
side it looked identical to the original overflow: hidden bug. Standard
|
||||||
|
workaround: the overflow/scroll and the flex-end alignment can't live on
|
||||||
|
the same element — .cart-items is now a plain scroll container (no
|
||||||
|
justify-content), and .cart-items-inner is the flex column that actually
|
||||||
|
bottom-anchors short lists via min-height: 100% (a floor, not a fixed
|
||||||
|
height, so it still grows past 100% and scrolls normally once content
|
||||||
|
overflows it). */
|
||||||
.cart-items {
|
.cart-items {
|
||||||
flex: 1 1 0;
|
flex: 1 1 0;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
.cart-items-inner {
|
||||||
|
min-height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
|
|
||||||
|
|
@ -198,45 +198,47 @@ export function Sale({ config, onChangeBar }: Props) {
|
||||||
|
|
||||||
<div class="cart">
|
<div class="cart">
|
||||||
<div class="cart-items">
|
<div class="cart-items">
|
||||||
{isEmpty && <div class="cart-line muted">Keine Einträge</div>}
|
<div class="cart-items-inner">
|
||||||
{lines.map((l, i) => {
|
{isEmpty && <div class="cart-line muted">Keine Einträge</div>}
|
||||||
const d = drinkById.get(l.drink_id);
|
{lines.map((l, i) => {
|
||||||
if (!d) return null;
|
const d = drinkById.get(l.drink_id);
|
||||||
return (
|
if (!d) return null;
|
||||||
<div key={i} class="cart-line">
|
return (
|
||||||
|
<div key={i} class="cart-line">
|
||||||
|
<div class="cart-line-label">
|
||||||
|
<button class="qty-btn" onClick={() => incLine(l.drink_id, -1)} aria-label="weniger">
|
||||||
|
−
|
||||||
|
</button>
|
||||||
|
<span>{l.qty}× {d.name}</span>
|
||||||
|
<button class="qty-btn" onClick={() => incLine(l.drink_id, 1)} aria-label="mehr">
|
||||||
|
+
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<span>{formatCents(d.price_cents * l.qty)}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{bar.pfand_cents > 0 && pfandCount > 0 && (
|
||||||
|
<div class="cart-line pfand">
|
||||||
|
<span>{pfandCount}× Pfand</span>
|
||||||
|
<span>{formatCents(bar.pfand_cents * pfandCount)}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{pfandReturns > 0 && (
|
||||||
|
<div class="cart-line return">
|
||||||
<div class="cart-line-label">
|
<div class="cart-line-label">
|
||||||
<button class="qty-btn" onClick={() => incLine(l.drink_id, -1)} aria-label="weniger">
|
<button class="qty-btn" onClick={() => incPfandReturns(-1)} aria-label="weniger">
|
||||||
−
|
−
|
||||||
</button>
|
</button>
|
||||||
<span>{l.qty}× {d.name}</span>
|
<span>{pfandReturns}× Pfand zurück</span>
|
||||||
<button class="qty-btn" onClick={() => incLine(l.drink_id, 1)} aria-label="mehr">
|
<button class="qty-btn" onClick={() => incPfandReturns(1)} aria-label="mehr">
|
||||||
+
|
+
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<span>{formatCents(d.price_cents * l.qty)}</span>
|
<span>{formatCents(-bar.pfand_cents * pfandReturns)}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
)}
|
||||||
})}
|
</div>
|
||||||
{bar.pfand_cents > 0 && pfandCount > 0 && (
|
|
||||||
<div class="cart-line pfand">
|
|
||||||
<span>{pfandCount}× Pfand</span>
|
|
||||||
<span>{formatCents(bar.pfand_cents * pfandCount)}</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{pfandReturns > 0 && (
|
|
||||||
<div class="cart-line return">
|
|
||||||
<div class="cart-line-label">
|
|
||||||
<button class="qty-btn" onClick={() => incPfandReturns(-1)} aria-label="weniger">
|
|
||||||
−
|
|
||||||
</button>
|
|
||||||
<span>{pfandReturns}× Pfand zurück</span>
|
|
||||||
<button class="qty-btn" onClick={() => incPfandReturns(1)} aria-label="mehr">
|
|
||||||
+
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<span>{formatCents(-bar.pfand_cents * pfandReturns)}</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div class={`cart-total ${total < 0 ? 'negative' : ''}`}>
|
<div class={`cart-total ${total < 0 ? 'negative' : ''}`}>
|
||||||
{formatCents(total)}
|
{formatCents(total)}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue