estimate wizard now fully responsive-mobile first
This commit is contained in:
@@ -12,7 +12,7 @@ import WizardShell from './components/WizardShell';
|
||||
const CompletionScreen = () => {
|
||||
const { inputs, reset } = useEstimateWizard();
|
||||
return (
|
||||
<div className="min-h-screen w-full bg-zinc-50 dark:bg-[#09090b] flex items-center justify-center px-4">
|
||||
<div className="min-h-[100dvh] w-full bg-zinc-50 dark:bg-[#09090b] flex items-center justify-center px-4 py-10">
|
||||
<div className="max-w-md text-center">
|
||||
<CheckCircle2 size={56} className="text-green-500 mx-auto mb-4" />
|
||||
<h1 className="text-2xl font-bold text-zinc-900 dark:text-white">
|
||||
@@ -34,7 +34,7 @@ const CompletionScreen = () => {
|
||||
};
|
||||
|
||||
const FeatureDisabledScreen = () => (
|
||||
<div className="min-h-screen w-full bg-zinc-50 dark:bg-[#09090b] flex items-center justify-center px-4">
|
||||
<div className="min-h-[100dvh] w-full bg-zinc-50 dark:bg-[#09090b] flex items-center justify-center px-4 py-10">
|
||||
<div className="max-w-md text-center">
|
||||
<h1 className="text-xl font-bold text-zinc-900 dark:text-white">Estimate wizard unavailable</h1>
|
||||
<p className="text-zinc-500 dark:text-zinc-400 mt-2">
|
||||
|
||||
@@ -102,14 +102,14 @@ const WizardShell = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen w-full bg-zinc-50 dark:bg-[#09090b] flex flex-col">
|
||||
<div className="min-h-[100dvh] w-full bg-zinc-50 dark:bg-[#09090b] flex flex-col">
|
||||
{/* Top bar */}
|
||||
<header className="w-full border-b border-zinc-200 dark:border-white/5 bg-white/70 dark:bg-zinc-900/60 backdrop-blur-md">
|
||||
<div className="max-w-2xl mx-auto px-4 py-4">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<span className="font-bold tracking-tight text-zinc-900 dark:text-white">
|
||||
<div className="max-w-2xl mx-auto px-4 py-3 sm:py-4">
|
||||
<div className="flex items-center justify-between gap-3 mb-3">
|
||||
<span className="font-bold tracking-tight text-zinc-900 dark:text-white truncate">
|
||||
LynkedUp<span className="text-amber-500">Pro</span>
|
||||
<span className="ml-2 text-xs font-medium text-zinc-400">Roof Options</span>
|
||||
<span className="ml-2 text-xs font-medium text-zinc-400 hidden xs:inline">Roof Options</span>
|
||||
</span>
|
||||
<button
|
||||
onClick={reset}
|
||||
@@ -134,7 +134,7 @@ const WizardShell = () => {
|
||||
|
||||
{/* Body */}
|
||||
<main className="flex-1 w-full">
|
||||
<div className="max-w-2xl mx-auto px-4 py-8">
|
||||
<div className="max-w-2xl mx-auto px-4 py-6 sm:py-8">
|
||||
{/* key forces remount per step → re-triggers the enter animation */}
|
||||
<div key={step.id} className="animate-in fade-in slide-in-from-right-4 duration-300">
|
||||
<h1 className="text-2xl md:text-3xl font-bold text-zinc-900 dark:text-white tracking-tight">
|
||||
@@ -148,22 +148,26 @@ const WizardShell = () => {
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{/* Footer nav — one primary CTA */}
|
||||
<footer className="sticky bottom-0 w-full border-t border-zinc-200 dark:border-white/5 bg-white/80 dark:bg-zinc-900/70 backdrop-blur-md">
|
||||
<div className="max-w-2xl mx-auto px-4 py-3 flex items-center gap-3">
|
||||
{/* Footer nav — one primary CTA. Respects the mobile safe-area inset so the
|
||||
CTA clears the iPhone home indicator. */}
|
||||
<footer
|
||||
className="sticky bottom-0 w-full border-t border-zinc-200 dark:border-white/5 bg-white/80 dark:bg-zinc-900/70 backdrop-blur-md"
|
||||
style={{ paddingBottom: 'env(safe-area-inset-bottom)' }}
|
||||
>
|
||||
<div className="max-w-2xl mx-auto px-4 py-3 flex items-center gap-2 sm:gap-3">
|
||||
{stepIndex > 0 && (
|
||||
<button
|
||||
onClick={back}
|
||||
className="rounded-xl border border-zinc-200 dark:border-white/10 px-4 py-2.5 text-sm font-medium text-zinc-600 dark:text-zinc-300 hover:border-amber-400 flex items-center gap-1.5"
|
||||
className="shrink-0 rounded-xl border border-zinc-200 dark:border-white/10 px-3 sm:px-4 py-2.5 text-sm font-medium text-zinc-600 dark:text-zinc-300 hover:border-amber-400 flex items-center gap-1.5"
|
||||
>
|
||||
<ArrowLeft size={16} /> Back
|
||||
<ArrowLeft size={16} /> <span className="hidden xs:inline">Back</span>
|
||||
</button>
|
||||
)}
|
||||
|
||||
{step.skippable && !isLast && (
|
||||
<button
|
||||
onClick={next}
|
||||
className="text-sm font-medium text-zinc-400 hover:text-amber-500 px-2"
|
||||
className="shrink-0 text-sm font-medium text-zinc-400 hover:text-amber-500 px-1.5 sm:px-2 py-2.5"
|
||||
>
|
||||
Skip
|
||||
</button>
|
||||
@@ -172,13 +176,13 @@ const WizardShell = () => {
|
||||
<button
|
||||
onClick={handleContinue}
|
||||
disabled={!advance}
|
||||
className={`ml-auto rounded-xl px-6 py-2.5 text-sm font-semibold flex items-center gap-1.5 transition-all
|
||||
className={`ml-auto min-w-0 rounded-xl px-5 sm:px-6 py-2.5 text-sm font-semibold flex items-center justify-center gap-1.5 whitespace-nowrap transition-all
|
||||
${advance
|
||||
? 'bg-gradient-to-r from-amber-400 to-orange-500 text-white shadow-lg shadow-amber-500/25 hover:shadow-amber-500/40'
|
||||
: 'bg-zinc-200 dark:bg-zinc-800 text-zinc-400 cursor-not-allowed'}`}
|
||||
>
|
||||
{isLast ? 'Finish' : stepIndex === 0 ? 'Start estimate' : 'Continue'}
|
||||
{!isLast && <ArrowRight size={16} />}
|
||||
{!isLast && <ArrowRight size={16} className="shrink-0" />}
|
||||
</button>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -52,8 +52,10 @@ const AddonsStep = () => {
|
||||
triggers={triggers}
|
||||
/>
|
||||
|
||||
{/* Running total for the selected package */}
|
||||
<div className="sticky bottom-0 rounded-2xl border border-zinc-200 dark:border-white/10 bg-white dark:bg-zinc-900 p-4 shadow-sm">
|
||||
{/* Running total for the selected package. Not sticky — the wizard's
|
||||
footer CTA is already pinned, and two stacked sticky bars overlap on
|
||||
mobile. */}
|
||||
<div className="rounded-2xl border border-zinc-200 dark:border-white/10 bg-white dark:bg-zinc-900 p-4 shadow-sm">
|
||||
<div className="flex items-center justify-between text-sm text-zinc-500 dark:text-zinc-400">
|
||||
<span>{pkg?.name} (base estimate)</span>
|
||||
<span>{formatUSD(base)}</span>
|
||||
|
||||
Reference in New Issue
Block a user