fix: mobile-responsive SurveyPage with touch-friendly targets
15+ responsive adjustments using sm: breakpoints for proper mobile display: compact padding, flex-wrap metadata, stacked email input, larger touch targets for drag-rank/range inputs, hidden brand text on small screens, and tighter line heights. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -260,8 +260,8 @@ export default function SurveyPage() {
|
|||||||
<div className="absolute -top-32 right-0 h-[500px] w-[500px] rounded-full opacity-[0.03]" style={{ background: 'radial-gradient(circle, #06b6d4, transparent 70%)' }} />
|
<div className="absolute -top-32 right-0 h-[500px] w-[500px] rounded-full opacity-[0.03]" style={{ background: 'radial-gradient(circle, #06b6d4, transparent 70%)' }} />
|
||||||
<div className="absolute -bottom-32 left-0 h-[400px] w-[400px] rounded-full opacity-[0.02]" style={{ background: 'radial-gradient(circle, #a855f7, transparent 70%)' }} />
|
<div className="absolute -bottom-32 left-0 h-[400px] w-[400px] rounded-full opacity-[0.02]" style={{ background: 'radial-gradient(circle, #a855f7, transparent 70%)' }} />
|
||||||
</div>
|
</div>
|
||||||
<div className="relative z-10 mx-auto max-w-[680px] px-5">
|
<div className="relative z-10 mx-auto max-w-[680px] px-4 sm:px-5">
|
||||||
<div className="text-center pt-32 animate-fade-in-up">
|
<div className="text-center pt-20 sm:pt-32 animate-fade-in-up">
|
||||||
<div className="w-16 h-16 mx-auto mb-5 rounded-full flex items-center justify-center" style={{ background: 'rgba(6, 182, 212, 0.1)' }}>
|
<div className="w-16 h-16 mx-auto mb-5 rounded-full flex items-center justify-center" style={{ background: 'rgba(6, 182, 212, 0.1)' }}>
|
||||||
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#06b6d4" strokeWidth="2.5"><path d="M20 6L9 17l-5-5"/></svg>
|
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#06b6d4" strokeWidth="2.5"><path d="M20 6L9 17l-5-5"/></svg>
|
||||||
</div>
|
</div>
|
||||||
@@ -272,7 +272,7 @@ export default function SurveyPage() {
|
|||||||
<p className="text-sm text-muted-foreground/70 max-w-[400px] mx-auto leading-relaxed mb-8">
|
<p className="text-sm text-muted-foreground/70 max-w-[400px] mx-auto leading-relaxed mb-8">
|
||||||
You can safely close this browser window now.
|
You can safely close this browser window now.
|
||||||
</p>
|
</p>
|
||||||
<div className="glass-card-static p-5 max-w-[400px] mx-auto text-center">
|
<div className="glass-card-static p-4 sm:p-5 max-w-[400px] mx-auto text-center">
|
||||||
<p className="text-xs text-muted-foreground leading-relaxed">
|
<p className="text-xs text-muted-foreground leading-relaxed">
|
||||||
Have feedback unrelated to the survey?{' '}
|
Have feedback unrelated to the survey?{' '}
|
||||||
<a href="mailto:feedback@resolutionflow.com" className="text-primary hover:underline font-medium">
|
<a href="mailto:feedback@resolutionflow.com" className="text-primary hover:underline font-medium">
|
||||||
@@ -306,35 +306,35 @@ export default function SurveyPage() {
|
|||||||
|
|
||||||
{/* Top bar */}
|
{/* Top bar */}
|
||||||
<div className="sticky top-0 z-50" style={{ backdropFilter: 'blur(20px)', WebkitBackdropFilter: 'blur(20px)', background: 'rgba(16, 17, 20, 0.85)', borderBottom: '1px solid var(--glass-border)' }}>
|
<div className="sticky top-0 z-50" style={{ backdropFilter: 'blur(20px)', WebkitBackdropFilter: 'blur(20px)', background: 'rgba(16, 17, 20, 0.85)', borderBottom: '1px solid var(--glass-border)' }}>
|
||||||
<div className="mx-auto flex max-w-[680px] items-center justify-between gap-3 px-5 py-3.5">
|
<div className="mx-auto flex max-w-[680px] items-center justify-between gap-3 px-4 py-3 sm:px-5 sm:py-3.5">
|
||||||
<a href="https://resolutionflow.com" target="_blank" rel="noreferrer" className="flex items-center gap-2.5 text-sm font-heading font-bold text-muted-foreground no-underline">
|
<a href="https://resolutionflow.com" target="_blank" rel="noreferrer" className="flex items-center gap-2 sm:gap-2.5 text-sm font-heading font-bold text-muted-foreground no-underline shrink-0">
|
||||||
<BrandLogo size="sm" />
|
<BrandLogo size="sm" />
|
||||||
<span>Resolution<span className="text-gradient-brand">Flow</span></span>
|
<span className="hidden sm:inline">Resolution<span className="text-gradient-brand">Flow</span></span>
|
||||||
</a>
|
</a>
|
||||||
<div className="flex flex-1 items-center gap-2.5" style={{ maxWidth: '240px' }}>
|
<div className="flex flex-1 items-center gap-2 sm:gap-2.5" style={{ maxWidth: '280px' }}>
|
||||||
<div className="flex-1 h-[3px] rounded-full overflow-hidden" style={{ background: 'hsl(var(--border))' }}>
|
<div className="flex-1 h-[3px] rounded-full overflow-hidden" style={{ background: 'hsl(var(--border))' }}>
|
||||||
<div className="h-full rounded-full bg-gradient-brand transition-[width] duration-500" style={{ width: `${progressPct}%` }} />
|
<div className="h-full rounded-full bg-gradient-brand transition-[width] duration-500" style={{ width: `${progressPct}%` }} />
|
||||||
</div>
|
</div>
|
||||||
<span className="text-[11px] font-label text-muted-foreground whitespace-nowrap tabular-nums">{answeredCount} of {TOTAL_QUESTIONS}</span>
|
<span className="text-[11px] font-label text-muted-foreground whitespace-nowrap tabular-nums">{answeredCount}/{TOTAL_QUESTIONS}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="relative z-10 mx-auto max-w-[680px] px-5 pb-24">
|
<div className="relative z-10 mx-auto max-w-[680px] px-4 pb-20 sm:px-5 sm:pb-24">
|
||||||
{/* Hero — visible only on first slide */}
|
{/* Hero — visible only on first slide */}
|
||||||
{currentSlide === 0 && !isComplete && (
|
{currentSlide === 0 && !isComplete && (
|
||||||
<div className="text-center pt-[72px] pb-10 animate-fade-in-up">
|
<div className="text-center pt-10 pb-8 sm:pt-[72px] sm:pb-10 animate-fade-in-up">
|
||||||
<div className="inline-flex items-center gap-1.5 px-3.5 py-1.5 rounded-full text-[11px] font-semibold font-label uppercase tracking-widest mb-5" style={{ background: 'rgba(6, 182, 212, 0.1)', border: '1px solid rgba(6, 182, 212, 0.15)', color: '#06b6d4' }}>
|
<div className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-[10px] sm:text-[11px] font-semibold font-label uppercase tracking-widest mb-4 sm:mb-5" style={{ background: 'rgba(6, 182, 212, 0.1)', border: '1px solid rgba(6, 182, 212, 0.15)', color: '#06b6d4' }}>
|
||||||
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>
|
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>
|
||||||
FlowPilot Research
|
FlowPilot Research
|
||||||
</div>
|
</div>
|
||||||
<h1 className="font-heading text-[clamp(26px,5vw,36px)] font-extrabold leading-tight mb-3">
|
<h1 className="font-heading text-[clamp(24px,5vw,36px)] font-extrabold leading-tight mb-3">
|
||||||
Help Build an AI That<br/>Thinks Like <span className="text-gradient-brand">You</span>
|
Help Build an AI That<br/>Thinks Like <span className="text-gradient-brand">You</span>
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-[15px] text-muted-foreground max-w-[500px] mx-auto leading-relaxed">
|
<p className="text-[14px] sm:text-[15px] text-muted-foreground max-w-[500px] mx-auto leading-relaxed">
|
||||||
We're building an AI assistant for MSP engineers. Your expertise shapes how it thinks. Takes about 5 minutes.
|
We're building an AI assistant for MSP engineers. Your expertise shapes how it thinks. Takes about 5 minutes.
|
||||||
</p>
|
</p>
|
||||||
<div className="flex justify-center gap-7 mt-5 text-[12px] text-muted-foreground">
|
<div className="flex flex-wrap justify-center gap-4 sm:gap-7 mt-4 sm:mt-5 text-[11px] sm:text-[12px] text-muted-foreground">
|
||||||
<span className="flex items-center gap-1.5">
|
<span className="flex items-center gap-1.5">
|
||||||
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="#06b6d4" strokeWidth="2"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
|
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="#06b6d4" strokeWidth="2"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
|
||||||
~5 minutes
|
~5 minutes
|
||||||
@@ -353,11 +353,11 @@ export default function SurveyPage() {
|
|||||||
|
|
||||||
{/* Step dots */}
|
{/* Step dots */}
|
||||||
{!isComplete && (
|
{!isComplete && (
|
||||||
<div className="flex gap-1 mb-9">
|
<div className="flex gap-1 mb-6 sm:mb-9">
|
||||||
{SLIDES.map((_, i) => (
|
{SLIDES.map((_, i) => (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
className="flex-1 h-[3px] rounded-full transition-colors duration-300"
|
className="flex-1 h-1 sm:h-[3px] rounded-full transition-colors duration-300"
|
||||||
style={{
|
style={{
|
||||||
background: i < currentSlide ? '#34d399' : i === currentSlide ? 'linear-gradient(90deg, #06b6d4, #22d3ee)' : 'hsl(var(--border))',
|
background: i < currentSlide ? '#34d399' : i === currentSlide ? 'linear-gradient(90deg, #06b6d4, #22d3ee)' : 'hsl(var(--border))',
|
||||||
}}
|
}}
|
||||||
@@ -374,20 +374,20 @@ export default function SurveyPage() {
|
|||||||
{slide.questions.map(q => (
|
{slide.questions.map(q => (
|
||||||
<QuestionCard key={q.id} question={q} answer={answers[q.id]} setAnswer={setAnswer} />
|
<QuestionCard key={q.id} question={q} answer={answers[q.id]} setAnswer={setAnswer} />
|
||||||
))}
|
))}
|
||||||
<div className="flex justify-between mt-7 gap-3">
|
<div className="flex justify-between mt-6 sm:mt-7 gap-3">
|
||||||
{si > 0 ? (
|
{si > 0 ? (
|
||||||
<button onClick={() => goSlide(si - 1)} className="inline-flex items-center gap-2 px-6 py-3 rounded-[10px] text-sm font-semibold text-muted-foreground transition-all duration-150 hover:text-foreground" style={{ background: 'rgba(255,255,255,0.04)', border: '1px solid rgba(255,255,255,0.06)' }}>
|
<button onClick={() => goSlide(si - 1)} className="inline-flex items-center gap-2 px-4 py-2.5 sm:px-6 sm:py-3 rounded-[10px] text-sm font-semibold text-muted-foreground transition-all duration-150 hover:text-foreground" style={{ background: 'rgba(255,255,255,0.04)', border: '1px solid rgba(255,255,255,0.06)' }}>
|
||||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M19 12H5"/><path d="M12 19l-7-7 7-7"/></svg>
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M19 12H5"/><path d="M12 19l-7-7 7-7"/></svg>
|
||||||
Back
|
Back
|
||||||
</button>
|
</button>
|
||||||
) : <div />}
|
) : <div />}
|
||||||
{si < SLIDES.length - 1 ? (
|
{si < SLIDES.length - 1 ? (
|
||||||
<button onClick={() => goSlide(si + 1)} className="inline-flex items-center gap-2 px-6 py-3 rounded-[10px] text-sm font-semibold bg-gradient-brand text-[#101114] shadow-lg shadow-primary/20 transition-all duration-150 hover:opacity-90 active:scale-[0.97]">
|
<button onClick={() => goSlide(si + 1)} className="inline-flex items-center gap-2 px-5 py-2.5 sm:px-6 sm:py-3 rounded-[10px] text-sm font-semibold bg-gradient-brand text-[#101114] shadow-lg shadow-primary/20 transition-all duration-150 hover:opacity-90 active:scale-[0.97]">
|
||||||
Next
|
Next
|
||||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M5 12h14"/><path d="M12 5l7 7-7 7"/></svg>
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M5 12h14"/><path d="M12 5l7 7-7 7"/></svg>
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button onClick={handleSubmit} disabled={isSubmitting} className="inline-flex items-center gap-2 px-6 py-3 rounded-[10px] text-sm font-semibold bg-gradient-brand text-[#101114] shadow-lg shadow-primary/20 transition-all duration-150 hover:opacity-90 active:scale-[0.97] disabled:opacity-40 disabled:cursor-not-allowed">
|
<button onClick={handleSubmit} disabled={isSubmitting} className="inline-flex items-center gap-2 px-5 py-2.5 sm:px-6 sm:py-3 rounded-[10px] text-sm font-semibold bg-gradient-brand text-[#101114] shadow-lg shadow-primary/20 transition-all duration-150 hover:opacity-90 active:scale-[0.97] disabled:opacity-40 disabled:cursor-not-allowed">
|
||||||
{isSubmitting ? 'Submitting...' : 'Submit'}
|
{isSubmitting ? 'Submitting...' : 'Submit'}
|
||||||
{!isSubmitting && <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M20 6L9 17l-5-5"/></svg>}
|
{!isSubmitting && <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M20 6L9 17l-5-5"/></svg>}
|
||||||
</button>
|
</button>
|
||||||
@@ -405,22 +405,22 @@ export default function SurveyPage() {
|
|||||||
|
|
||||||
{/* Completion */}
|
{/* Completion */}
|
||||||
{isComplete && (
|
{isComplete && (
|
||||||
<div className="text-center pt-16 animate-fade-in-up">
|
<div className="text-center pt-10 sm:pt-16 animate-fade-in-up">
|
||||||
<div className="w-16 h-16 mx-auto mb-5 rounded-full flex items-center justify-center" style={{ background: 'rgba(52, 211, 153, 0.1)' }}>
|
<div className="w-16 h-16 mx-auto mb-5 rounded-full flex items-center justify-center" style={{ background: 'rgba(52, 211, 153, 0.1)' }}>
|
||||||
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#34d399" strokeWidth="2.5"><path d="M20 6L9 17l-5-5"/></svg>
|
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#34d399" strokeWidth="2.5"><path d="M20 6L9 17l-5-5"/></svg>
|
||||||
</div>
|
</div>
|
||||||
<h2 className="font-heading text-2xl font-bold mb-2.5">Response Submitted!</h2>
|
<h2 className="font-heading text-2xl font-bold mb-2.5">Response Submitted!</h2>
|
||||||
<p className="text-muted-foreground text-sm max-w-[440px] mx-auto mb-8 leading-relaxed">
|
<p className="text-muted-foreground text-sm max-w-[440px] mx-auto mb-6 sm:mb-8 leading-relaxed">
|
||||||
Your answers will directly shape how FlowPilot troubleshoots. Would you like a copy of your responses?
|
Your answers will directly shape how FlowPilot troubleshoots. Would you like a copy of your responses?
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{/* Email a copy */}
|
{/* Email a copy */}
|
||||||
<div className="glass-card-static p-6 max-w-[420px] mx-auto mb-5">
|
<div className="glass-card-static p-4 sm:p-6 max-w-[420px] mx-auto mb-5">
|
||||||
<p className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground mb-3">
|
<p className="font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground mb-3">
|
||||||
Email a copy to yourself
|
Email a copy to yourself
|
||||||
</p>
|
</p>
|
||||||
{!emailSent ? (
|
{!emailSent ? (
|
||||||
<div className="flex gap-2">
|
<div className="flex flex-col sm:flex-row gap-2">
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
value={emailInput}
|
value={emailInput}
|
||||||
@@ -456,7 +456,7 @@ export default function SurveyPage() {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
disabled={!emailInput.trim() || emailSending}
|
disabled={!emailInput.trim() || emailSending}
|
||||||
className="inline-flex items-center gap-2 px-5 py-2.5 rounded-[9px] text-sm font-semibold bg-gradient-brand text-[#101114] transition-all duration-150 hover:opacity-90 active:scale-[0.97] disabled:opacity-40 disabled:cursor-not-allowed whitespace-nowrap"
|
className="inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-[9px] text-sm font-semibold bg-gradient-brand text-[#101114] transition-all duration-150 hover:opacity-90 active:scale-[0.97] disabled:opacity-40 disabled:cursor-not-allowed whitespace-nowrap"
|
||||||
>
|
>
|
||||||
{emailSending ? (
|
{emailSending ? (
|
||||||
<>
|
<>
|
||||||
@@ -479,13 +479,13 @@ export default function SurveyPage() {
|
|||||||
|
|
||||||
{/* Copy + Finish buttons */}
|
{/* Copy + Finish buttons */}
|
||||||
<div className="flex gap-2.5 justify-center flex-wrap">
|
<div className="flex gap-2.5 justify-center flex-wrap">
|
||||||
<button onClick={copyAll} className="inline-flex items-center gap-2 px-5 py-2.5 rounded-[10px] text-sm font-semibold transition-all duration-150 text-muted-foreground hover:text-foreground" style={{ background: 'rgba(255,255,255,0.04)', border: '1px solid rgba(255,255,255,0.06)' }}>
|
<button onClick={copyAll} className="inline-flex items-center gap-2 px-4 py-2.5 sm:px-5 rounded-[10px] text-sm font-semibold transition-all duration-150 text-muted-foreground hover:text-foreground" style={{ background: 'rgba(255,255,255,0.04)', border: '1px solid rgba(255,255,255,0.06)' }}>
|
||||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
|
||||||
Copy to Clipboard
|
Copy to Clipboard
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => navigate('/survey/thank-you')}
|
onClick={() => navigate('/survey/thank-you')}
|
||||||
className="inline-flex items-center gap-2 px-6 py-2.5 rounded-[10px] text-sm font-semibold bg-gradient-brand text-[#101114] shadow-lg shadow-primary/20 transition-all duration-150 hover:opacity-90 active:scale-[0.97]"
|
className="inline-flex items-center gap-2 px-5 py-2.5 sm:px-6 rounded-[10px] text-sm font-semibold bg-gradient-brand text-[#101114] shadow-lg shadow-primary/20 transition-all duration-150 hover:opacity-90 active:scale-[0.97]"
|
||||||
>
|
>
|
||||||
Finish
|
Finish
|
||||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M5 12h14"/><path d="M12 5l7 7-7 7"/></svg>
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M5 12h14"/><path d="M12 5l7 7-7 7"/></svg>
|
||||||
@@ -502,13 +502,13 @@ export default function SurveyPage() {
|
|||||||
|
|
||||||
function ScenarioBox({ scenario }: { scenario: { title: string; symptom: string; details: string } }) {
|
function ScenarioBox({ scenario }: { scenario: { title: string; symptom: string; details: string } }) {
|
||||||
return (
|
return (
|
||||||
<div className="rounded-[10px] p-4 px-5 mb-4 text-[13px]" style={{ background: 'linear-gradient(135deg, rgba(6, 182, 212, 0.06), rgba(139, 92, 246, 0.03))', border: '1px solid rgba(6, 182, 212, 0.12)' }}>
|
<div className="rounded-[10px] p-3.5 px-4 sm:p-4 sm:px-5 mb-4 text-[13px]" style={{ background: 'linear-gradient(135deg, rgba(6, 182, 212, 0.06), rgba(139, 92, 246, 0.03))', border: '1px solid rgba(6, 182, 212, 0.12)' }}>
|
||||||
<div className="font-label text-[10px] uppercase tracking-widest mb-2 font-semibold" style={{ color: '#06b6d4' }}>{scenario.title}</div>
|
<div className="font-label text-[10px] uppercase tracking-widest mb-2 font-semibold" style={{ color: '#06b6d4' }}>{scenario.title}</div>
|
||||||
<div className="flex gap-2 mb-1">
|
<div className="sm:flex gap-2 mb-1">
|
||||||
<span className="text-muted-foreground font-medium whitespace-nowrap">Symptom:</span>
|
<span className="text-muted-foreground font-medium whitespace-nowrap">Symptom:</span>
|
||||||
<span className="text-muted-foreground/80">{scenario.symptom}</span>
|
<span className="text-muted-foreground/80">{scenario.symptom}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2">
|
<div className="sm:flex gap-2">
|
||||||
<span className="text-muted-foreground font-medium whitespace-nowrap">Details:</span>
|
<span className="text-muted-foreground font-medium whitespace-nowrap">Details:</span>
|
||||||
<span className="text-muted-foreground/80">{scenario.details}</span>
|
<span className="text-muted-foreground/80">{scenario.details}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -518,11 +518,11 @@ function ScenarioBox({ scenario }: { scenario: { title: string; symptom: string;
|
|||||||
|
|
||||||
function QuestionCard({ question: q, answer, setAnswer }: { question: SurveyQuestion; answer?: string | string[]; setAnswer: (id: string, val: string | string[]) => void }) {
|
function QuestionCard({ question: q, answer, setAnswer }: { question: SurveyQuestion; answer?: string | string[]; setAnswer: (id: string, val: string | string[]) => void }) {
|
||||||
return (
|
return (
|
||||||
<div className="glass-card-static p-7 mb-4 transition-[border-color] duration-200 focus-within:!border-[rgba(6,182,212,0.25)]">
|
<div className="glass-card-static p-4 sm:p-7 mb-3 sm:mb-4 transition-[border-color] duration-200 focus-within:!border-[rgba(6,182,212,0.25)]">
|
||||||
<div className="font-label text-[11px] mb-1.5 font-medium" style={{ color: '#06b6d4' }}>Q{q.num}</div>
|
<div className="font-label text-[11px] mb-1.5 font-medium" style={{ color: '#06b6d4' }}>Q{q.num}</div>
|
||||||
<div className="font-heading text-[15px] font-semibold text-foreground leading-snug mb-1">{q.text}</div>
|
<div className="font-heading text-[14px] sm:text-[15px] font-semibold text-foreground leading-snug mb-1">{q.text}</div>
|
||||||
{q.hint && <div className="text-[12px] text-muted-foreground mb-4 leading-snug">{q.hint}</div>}
|
{q.hint && <div className="text-[12px] text-muted-foreground mb-3 sm:mb-4 leading-snug">{q.hint}</div>}
|
||||||
{!q.hint && <div className="mb-4" />}
|
{!q.hint && <div className="mb-3 sm:mb-4" />}
|
||||||
|
|
||||||
{q.type === 'mc' && q.options && (
|
{q.type === 'mc' && q.options && (
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
@@ -530,17 +530,17 @@ function QuestionCard({ question: q, answer, setAnswer }: { question: SurveyQues
|
|||||||
<button
|
<button
|
||||||
key={opt}
|
key={opt}
|
||||||
onClick={() => setAnswer(q.id, opt)}
|
onClick={() => setAnswer(q.id, opt)}
|
||||||
className="flex items-center gap-3 px-4 py-3 rounded-[9px] text-left text-sm transition-all duration-150 select-none"
|
className="flex items-start gap-3 px-3.5 py-3 sm:px-4 rounded-[9px] text-left text-[13px] sm:text-sm transition-all duration-150 select-none"
|
||||||
style={{
|
style={{
|
||||||
background: answer === opt ? 'rgba(6, 182, 212, 0.1)' : 'rgba(16, 17, 20, 0.6)',
|
background: answer === opt ? 'rgba(6, 182, 212, 0.1)' : 'rgba(16, 17, 20, 0.6)',
|
||||||
border: `1px solid ${answer === opt ? '#06b6d4' : 'var(--glass-border)'}`,
|
border: `1px solid ${answer === opt ? '#06b6d4' : 'var(--glass-border)'}`,
|
||||||
color: answer === opt ? 'hsl(var(--foreground))' : 'hsl(var(--muted-foreground))',
|
color: answer === opt ? 'hsl(var(--foreground))' : 'hsl(var(--muted-foreground))',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="w-[18px] h-[18px] rounded-full flex-shrink-0 flex items-center justify-center transition-all duration-150" style={{ border: `2px solid ${answer === opt ? '#06b6d4' : 'var(--glass-border)'}` }}>
|
<div className="w-[18px] h-[18px] rounded-full flex-shrink-0 flex items-center justify-center transition-all duration-150 mt-0.5" style={{ border: `2px solid ${answer === opt ? '#06b6d4' : 'var(--glass-border)'}` }}>
|
||||||
{answer === opt && <div className="w-2 h-2 rounded-full" style={{ background: '#06b6d4' }} />}
|
{answer === opt && <div className="w-2 h-2 rounded-full" style={{ background: '#06b6d4' }} />}
|
||||||
</div>
|
</div>
|
||||||
<span>{opt}</span>
|
<span className="leading-snug">{opt}</span>
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -557,17 +557,17 @@ function QuestionCard({ question: q, answer, setAnswer }: { question: SurveyQues
|
|||||||
const current = Array.isArray(answer) ? answer : []
|
const current = Array.isArray(answer) ? answer : []
|
||||||
setAnswer(q.id, selected ? current.filter(v => v !== opt) : [...current, opt])
|
setAnswer(q.id, selected ? current.filter(v => v !== opt) : [...current, opt])
|
||||||
}}
|
}}
|
||||||
className="flex items-center gap-3 px-4 py-3 rounded-[9px] text-left text-sm transition-all duration-150 select-none"
|
className="flex items-start gap-3 px-3.5 py-3 sm:px-4 rounded-[9px] text-left text-[13px] sm:text-sm transition-all duration-150 select-none"
|
||||||
style={{
|
style={{
|
||||||
background: selected ? 'rgba(6, 182, 212, 0.1)' : 'rgba(16, 17, 20, 0.6)',
|
background: selected ? 'rgba(6, 182, 212, 0.1)' : 'rgba(16, 17, 20, 0.6)',
|
||||||
border: `1px solid ${selected ? '#06b6d4' : 'var(--glass-border)'}`,
|
border: `1px solid ${selected ? '#06b6d4' : 'var(--glass-border)'}`,
|
||||||
color: selected ? 'hsl(var(--foreground))' : 'hsl(var(--muted-foreground))',
|
color: selected ? 'hsl(var(--foreground))' : 'hsl(var(--muted-foreground))',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="w-[18px] h-[18px] rounded-[5px] flex-shrink-0 flex items-center justify-center text-[11px] transition-all duration-150" style={{ border: `2px solid ${selected ? '#06b6d4' : 'var(--glass-border)'}`, background: selected ? '#06b6d4' : 'transparent', color: selected ? 'white' : 'transparent' }}>
|
<div className="w-[18px] h-[18px] rounded-[5px] flex-shrink-0 flex items-center justify-center text-[11px] transition-all duration-150 mt-0.5" style={{ border: `2px solid ${selected ? '#06b6d4' : 'var(--glass-border)'}`, background: selected ? '#06b6d4' : 'transparent', color: selected ? 'white' : 'transparent' }}>
|
||||||
{'\u2713'}
|
{'\u2713'}
|
||||||
</div>
|
</div>
|
||||||
<span>{opt}</span>
|
<span className="leading-snug">{opt}</span>
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
@@ -583,7 +583,7 @@ function QuestionCard({ question: q, answer, setAnswer }: { question: SurveyQues
|
|||||||
value={(answer as string) || ''}
|
value={(answer as string) || ''}
|
||||||
onChange={e => setAnswer(q.id, e.target.value)}
|
onChange={e => setAnswer(q.id, e.target.value)}
|
||||||
placeholder="Type your answer here..."
|
placeholder="Type your answer here..."
|
||||||
className="w-full min-h-[100px] rounded-[9px] p-3.5 text-sm text-foreground leading-relaxed resize-y transition-all duration-200 placeholder:text-[#5a6170] focus:outline-none"
|
className="w-full min-h-[100px] rounded-[9px] p-3 sm:p-3.5 text-[13px] sm:text-sm text-foreground leading-relaxed resize-y transition-all duration-200 placeholder:text-[#5a6170] focus:outline-none"
|
||||||
style={{
|
style={{
|
||||||
background: 'rgba(16, 17, 20, 0.6)',
|
background: 'rgba(16, 17, 20, 0.6)',
|
||||||
border: '1px solid var(--glass-border)',
|
border: '1px solid var(--glass-border)',
|
||||||
@@ -614,7 +614,7 @@ function RangeInput({ question: q, value, onChange }: { question: SurveyQuestion
|
|||||||
step={q.step}
|
step={q.step}
|
||||||
value={numVal}
|
value={numVal}
|
||||||
onChange={e => onChange(e.target.value + (q.suffix || ''))}
|
onChange={e => onChange(e.target.value + (q.suffix || ''))}
|
||||||
className="w-full h-1 rounded-full appearance-none cursor-pointer"
|
className="w-full h-2 sm:h-1 rounded-full appearance-none cursor-pointer touch-none"
|
||||||
style={{
|
style={{
|
||||||
background: `linear-gradient(to right, #06b6d4 0%, #06b6d4 ${((numVal - (q.min || 0)) / ((q.max || 10) - (q.min || 0))) * 100}%, hsl(var(--border)) ${((numVal - (q.min || 0)) / ((q.max || 10) - (q.min || 0))) * 100}%, hsl(var(--border)) 100%)`,
|
background: `linear-gradient(to right, #06b6d4 0%, #06b6d4 ${((numVal - (q.min || 0)) / ((q.max || 10) - (q.min || 0))) * 100}%, hsl(var(--border)) ${((numVal - (q.min || 0)) / ((q.max || 10) - (q.min || 0))) * 100}%, hsl(var(--border)) 100%)`,
|
||||||
}}
|
}}
|
||||||
@@ -710,7 +710,7 @@ function DragRank({ items, onChange }: { items: string[]; onChange: (items: stri
|
|||||||
onDragEnd={handleDragEnd}
|
onDragEnd={handleDragEnd}
|
||||||
onDragLeave={() => setOverIdx(null)}
|
onDragLeave={() => setOverIdx(null)}
|
||||||
onTouchStart={() => handleTouchStart(idx)}
|
onTouchStart={() => handleTouchStart(idx)}
|
||||||
className="flex items-center gap-3 px-4 py-2.5 rounded-[9px] text-sm transition-all duration-150 select-none"
|
className="flex items-center gap-2.5 sm:gap-3 px-3 py-3 sm:px-4 sm:py-2.5 rounded-[9px] text-[13px] sm:text-sm transition-all duration-150 select-none"
|
||||||
style={{
|
style={{
|
||||||
background: overIdx === idx ? 'rgba(6, 182, 212, 0.1)' : 'rgba(16, 17, 20, 0.6)',
|
background: overIdx === idx ? 'rgba(6, 182, 212, 0.1)' : 'rgba(16, 17, 20, 0.6)',
|
||||||
border: `1px solid ${overIdx === idx || draggingIdx === idx ? '#06b6d4' : 'var(--glass-border)'}`,
|
border: `1px solid ${overIdx === idx || draggingIdx === idx ? '#06b6d4' : 'var(--glass-border)'}`,
|
||||||
@@ -723,7 +723,7 @@ function DragRank({ items, onChange }: { items: string[]; onChange: (items: stri
|
|||||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="9" cy="6" r="1"/><circle cx="15" cy="6" r="1"/><circle cx="9" cy="12" r="1"/><circle cx="15" cy="12" r="1"/><circle cx="9" cy="18" r="1"/><circle cx="15" cy="18" r="1"/></svg>
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="9" cy="6" r="1"/><circle cx="15" cy="6" r="1"/><circle cx="9" cy="12" r="1"/><circle cx="15" cy="12" r="1"/><circle cx="9" cy="18" r="1"/><circle cx="15" cy="18" r="1"/></svg>
|
||||||
</div>
|
</div>
|
||||||
<div className="font-label text-[11px] font-semibold w-5 text-center flex-shrink-0" style={{ color: '#06b6d4' }}>{idx + 1}</div>
|
<div className="font-label text-[11px] font-semibold w-5 text-center flex-shrink-0" style={{ color: '#06b6d4' }}>{idx + 1}</div>
|
||||||
<div className="flex-1">{item}</div>
|
<div className="flex-1 leading-snug">{item}</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user