refactor(ui): mobile-first viewport fixes on ProposalPageClient
Swaps min-h-screen -> min-h-[100dvh] across all five screen states (expired, key-missing, loading, answered, reveal) so mobile browser chrome (address bar) doesn't clip full-bleed gradient screens. Bottom padding on the main content column now respects env(safe-area-inset-bottom) for iOS home-indicator devices. This page intentionally keeps its own theme.* driven styling (cardBg/cardBorder/textPrimary/buttonGradient from lib/themes.ts) rather than shadcn Card/Button — those tokens ARE the per-proposal color set this refactor was told to preserve exactly, so wrapping them in the shadcn primitives would fight the dynamic theming instead of composing with it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -171,12 +171,12 @@ export default function ProposalPageClient({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const bgClassName = bgStyle.className ? `min-h-screen ${bgStyle.className}` : 'min-h-screen';
|
const bgClassName = bgStyle.className ? `min-h-[100dvh] ${bgStyle.className}` : 'min-h-[100dvh]';
|
||||||
|
|
||||||
if (isExpired) {
|
if (isExpired) {
|
||||||
return (
|
return (
|
||||||
<div className={bgClassName} style={bgStyle.style}>
|
<div className={bgClassName} style={bgStyle.style}>
|
||||||
<div className="flex items-center justify-center min-h-screen px-4">
|
<div className="flex items-center justify-center min-h-[100dvh] px-4">
|
||||||
<div className="bg-white rounded-3xl shadow-2xl p-8 sm:p-10 text-center max-w-md w-full">
|
<div className="bg-white rounded-3xl shadow-2xl p-8 sm:p-10 text-center max-w-md w-full">
|
||||||
<div className="text-5xl mb-4">⏰</div>
|
<div className="text-5xl mb-4">⏰</div>
|
||||||
<h1 className="font-display text-2xl font-extrabold text-gray-900 mb-2">
|
<h1 className="font-display text-2xl font-extrabold text-gray-900 mb-2">
|
||||||
@@ -192,7 +192,7 @@ export default function ProposalPageClient({
|
|||||||
if (keyMissing) {
|
if (keyMissing) {
|
||||||
return (
|
return (
|
||||||
<div className={bgClassName} style={bgStyle.style}>
|
<div className={bgClassName} style={bgStyle.style}>
|
||||||
<div className="flex items-center justify-center min-h-screen px-4">
|
<div className="flex items-center justify-center min-h-[100dvh] px-4">
|
||||||
<div className="bg-white rounded-3xl shadow-2xl p-8 sm:p-10 text-center max-w-md w-full">
|
<div className="bg-white rounded-3xl shadow-2xl p-8 sm:p-10 text-center max-w-md w-full">
|
||||||
<div className="text-5xl mb-4">🔒</div>
|
<div className="text-5xl mb-4">🔒</div>
|
||||||
<h1 className="font-display text-2xl font-extrabold text-gray-900 mb-2">
|
<h1 className="font-display text-2xl font-extrabold text-gray-900 mb-2">
|
||||||
@@ -210,7 +210,7 @@ export default function ProposalPageClient({
|
|||||||
if (!decrypted) {
|
if (!decrypted) {
|
||||||
return (
|
return (
|
||||||
<div className={bgClassName} style={bgStyle.style}>
|
<div className={bgClassName} style={bgStyle.style}>
|
||||||
<div className="flex items-center justify-center min-h-screen px-4">
|
<div className="flex items-center justify-center min-h-[100dvh] px-4">
|
||||||
<motion.div
|
<motion.div
|
||||||
animate={{ opacity: [0.4, 1, 0.4] }}
|
animate={{ opacity: [0.4, 1, 0.4] }}
|
||||||
transition={{ duration: 1.4, repeat: Infinity }}
|
transition={{ duration: 1.4, repeat: Infinity }}
|
||||||
@@ -233,7 +233,7 @@ export default function ProposalPageClient({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={bgClassName} style={bgStyle.style}>
|
<div className={bgClassName} style={bgStyle.style}>
|
||||||
<div className="flex items-center justify-center min-h-screen px-4">
|
<div className="flex items-center justify-center min-h-[100dvh] px-4">
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, scale: 0.85 }}
|
initial={{ opacity: 0, scale: 0.85 }}
|
||||||
animate={{ opacity: 1, scale: 1 }}
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
@@ -288,7 +288,7 @@ export default function ProposalPageClient({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setRevealed(true)}
|
onClick={() => setRevealed(true)}
|
||||||
className="flex flex-col items-center justify-center min-h-screen w-full px-4 text-center
|
className="flex flex-col items-center justify-center min-h-[100dvh] w-full px-4 text-center
|
||||||
focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/70"
|
focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/70"
|
||||||
>
|
>
|
||||||
<motion.div
|
<motion.div
|
||||||
@@ -315,7 +315,7 @@ export default function ProposalPageClient({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={bgClassName} style={bgStyle.style}>
|
<div className={bgClassName} style={bgStyle.style}>
|
||||||
<div className="max-w-lg mx-auto px-4 py-6 sm:py-10">
|
<div className="max-w-lg mx-auto px-4 pt-6 sm:pt-10 pb-6 sm:pb-10" style={{ paddingBottom: 'max(env(safe-area-inset-bottom), 1.5rem)' }}>
|
||||||
<motion.div variants={container} initial="hidden" animate="show" className="space-y-4 sm:space-y-5">
|
<motion.div variants={container} initial="hidden" animate="show" className="space-y-4 sm:space-y-5">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<motion.div variants={item}
|
<motion.div variants={item}
|
||||||
|
|||||||
Reference in New Issue
Block a user