refactor(ui): standardize page layouts and component styling

Introduce structural CSS classes for page shells, headers, and surface cards
Update primary theme color to red and neutral to zinc across the application
This commit is contained in:
2026-05-08 16:25:42 +08:00
parent bc009cffda
commit 227c64d346
12 changed files with 454 additions and 194 deletions

View File

@@ -365,23 +365,23 @@ async function openBatchShare() {
</script>
<template>
<UContainer class="py-6 sm:py-8">
<div class="mx-auto max-w-5xl space-y-5">
<div class="space-y-1 text-center">
<UBadge :label="t('receipt.badge')" color="primary" variant="soft" class="rounded-full" />
<h1 class="text-2xl font-bold tracking-tight text-highlighted sm:text-3xl">
<UContainer class="page-shell-narrow">
<div class="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">
{{ eventDetails.title }}
</h1>
</div>
<div class="rounded-2xl border border-default bg-default p-1.5 shadow-sm">
<div class="surface-card rounded-lg p-1.5">
<div class="flex gap-1.5">
<button
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-xl px-3 py-2 text-xs font-medium transition sm:text-sm"
:class="activeTab === tab.id
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="activeTab === tab.id
? 'bg-primary text-inverted shadow-sm'
: 'bg-elevated text-default hover:bg-muted'"
@click="activeTab = tab.id"
@@ -394,17 +394,17 @@ async function openBatchShare() {
<UCard
v-if="activeTab === 'main'"
class="border border-default bg-default shadow-sm"
class="surface-card overflow-hidden rounded-lg"
:ui="{ body: 'p-5 sm:p-8' }"
>
<div class="mx-auto flex max-w-sm flex-col items-center gap-5 text-center">
<div class="rounded-[1.75rem] border border-default bg-elevated p-5 shadow-sm">
<div class="surface-panel rounded-lg p-5 shadow-sm">
<QrCodeSvg :value="receipt.receiptUrl" :size="240" />
</div>
<div class="grid w-full gap-2 sm:grid-cols-3">
<div class="rounded-2xl border border-default bg-elevated px-4 py-3 text-left">
<p class="text-[11px] font-medium uppercase tracking-wide text-muted">
<div class="surface-panel rounded-lg px-4 py-3 text-left">
<p class="text-[11px] font-medium uppercase tracking-wide text-muted">
{{ t('common.category') }}
</p>
<p class="mt-1 text-sm font-semibold text-highlighted">
@@ -412,8 +412,8 @@ async function openBatchShare() {
</p>
</div>
<div class="rounded-2xl border border-default bg-elevated px-4 py-3 text-left">
<p class="text-[11px] font-medium uppercase tracking-wide text-muted">
<div class="surface-panel rounded-lg px-4 py-3 text-left">
<p class="text-[11px] font-medium uppercase tracking-wide text-muted">
{{ t('common.seats') }}
</p>
<p class="mt-1 text-sm font-semibold text-highlighted">
@@ -421,8 +421,8 @@ async function openBatchShare() {
</p>
</div>
<div class="rounded-2xl border border-default bg-elevated px-4 py-3 text-left">
<p class="text-[11px] font-medium uppercase tracking-wide text-muted">
<div class="surface-panel rounded-lg px-4 py-3 text-left">
<p class="text-[11px] font-medium uppercase tracking-wide text-muted">
{{ t('common.totalPrice') }}
</p>
<p class="mt-1 text-sm font-semibold text-highlighted">
@@ -443,10 +443,10 @@ async function openBatchShare() {
<UCard
v-else-if="activeTab === 'status'"
class="border border-default bg-default shadow-sm"
class="surface-card overflow-hidden rounded-lg"
:ui="{ body: 'p-0' }"
>
<div class="overflow-hidden rounded-2xl">
<div class="overflow-hidden rounded-lg">
<div
v-for="row in statusRows"
:key="row.label"
@@ -467,7 +467,7 @@ async function openBatchShare() {
<UCard
v-else
class="border border-default bg-default shadow-sm"
class="surface-card overflow-hidden rounded-lg"
:ui="{ header: 'px-4 py-3', body: 'p-0' }"
>
<template #header>
@@ -494,7 +494,7 @@ async function openBatchShare() {
:data="receipt.seats"
:columns="seatColumns"
:caption="t('common.seats')"
class="min-w-[560px] sm:min-w-[720px]"
class="compact-table min-w-[560px] sm:min-w-[720px]"
>
<template #seatNumber-cell="{ row }">
<div class="min-w-0 space-y-0.5 py-0.5">
@@ -502,7 +502,7 @@ async function openBatchShare() {
<p class="text-sm font-semibold leading-tight text-highlighted sm:text-base">
{{ getSeatLabel(row.original.seatNumber, locale) }}
</p>
<UBadge
<UBadge
:label="row.original.sharedAt ? t('receipt.sharedStatus') : t('receipt.availableStatus')"
:color="row.original.sharedAt ? 'primary' : 'neutral'"
variant="soft"
@@ -586,7 +586,7 @@ async function openBatchShare() {
<template #body>
<div class="space-y-4">
<div class="grid gap-3 sm:grid-cols-2">
<div class="rounded-2xl border border-default bg-elevated p-4">
<div class="surface-panel rounded-lg p-4">
<p class="text-xs uppercase tracking-wide text-muted">
{{ t('receipt.seatsToShare') }}
</p>
@@ -600,7 +600,7 @@ async function openBatchShare() {
/>
</div>
<div class="rounded-2xl border border-default bg-elevated p-4">
<div class="surface-panel rounded-lg p-4">
<p class="text-xs uppercase tracking-wide text-muted">
{{ t('receipt.nextSeats') }}
</p>