From 1b24e3dcef7dfa468625acdad49603d5fca62ee4 Mon Sep 17 00:00:00 2001 From: Maurice Date: Fri, 6 Nov 2026 16:32:37 +0100 Subject: [PATCH] feat(mobile): collections sheets in the common sheet style The collections sheets had a header of their own with a hairline, white square fields and short buttons. Their kit now draws the icon tile header every phone sheet has (an icon per sheet), round 42 px fields on the field surface and 42 px footer buttons; the sheets sit on glass with the soft scroll edge. New list and add place lose their last own field styles: the labels are the sheets' eyebrows, the search fields, the category picker and the status choices are round fields of the same height. --- client/scripts/theme-baseline.json | 10 +++---- .../screens/collections/MCollAddSheet.tsx | 17 ++++++------ .../collections/MCollCategoryPicker.tsx | 4 +-- .../screens/collections/MCollEditSheet.tsx | 18 +++++++------ .../screens/collections/MCollLabelsSheet.tsx | 5 ++-- .../collections/MCollListPickerSheet.tsx | 7 ++--- .../screens/collections/MCollShareSheet.tsx | 7 ++--- .../screens/collections/MCollSheetKit.tsx | 27 +++++++++++++------ .../mobile/screens/collections/MCollTours.tsx | 5 ++-- .../collections/MCollTripPickerSheet.tsx | 7 ++--- 10 files changed, 63 insertions(+), 44 deletions(-) diff --git a/client/scripts/theme-baseline.json b/client/scripts/theme-baseline.json index 32181e17e..f9fd547b0 100644 --- a/client/scripts/theme-baseline.json +++ b/client/scripts/theme-baseline.json @@ -170,21 +170,21 @@ "mobile/screens/atlas/MAtlasCountryPopup.tsx": 11, "mobile/screens/atlas/MAtlasSearch.tsx": 5, "mobile/screens/atlas/MAtlasStatsCard.tsx": 3, - "mobile/screens/collections/MCollAddSheet.tsx": 7, + "mobile/screens/collections/MCollAddSheet.tsx": 6, "mobile/screens/collections/MCollCategoryPicker.tsx": 2, - "mobile/screens/collections/MCollEditSheet.tsx": 5, + "mobile/screens/collections/MCollEditSheet.tsx": 2, "mobile/screens/collections/MCollLabelsSheet.tsx": 6, "mobile/screens/collections/MCollLinksEditor.tsx": 2, "mobile/screens/collections/MCollListPickerSheet.tsx": 3, "mobile/screens/collections/MCollPlaceRow.tsx": 3, "mobile/screens/collections/MCollPlaceSheet.tsx": 11, "mobile/screens/collections/MCollShareSheet.tsx": 14, - "mobile/screens/collections/MCollSheetKit.tsx": 6, + "mobile/screens/collections/MCollSheetKit.tsx": 5, "mobile/screens/collections/MCollTripPickerSheet.tsx": 4, "mobile/screens/collections/MCollections.tsx": 21, "mobile/screens/dashboard/MDashWidgets.tsx": 22, "mobile/screens/dashboard/MDashboard.tsx": 36, - "mobile/screens/dashboard/MNewTripSheet.tsx": 20, + "mobile/screens/dashboard/MNewTripSheet.tsx": 12, "mobile/screens/dashboard/MUserMenu.tsx": 7, "mobile/screens/journey/MJourney.tsx": 10, "mobile/screens/journey/MJourneyCreateSheet.tsx": 10, @@ -235,7 +235,7 @@ "mobile/screens/trip/sheets/ImpFileStep.tsx": 12, "mobile/screens/trip/sheets/ImpListStep.tsx": 3, "mobile/screens/trip/sheets/MAccommodationSheet.tsx": 10, - "mobile/screens/trip/sheets/MBookingFields.tsx": 6, + "mobile/screens/trip/sheets/MBookingFields.tsx": 5, "mobile/screens/trip/sheets/MBrowseActionsSheet.tsx": 5, "mobile/screens/trip/sheets/MCostSheet.tsx": 33, "mobile/screens/trip/sheets/MDaySheet.tsx": 22, diff --git a/client/src/mobile/screens/collections/MCollAddSheet.tsx b/client/src/mobile/screens/collections/MCollAddSheet.tsx index 20b80f332..bae23e7b7 100644 --- a/client/src/mobile/screens/collections/MCollAddSheet.tsx +++ b/client/src/mobile/screens/collections/MCollAddSheet.tsx @@ -1,4 +1,4 @@ -import { Check, Loader2, MapPin, Search, X } from 'lucide-react' +import { Check, Loader2, MapPin, Search, X, MapPinPlus } from 'lucide-react' import type { Category, TranslationFn } from '../../../types' import { STATUS_ORDER } from '../../../pages/collections/collectionsModel' import MSheet from '../../components/MSheet' @@ -32,9 +32,10 @@ export default function MCollAddSheet({ open, collectionId, collectionName, list } = useAddPlaceToCollection({ variant: 'sheet', open, collectionId, collectionName, lists, t, onClose, onAdded }) return ( - - -
+ + } title={t('collections.addPlace')} onClose={onClose} closeLabel={t('common.close')} /> +
{/* List picker — only when opened without a fixed target list */} {collectionId == null && (
@@ -65,20 +66,20 @@ export default function MCollAddSheet({ open, collectionId, collectionName, list
)} {/* Search — picking a result fills the location */} -
+
setQuery(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); void search() } }} placeholder={t('collections.addPlaceSearch')} - className="min-w-0 flex-1 bg-transparent py-2 font-[inherit] text-[0.8125rem] text-m-ink outline-none placeholder:text-m-faint" + className="min-w-0 flex-1 bg-transparent font-[inherit] text-[0.8125rem] text-m-ink outline-none placeholder:text-m-faint" /> @@ -113,7 +115,7 @@ export default function MCollEditSheet({ target, onClose, onCreated, onRequestDe value={name} onChange={e => setName(e.target.value)} placeholder={t('collections.listNamePlaceholder')} - className="w-full box-border rounded-[12px] border-[1.5px] border-[color:var(--m-rowbr)] bg-[color:var(--m-sheet)] px-[13px] py-[11px] font-[inherit] text-[0.84375rem] font-semibold text-m-ink outline-none placeholder:text-m-faint" + className={`${INPUT_CLS} font-semibold`} />
{t('collections.listColor')}
diff --git a/client/src/mobile/screens/collections/MCollLabelsSheet.tsx b/client/src/mobile/screens/collections/MCollLabelsSheet.tsx index 809425420..3813261b5 100644 --- a/client/src/mobile/screens/collections/MCollLabelsSheet.tsx +++ b/client/src/mobile/screens/collections/MCollLabelsSheet.tsx @@ -92,8 +92,9 @@ export default function MCollLabelsSheet({ const title = mode === 'assign' ? t('collections.labels.assignN', { count: selectedCount }) : t('collections.labels.manage') return ( - - + + } title={title} onClose={onClose} closeLabel={t('common.close')} />
{mode === 'manage' && ( <> diff --git a/client/src/mobile/screens/collections/MCollListPickerSheet.tsx b/client/src/mobile/screens/collections/MCollListPickerSheet.tsx index 3a866ef05..3ef0f75ce 100644 --- a/client/src/mobile/screens/collections/MCollListPickerSheet.tsx +++ b/client/src/mobile/screens/collections/MCollListPickerSheet.tsx @@ -1,5 +1,5 @@ import { useState } from 'react' -import { Loader2 } from 'lucide-react' +import { Loader2, ListPlus } from 'lucide-react' import type { Collection } from '@trek/shared' import type { TranslationFn } from '../../../types' import MSheet from '../../components/MSheet' @@ -40,8 +40,9 @@ export default function MCollListPickerSheet({ mode, lists, count, onPick, onClo } return ( - - + + } title={title} onClose={onClose} closeLabel={t('common.close')} />
{lists.length === 0 ? (
{t('collections.noOtherLists')}
diff --git a/client/src/mobile/screens/collections/MCollShareSheet.tsx b/client/src/mobile/screens/collections/MCollShareSheet.tsx index 054f8e555..ed526112d 100644 --- a/client/src/mobile/screens/collections/MCollShareSheet.tsx +++ b/client/src/mobile/screens/collections/MCollShareSheet.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react' -import { Check, ChevronDown, Clock, Crown, Loader2, LogOut, UserPlus, X } from 'lucide-react' +import { Check, ChevronDown, Clock, Crown, Loader2, LogOut, UserPlus, X, Share2 } from 'lucide-react' import type { CollectionMember } from '@trek/shared' import { COLLECTION_ROLES } from '@trek/shared' import type { TranslationFn } from '../../../types' @@ -54,8 +54,9 @@ export default function MCollShareSheet({ const badge = 'inline-flex flex-none items-center gap-[3px] font-geist text-[0.625rem] font-extrabold' return ( - - + + } title={t('collections.share.titleNamed', { name: collectionName })} onClose={onClose} closeLabel={t('common.close')} />
{t('collections.share.members').toUpperCase()} diff --git a/client/src/mobile/screens/collections/MCollSheetKit.tsx b/client/src/mobile/screens/collections/MCollSheetKit.tsx index 272f0c09b..f2ac68abf 100644 --- a/client/src/mobile/screens/collections/MCollSheetKit.tsx +++ b/client/src/mobile/screens/collections/MCollSheetKit.tsx @@ -4,22 +4,33 @@ import { X } from 'lucide-react' /** Shared sheet scaffolding of the collections sheets (opaque floating cards). */ export const INPUT_CLS = - 'w-full box-border rounded-[12px] border border-[color:var(--m-rowbr)] bg-[color:var(--m-sheet)] px-[13px] py-[11px] font-[inherit] text-[0.8125rem] text-m-ink outline-none placeholder:text-m-faint' + 'w-full box-border rounded-full border border-[color:var(--m-rowbr)] bg-[color:var(--m-ic)] px-[14px] py-[10px] font-[inherit] text-[0.8125rem] text-m-ink outline-none placeholder:text-m-faint' export const TEXTAREA_CLS = - 'w-full box-border resize-none rounded-[12px] border border-[color:var(--m-rowbr)] bg-[color:var(--m-sheet)] px-[13px] py-[11px] font-geist text-[0.78125rem] leading-[1.5] text-m-ink outline-none placeholder:text-m-faint' + 'w-full box-border resize-none rounded-[18px] border border-[color:var(--m-rowbr)] bg-[color:var(--m-ic)] px-[14px] py-[10px] font-geist text-[0.78125rem] leading-[1.5] text-m-ink outline-none placeholder:text-m-faint' interface SheetHeaderProps { title: ReactNode + /** The icon tile in front of the title, as every phone sheet has. */ + icon?: ReactNode + sub?: ReactNode onClose: () => void closeLabel: string } -/** Sheet header: 17px/700 title + 34px round close, hairline below. */ -export function SheetHeader({ title, onClose, closeLabel }: SheetHeaderProps) { +/** Sheet header: the icon tile, the 17px/700 title (with an optional line under it) and the 34px round close, as TileHeader. */ +export function SheetHeader({ title, icon, sub, onClose, closeLabel }: SheetHeaderProps) { return ( -
-
{title}
+
+ {icon && ( +
+ {icon} +
+ )} +
+
{title}
+ {sub &&
{sub}
} +
@@ -69,7 +80,7 @@ export function PrimaryPill({ onClick, disabled, className = '', children }: Pil type="button" onClick={onClick} disabled={disabled} - className={`flex items-center gap-[6px] rounded-full bg-m-act px-[18px] py-[9px] text-[0.78125rem] font-bold text-m-actfg disabled:opacity-40 ${className}`} + className={`flex h-[42px] items-center justify-center gap-[6px] rounded-full bg-m-act px-4 text-[length:calc(13px*var(--fs-scale-body,1))] font-semibold text-m-actfg disabled:opacity-40 ${className}`} > {children} diff --git a/client/src/mobile/screens/collections/MCollTours.tsx b/client/src/mobile/screens/collections/MCollTours.tsx index 899bb41a8..8a1514370 100644 --- a/client/src/mobile/screens/collections/MCollTours.tsx +++ b/client/src/mobile/screens/collections/MCollTours.tsx @@ -211,8 +211,9 @@ function MCollTourSheet({ const tour = takeOver.tour; const title = tour?.name ?? t('tours.collection.add'); return ( - - + + } title={title} onClose={takeOver.close} closeLabel={t('common.close')} />
{tour && (

diff --git a/client/src/mobile/screens/collections/MCollTripPickerSheet.tsx b/client/src/mobile/screens/collections/MCollTripPickerSheet.tsx index 1459f438a..698cf81c7 100644 --- a/client/src/mobile/screens/collections/MCollTripPickerSheet.tsx +++ b/client/src/mobile/screens/collections/MCollTripPickerSheet.tsx @@ -1,4 +1,4 @@ -import { CalendarDays, Copy, Loader2, MapPin, Search } from 'lucide-react' +import { CalendarDays, Copy, Loader2, MapPin, Search, Luggage } from 'lucide-react' import type { TranslationFn } from '../../../types' import { useTripCopyPicker } from '../../../components/Collections/useTripCopyPicker' import MSheet from '../../components/MSheet' @@ -23,8 +23,9 @@ export default function MCollTripPickerSheet({ open, count, onCopy, onClose, t } const title = t('collections.copyN', { count }) return ( - - + + } title={title} onClose={onClose} closeLabel={t('common.close')} />