fix: mobile UI — touch targets, safe areas, text sizes

- Button: add min-h-11 (44px) for mobile touch targets
- NavBar: add safe-area-inset-top for notched phones
- NavBar mobile menu: increase link padding from py-2 to py-3
- Footer: increase text size from text-xs to text-sm (16px minimum)
- Footer: add px-4 for better mobile spacing
- DatePicker: increase calendar cell size on mobile to 44px
- Checkbox: add p-3 -m-3 on mobile for 44px touch target (desktop unchanged)
This commit is contained in:
2026-08-22 00:34:51 +01:00
parent 4146f8e09a
commit 73f0258b97
5 changed files with 15 additions and 14 deletions
@@ -34,7 +34,7 @@
// Without this the stable isDateUnavailable reference may cause stale availability
// after workingHours/availableHours are updated (e.g. after month data loading).
isDateUnavailable={(d) => isDateUnavailable(d)}
class="bg-transparent p-0 [--cell-size:--spacing(11)] data-unavailable:line-through data-unavailable:opacity-100 max-sm:[--cell-size:--spacing(10)] md:[--cell-size:--spacing(12)] [&_[data-outside-month]]:pointer-events-none [&_[data-outside-month]]:opacity-0"
class="bg-transparent p-0 [--cell-size:--spacing(11)] data-unavailable:line-through data-unavailable:opacity-100 max-sm:[--cell-size:--spacing(11)] md:[--cell-size:--spacing(12)] [&_[data-outside-month]]:pointer-events-none [&_[data-outside-month]]:opacity-0"
weekdayFormat="short"
{minValue}
{maxValue}
@@ -91,6 +91,7 @@
<nav
class="fixed top-0 left-0 z-50 w-full border-b border-gray-200"
style="padding-top: env(safe-area-inset-top, 0px)"
class:frosty-nav={!mobileMenuOpen}
class:bg-background={mobileMenuOpen}
>
@@ -231,14 +232,14 @@
<!-- eslint-disable svelte/no-navigation-without-resolve -->
<Skeleton class="h-4 w-full rounded" />
{:else}
<!-- eslint-disable-next-line svelte/no-navigation-without-resolve -->
<a
href={link.href}
class="block rounded px-3 py-2 text-center text-primary hover:text-gray-800"
>
{link.label}
</a>
<!-- eslint-enable svelte/no-navigation-without-resolve -->
<!-- eslint-disable-next-line svelte/no-navigation-without-resolve -->
<a
href={link.href}
class="block rounded px-3 py-3 text-center text-primary hover:text-gray-800"
>
{link.label}
</a>
<!-- eslint-enable svelte/no-navigation-without-resolve -->
{/if}
{/if}
{/each}
@@ -4,7 +4,7 @@
import { type VariantProps, tv } from 'tailwind-variants';
export const buttonVariants = tv({
base: "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive focus-visible:border-ring focus-visible:ring-ring/50 relative inline-flex shrink-0 items-center justify-center gap-2 overflow-hidden rounded-md text-sm font-medium whitespace-nowrap outline-hidden transition-all select-none focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 active:opacity-80 active:scale-[0.99] [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
base: "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive focus-visible:border-ring focus-visible:ring-ring/50 relative inline-flex shrink-0 items-center justify-center gap-2 overflow-hidden rounded-md text-sm font-medium whitespace-nowrap outline-hidden transition-all select-none focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 active:opacity-80 active:scale-[0.99] min-h-11 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
variants: {
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90 shadow-2xs',
@@ -17,7 +17,7 @@
bind:ref
data-slot="checkbox"
class={cn(
'peer flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input bg-white shadow-xs transition-shadow outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:bg-input/30 dark:aria-invalid:ring-destructive/40 dark:data-[state=checked]:bg-primary',
'peer flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input bg-white shadow-xs transition-shadow outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground p-3 -m-3 md:p-0 md:m-0 dark:bg-input/30 dark:aria-invalid:ring-destructive/40 dark:data-[state=checked]:bg-primary',
className
)}
bind:checked
+3 -3
View File
@@ -167,8 +167,8 @@
</main>
{#if !hideFooter}
<footer class="border-t py-3 text-center text-xs text-gray-500 md:py-4 md:text-sm">
<div class="mx-auto flex max-w-3xl flex-wrap items-center justify-center gap-x-4 gap-y-1">
<footer class="border-t py-4 text-center text-sm text-gray-500 md:py-6">
<div class="mx-auto flex max-w-3xl flex-wrap items-center justify-center gap-x-4 gap-y-2 px-4">
<a href={resolve('/privacy-policy')} class="hover:text-gray-700 hover:underline"
>Privacy Policy</a
>
@@ -183,7 +183,7 @@
>
<a href={resolve('/gdpr')} class="hover:text-gray-700 hover:underline">Your Data</a>
</div>
<div class="mt-1">&copy; {new Date().getFullYear()} Crussell Nails. All rights reserved.</div>
<div class="mt-2">&copy; {new Date().getFullYear()} Crussell Nails. All rights reserved.</div>
</footer>
{/if}
</div>