mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
fix(mobile): keep the dashboard filter row from widening the layout viewport
This commit is contained in:
@@ -15,7 +15,14 @@ body { height: 100%; overflow: auto; overscroll-behavior: none; -webkit-overflow
|
||||
reloads the installed PWA. Desktop/tablet keep the rules above. */
|
||||
@media (max-width: 767px) {
|
||||
html { overflow: visible; overscroll-behavior: none; }
|
||||
body { height: auto; overflow: visible; }
|
||||
/* overflow-x clip (not hidden: clip creates no scroll container) so a screen
|
||||
that accidentally overflows sideways cannot widen the document. Android's
|
||||
forced-zoom setting reacts to a wider document by growing the layout
|
||||
viewport that position:fixed resolves against, which pushed the top bar
|
||||
and the dock off the right edge on narrow phones. On body, never on html:
|
||||
body's overflow only propagates to the viewport while html stays visible,
|
||||
and the shared body scroll lock relies on that propagation. */
|
||||
body { height: auto; overflow: visible; overflow-x: clip; }
|
||||
/* Transparent so the shell's own background layer, which sits behind the page
|
||||
on a negative z-index, is not painted over: a negative layer goes above the
|
||||
canvas but below the background of ordinary blocks, and body is one. The
|
||||
|
||||
@@ -363,3 +363,14 @@
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
/* Horizontal scroller without a visible scrollbar, for control rows that must
|
||||
survive narrow viewports and large system font scales (dashboard filter). */
|
||||
.m-hscroll {
|
||||
overflow-x: auto;
|
||||
overscroll-behavior-x: contain;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
.m-hscroll::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -132,17 +132,25 @@ export default function MDashboard(): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
<div className="mt-[14px] flex items-center gap-[7px]">
|
||||
<MSegmented<TripFilter>
|
||||
value={tripFilter}
|
||||
onChange={setTripFilter}
|
||||
variant="intrinsic"
|
||||
options={[
|
||||
{ value: 'planned', label: t('dashboard.filter.planned') },
|
||||
{ value: 'archive', label: t('dashboard.archived') },
|
||||
{ value: 'completed', label: t('dashboard.mobile.completed') },
|
||||
]}
|
||||
/>
|
||||
<MIconBtn ariaLabel={t('dashboard.subscribeAllTrips')} size={36} className="ml-auto" onClick={() => setSubOpen(true)}>
|
||||
{/* The chips scroll inside their own flexible box on narrow viewports
|
||||
or large system font scales; without it this row was the widest
|
||||
thing on the page and dragged the fixed bars off-screen under
|
||||
Android's forced zoom. min-w-max keeps the pill track wrapping
|
||||
its chips instead of getting squeezed to the box. */}
|
||||
<div className="m-hscroll min-w-0 flex-1">
|
||||
<MSegmented<TripFilter>
|
||||
value={tripFilter}
|
||||
onChange={setTripFilter}
|
||||
variant="intrinsic"
|
||||
className="min-w-max"
|
||||
options={[
|
||||
{ value: 'planned', label: t('dashboard.filter.planned') },
|
||||
{ value: 'archive', label: t('dashboard.archived') },
|
||||
{ value: 'completed', label: t('dashboard.mobile.completed') },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<MIconBtn ariaLabel={t('dashboard.subscribeAllTrips')} size={36} className="flex-none" onClick={() => setSubOpen(true)}>
|
||||
<CalendarPlus size={15} strokeWidth={2} className="text-m-muted" />
|
||||
</MIconBtn>
|
||||
<button
|
||||
|
||||
@@ -539,4 +539,19 @@ describe('MDashboard', () => {
|
||||
await waitFor(() =>
|
||||
expect(screen.queryByText('dashboard.subscribeAllTripsDesc')).not.toBeInTheDocument());
|
||||
});
|
||||
|
||||
it('FE-MOB-DASH-038: the filter row cannot widen the document on narrow phones (#discord S26)', async () => {
|
||||
render(<MDashboard />);
|
||||
|
||||
// The chip track scrolls inside its own flexible box; without this the row
|
||||
// was the widest element on the page and dragged the fixed bars off-screen
|
||||
// under Android's forced zoom.
|
||||
const chip = await screen.findByText('dashboard.filter.planned');
|
||||
const track = chip.closest('button')!.parentElement as HTMLElement;
|
||||
expect(track.className).toContain('min-w-max');
|
||||
const wrapper = track.parentElement as HTMLElement;
|
||||
expect(wrapper.className).toContain('m-hscroll');
|
||||
expect(wrapper.className).toContain('min-w-0');
|
||||
expect(wrapper.className).toContain('flex-1');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user