Merge feat/mobile-ux-polish: berth/header/tab/contacts mobile fixes

# Conflicts:
#	src/components/clients/contacts-editor.tsx
This commit is contained in:
Matt Ciaccio
2026-05-03 16:20:12 +02:00
4 changed files with 95 additions and 73 deletions

View File

@@ -178,7 +178,10 @@ export function BerthDetailHeader({ berth }: BerthDetailHeaderProps) {
return (
<>
<DetailHeaderStrip>
<div className="flex items-start gap-4">
{/* Stacks vertically on phone widths so the action buttons don't
squeeze the area subtitle into a two-line wrap. From sm up the
title/area block sits side-by-side with the action buttons. */}
<div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:gap-4">
<div className="flex-1 min-w-0">
<div className="flex items-center gap-3 flex-wrap">
<h1 className="hidden sm:block text-2xl font-bold text-foreground">
@@ -193,7 +196,7 @@ export function BerthDetailHeader({ berth }: BerthDetailHeaderProps) {
{berth.area && <p className="text-muted-foreground mt-1">{berth.area}</p>}
</div>
<div className="flex flex-wrap items-center gap-2 shrink-0">
<div className="flex flex-wrap items-center gap-2 sm:shrink-0">
<PermissionGate resource="berths" action="edit">
<Button variant="outline" size="sm" onClick={() => setStatusOpen(true)}>
<RefreshCw className="mr-1.5 h-4 w-4" />

View File

@@ -48,10 +48,13 @@ type BerthData = {
function SpecRow({ label, value }: { label: string; value: React.ReactNode }) {
if (!value && value !== 0 && value !== false) return null;
// Mobile-first: stack vertically with label on top so long values
// (e.g. "206.69 ft / 62.99 m") never clip at the right edge.
// From `sm` (>=640px) up: switch to the original two-column layout.
return (
<div className="flex justify-between py-2 text-sm">
<div className="flex flex-col gap-0.5 py-2 text-sm sm:flex-row sm:items-baseline sm:justify-between sm:gap-3">
<span className="text-muted-foreground">{label}</span>
<span className="font-medium text-right max-w-[60%]">{value}</span>
<span className="font-medium sm:max-w-[60%] sm:text-right">{value}</span>
</div>
);
}