From 2879433bd335af6a5bc3c9c25cf8b855c224e1e2 Mon Sep 17 00:00:00 2001 From: Maurice Date: Thu, 17 Sep 2026 15:05:29 +0200 Subject: [PATCH] fix(dawarich): the panel opens to its full height and the rail scrolls past it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Capping it was the wrong half of the fix: the stays were reachable but the panel was cut off at half the rail, which is not what opening something means. It sits inside the places list's own scroller now, above the rows, so it simply grows to whatever the day's stays need — 3350px for forty of them — and the rail scrolls past it to the places. No second scrollbar, no fold. As a band of its own it could never do that: the list is the flex child that scrolls, so anything unbounded above it squeezed the list to nothing and took the rail's scrolling with it. --- .../src/components/Planner/PlacesSidebar.tsx | 49 ++++++++----------- .../components/Planner/PlacesSidebarList.tsx | 16 +++++- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/client/src/components/Planner/PlacesSidebar.tsx b/client/src/components/Planner/PlacesSidebar.tsx index a9d5f6f9b..8cb05b3ef 100644 --- a/client/src/components/Planner/PlacesSidebar.tsx +++ b/client/src/components/Planner/PlacesSidebar.tsx @@ -65,34 +65,27 @@ const PlacesSidebar = React.memo(function PlacesSidebar(props: PlacesSidebarProp )} - {/* Stays Dawarich recorded on these dates, waiting to be reviewed (#2279). - Above the list because that is what they become, and the panel renders - nothing at all when there is nothing pending — an integration that is - connected and quiet should be invisible rather than a permanent empty - card. */} - {/* Capped and scrolling on its own. Open, the panel is as tall as the day has stays — - ten of them on a day of driving — and with nothing holding it back it pushed the - places list, which is the flex child that scrolls, down to nothing: the rail - stopped scrolling and half the stays sat below the bottom edge with no way to - reach them. Half the rail at most, so the list it sits above is always still a - list. */} -
- days.map(day => ({ - id: day.id, - ...formatDayOption(day.day_number, day.date, locale, t), - }))} - // The place it just created belongs on the map and in the list - // now, not after a reload. - onAccepted={() => { void refreshTripAfterAccept(tripId) }} - initiallyCollapsed - /> -
- - {/* Liste */} - + {/* Liste, with the Dawarich stays riding on top of it inside the same scroller — + see the `header` prop for why they are not a band of their own. */} + + days.map(day => ({ + id: day.id, + ...formatDayOption(day.day_number, day.date, locale, t), + }))} + // The place it just created belongs on the map and in the list + // now, not after a reload. + onAccepted={() => { void refreshTripAfterAccept(tripId) }} + initiallyCollapsed + /> + + )} + /> {dayPickerPlace && } {listImportOpen && } diff --git a/client/src/components/Planner/PlacesSidebarList.tsx b/client/src/components/Planner/PlacesSidebarList.tsx index 1c0f60799..ccc1843ff 100644 --- a/client/src/components/Planner/PlacesSidebarList.tsx +++ b/client/src/components/Planner/PlacesSidebarList.tsx @@ -1,10 +1,21 @@ -import { Fragment } from 'react' +import { Fragment, type ReactNode } from 'react' import EmptyState from '../shared/EmptyState' import { MemoPlaceRow } from './PlacesSidebarRow' import type { SidebarState } from './usePlacesSidebar' import { usePluginViewContributions, PluginCardFooter } from '../Plugins/PluginContributions' -export function PlacesList(S: SidebarState) { +export function PlacesList({ header, ...S }: SidebarState & { + /** + * A block that sits above the places and scrolls WITH them. + * + * The Dawarich panel lives here rather than in a band of its own above the list. As its + * own band it could not grow: the list is the flex child that scrolls, so a panel with + * ten stays in it squeezed the list to nothing and took the rail's scrolling with it, + * and capping the panel left half its stays below a fold with no way to reach them. + * Inside the scroller it simply opens to its full height and the rail scrolls past it. + */ + header?: ReactNode +}) { const { filtered, scrollContainerRef, onScrollTopChange, filter, t, canEditPlaces, onAddPlace, categories, selectedPlaceId, plannedIds, inDaySet, selectedIds, selectMode, selectedDayId, @@ -14,6 +25,7 @@ export function PlacesList(S: SidebarState) { const contribFor = usePluginViewContributions('places', tripId) return (
onScrollTopChange?.((e.currentTarget as HTMLElement).scrollTop)}> + {header} {filtered.length === 0 ? ( /* The mascot and one line, the shape every other empty state in TREK has. The add link stays as the state's action: an empty list of places is