fix(places): centre the empty states, and give the details column one too

Five states, one shape. EmptyState grows a `fill` option: the stack already
centres what it holds, but with no height of its own there was nothing to centre
inside, so every one of them sat pinned under the header of its column.

Optically centred rather than geometrically. The extra room goes underneath,
which puts the mascot slightly above the middle: in a column you can scroll,
dead centre reads as having fallen to the bottom the moment the list is short.

The details column's own placeholder joins them, with the idle look rather than
the sad one, because nothing being picked yet is a state and not a fault. Its
line is shortened to fit on one: "Pick a result to see more", in all 23
languages.

The corridor panel, the saved-places list and the place details all dropped
`compact`, so the five now read at the same size as the road trip rail.
This commit is contained in:
Maurice
2026-09-08 17:16:48 +02:00
committed by Maurice
parent 4a88dbcbcf
commit 900e4806ad
29 changed files with 79 additions and 37 deletions
+17 -1
View File
@@ -23,6 +23,7 @@ export default function EmptyState({
surface = 'var(--bg-card)',
layout = 'stack',
compact = false,
fill = false,
className = '',
action,
}: {
@@ -40,13 +41,28 @@ export default function EmptyState({
* about why the list below is blank.
*/
compact?: boolean
/**
* Fill the parent and sit in the middle of it.
*
* The stack already centres what it contains, but with no height of its own
* `justify-center` has nothing to centre inside, so the state lands under
* whatever sits above it. A state that stands for a whole empty column wants
* the middle of that column; one that sits inline in a page does not, which is
* why this is a choice rather than the default. The parent has to be the one
* with the height, which every scroll container here already is.
*
* Optically centred rather than geometrically: the extra room goes underneath,
* which lands the mascot slightly above the middle. In a column you can scroll,
* dead centre reads as "fell to the bottom" the moment the list is short.
*/
fill?: boolean
className?: string
/** Optional call to action under the title, for states that have an obvious next step. */
action?: ReactNode
}) {
const layoutClasses = layout === 'row'
? 'flex flex-row items-center justify-center gap-3 px-6 py-3'
: 'flex flex-col items-center justify-center gap-3 px-6 py-12 text-center'
: `flex flex-col items-center justify-center gap-3 px-6 text-center ${fill ? 'min-h-full pt-4 pb-14' : 'py-12'}`
return (
<div
className={`${layoutClasses} ${className}`}