feat(ui): improve mobile responsiveness and touch targets

Add mobile-optimized card view for seat lists on smaller screens
Increase minimum height for buttons and form items for better touch interaction
Adjust grid layouts, padding, and spacing across pages for mobile devices
This commit is contained in:
2026-05-08 16:28:47 +08:00
parent 227c64d346
commit b6749bc5e7
4 changed files with 89 additions and 32 deletions

View File

@@ -366,7 +366,7 @@ async function openBatchShare() {
<template>
<UContainer class="page-shell-narrow">
<div class="space-y-6">
<div class="space-y-5 sm:space-y-6">
<div class="page-header text-center sm:items-center">
<UBadge :label="t('receipt.badge')" color="primary" variant="soft" class="page-eyebrow" />
<h1 class="page-title">
@@ -380,7 +380,7 @@ async function openBatchShare() {
v-for="tab in tabs"
:key="tab.id"
type="button"
class="flex min-h-10 flex-1 items-center justify-center gap-1.5 rounded-lg px-3 py-2 text-xs font-medium transition sm:text-sm"
class="flex min-h-12 flex-1 items-center justify-center gap-1.5 rounded-lg px-2 py-2 text-xs font-medium transition sm:px-3 sm:text-sm"
:class="activeTab === tab.id
? 'bg-primary text-inverted shadow-sm'
: 'bg-elevated text-default hover:bg-muted'"
@@ -395,11 +395,11 @@ async function openBatchShare() {
<UCard
v-if="activeTab === 'main'"
class="surface-card overflow-hidden rounded-lg"
:ui="{ body: 'p-5 sm:p-8' }"
:ui="{ body: 'p-4 sm:p-8' }"
>
<div class="mx-auto flex max-w-sm flex-col items-center gap-5 text-center">
<div class="surface-panel rounded-lg p-5 shadow-sm">
<QrCodeSvg :value="receipt.receiptUrl" :size="240" />
<div class="surface-panel w-full rounded-lg p-3 shadow-sm sm:p-5">
<QrCodeSvg :value="receipt.receiptUrl" :size="220" />
</div>
<div class="grid w-full gap-2 sm:grid-cols-3">
@@ -434,7 +434,7 @@ async function openBatchShare() {
<UButton
:label="t('receipt.shareSeats')"
icon="i-lucide-share-2"
class="w-full justify-center sm:w-auto"
class="min-h-12 w-full justify-center sm:w-auto"
:disabled="!availableSeats.length || shareSeatsLoading || Boolean(seatActionId)"
@click="batchShareModalOpen = true"
/>
@@ -489,7 +489,64 @@ async function openBatchShare() {
</div>
</template>
<div class="overflow-x-auto">
<div class="grid gap-3 p-3 sm:hidden">
<div
v-for="seat in receipt.seats"
:key="seat.id"
class="surface-panel rounded-lg p-3"
>
<div class="flex items-start justify-between gap-3">
<div class="min-w-0">
<div class="flex flex-wrap items-center gap-2">
<p class="font-semibold leading-tight text-highlighted">
{{ getSeatLabel(seat.seatNumber, locale) }}
</p>
<UBadge
:label="seat.sharedAt ? t('receipt.sharedStatus') : t('receipt.availableStatus')"
:color="seat.sharedAt ? 'primary' : 'neutral'"
variant="soft"
size="sm"
/>
</div>
<p class="mt-1 text-xs text-muted">
{{ seat.recipientName || t('receipt.unassigned') }}
<span v-if="seat.recipientPhone"> · {{ seat.recipientPhone }}</span>
</p>
<p class="mt-1 text-xs text-muted">
{{ seat.sharedAt
? t('receipt.sharedAt', { date: formatDateTime(seat.sharedAt, t('date.notAvailable'), locale) })
: t('receipt.readyToShare') }}
</p>
</div>
</div>
<div class="mt-3 grid grid-cols-2 gap-2">
<UButton
:to="seat.seatUrl"
target="_blank"
:label="t('common.open')"
color="neutral"
variant="outline"
icon="i-lucide-external-link"
size="sm"
class="min-h-11 justify-center"
/>
<UButton
:label="seat.sharedAt ? t('receipt.unshare') : t('receipt.share')"
:icon="seat.sharedAt ? 'i-lucide-user-minus' : 'i-lucide-share-2'"
color="neutral"
:variant="seat.sharedAt ? 'outline' : 'solid'"
size="sm"
class="min-h-11 justify-center"
:loading="seatActionId === seat.id"
:disabled="shareSeatsLoading"
@click="seat.sharedAt ? unshareSeat(seat) : shareSeat(seat)"
/>
</div>
</div>
</div>
<div class="hidden overflow-x-auto sm:block">
<UTable
:data="receipt.seats"
:columns="seatColumns"
@@ -632,7 +689,7 @@ async function openBatchShare() {
:label="t('common.cancel')"
color="neutral"
variant="ghost"
class="justify-center"
class="min-h-11 justify-center"
:disabled="shareSeatsLoading"
@click="batchShareModalOpen = false"
/>
@@ -640,7 +697,7 @@ async function openBatchShare() {
<UButton
:label="t('receipt.shareSeats')"
icon="i-lucide-share-2"
class="justify-center"
class="min-h-11 justify-center"
:disabled="!availableSeats.length || Boolean(seatActionId)"
:loading="shareSeatsLoading"
@click="openBatchShare"