Add mobile foundation: iOS zoom fix, safe area insets, row padding

- Input base font 16px on mobile to prevent iOS Safari auto-zoom
- Safe area insets for notched phones (top/bottom bars)
- viewport-fit=cover to enable safe area env() values
- Action bar flex-wrap for custom stat field overflow
- Slightly increased row padding on mobile (py-3 sm:py-2)
- Removed redundant font-size classes from Input usages

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Lukas
2026-03-24 23:19:10 +01:00
parent 5e5812bcaa
commit 64a1f0b8db
6 changed files with 16 additions and 10 deletions

View File

@@ -2,7 +2,7 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<meta name="theme-color" content="#0e1a2e" /> <meta name="theme-color" content="#0e1a2e" />
<link rel="manifest" href="/manifest.json" /> <link rel="manifest" href="/manifest.json" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" />

View File

@@ -46,7 +46,10 @@ export function App() {
<div className="relative mx-auto flex min-h-0 w-full flex-1 flex-col gap-3 sm:max-w-2xl sm:px-4"> <div className="relative mx-auto flex min-h-0 w-full flex-1 flex-col gap-3 sm:max-w-2xl sm:px-4">
{!!actionBarAnim.showTopBar && ( {!!actionBarAnim.showTopBar && (
<div <div
className={cn("shrink-0 sm:pt-8", actionBarAnim.topBarClass)} className={cn(
"shrink-0 pt-[env(safe-area-inset-top)] sm:pt-[max(env(safe-area-inset-top),2rem)]",
actionBarAnim.topBarClass,
)}
onAnimationEnd={actionBarAnim.onTopBarExitEnd} onAnimationEnd={actionBarAnim.onTopBarExitEnd}
> >
<TurnNavigation /> <TurnNavigation />
@@ -85,7 +88,10 @@ export function App() {
</div> </div>
<div <div
className={cn("shrink-0 sm:pb-8", actionBarAnim.settlingClass)} className={cn(
"shrink-0 pb-[env(safe-area-inset-bottom)] sm:pb-[max(env(safe-area-inset-bottom),2rem)]",
actionBarAnim.settlingClass,
)}
onAnimationEnd={actionBarAnim.onSettleEnd} onAnimationEnd={actionBarAnim.onSettleEnd}
> >
<ActionBar <ActionBar

View File

@@ -521,7 +521,7 @@ export function ActionBar({
<div className="card-glow flex items-center gap-3 border-border border-t bg-card px-4 py-3 sm:rounded-lg sm:border"> <div className="card-glow flex items-center gap-3 border-border border-t bg-card px-4 py-3 sm:rounded-lg sm:border">
<form <form
onSubmit={handleAdd} onSubmit={handleAdd}
className="relative flex flex-1 items-center gap-2" className="relative flex flex-1 flex-wrap items-center gap-2 sm:flex-nowrap"
> >
<div className="flex-1"> <div className="flex-1">
<div className="relative max-w-xs"> <div className="relative max-w-xs">

View File

@@ -157,7 +157,7 @@ function MaxHpDisplay({
inputMode="numeric" inputMode="numeric"
value={draft} value={draft}
placeholder="Max" placeholder="Max"
className="h-7 w-[7ch] text-center text-sm tabular-nums" className="h-7 w-[7ch] text-center tabular-nums"
onChange={(e) => setDraft(e.target.value)} onChange={(e) => setDraft(e.target.value)}
onBlur={commit} onBlur={commit}
onKeyDown={(e) => { onKeyDown={(e) => {
@@ -272,7 +272,7 @@ function AcDisplay({
inputMode="numeric" inputMode="numeric"
value={draft} value={draft}
placeholder="AC" placeholder="AC"
className="h-7 w-[6ch] text-center text-sm tabular-nums" className="h-7 w-[6ch] text-center tabular-nums"
onChange={(e) => setDraft(e.target.value)} onChange={(e) => setDraft(e.target.value)}
onBlur={commit} onBlur={commit}
onKeyDown={(e) => { onKeyDown={(e) => {
@@ -348,7 +348,7 @@ function InitiativeDisplay({
value={draft} value={draft}
placeholder="--" placeholder="--"
className={cn( className={cn(
"h-7 w-full text-center text-sm tabular-nums", "h-7 w-full text-center tabular-nums",
dimmed && "opacity-50", dimmed && "opacity-50",
)} )}
onChange={(e) => setDraft(e.target.value)} onChange={(e) => setDraft(e.target.value)}
@@ -520,7 +520,7 @@ export function CombatantRow({
isPulsing && "animate-concentration-pulse", isPulsing && "animate-concentration-pulse",
)} )}
> >
<div className="grid grid-cols-[2rem_3rem_auto_1fr_auto_2rem] items-center gap-1.5 py-2 sm:grid-cols-[2rem_3.5rem_auto_1fr_auto_2rem] sm:gap-3"> <div className="grid grid-cols-[2rem_3rem_auto_1fr_auto_2rem] items-center gap-1.5 py-3 sm:grid-cols-[2rem_3.5rem_auto_1fr_auto_2rem] sm:gap-3 sm:py-2">
{/* Concentration */} {/* Concentration */}
<button <button
type="button" type="button"

View File

@@ -106,7 +106,7 @@ export function HpAdjustPopover({
inputMode="numeric" inputMode="numeric"
value={inputValue} value={inputValue}
placeholder="HP" placeholder="HP"
className="h-7 w-[7ch] text-center text-sm tabular-nums" className="h-7 w-[7ch] text-center tabular-nums"
onChange={(e) => { onChange={(e) => {
const v = e.target.value; const v = e.target.value;
if (v === "" || DIGITS_ONLY_REGEX.test(v)) { if (v === "" || DIGITS_ONLY_REGEX.test(v)) {

View File

@@ -12,7 +12,7 @@ export const Input = ({
<input <input
ref={ref} ref={ref}
className={cn( className={cn(
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-foreground text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:cursor-not-allowed disabled:opacity-50", "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base text-foreground shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:cursor-not-allowed disabled:opacity-50 sm:text-sm",
className, className,
)} )}
{...props} {...props}