Polish website flow and add Questions story

This commit is contained in:
2026-08-24 12:26:54 -04:00
parent dcc1fff784
commit 33d4f19bf0
16 changed files with 385 additions and 232 deletions
+10 -10
View File
@@ -20,7 +20,7 @@ const features = [
icon: CalendarDays,
title: "Turn a visit into context you can review",
description:
"Type or paste notes, import a portal screenshot or document, or use consent-gated recording to create a summary you can check.",
"Keep the important details from a visit together in a summary you can check and revisit.",
points: [
"Keep the visit and summary easy to revisit",
"Review important details before relying on them",
@@ -53,13 +53,13 @@ const features = [
id: "questions",
label: "Questions",
icon: MessageCircle,
title: "Facts first, fluent answers second",
title: "Keep the question for the right conversation",
description:
"Ask about a visit or medication using the context you have already collected. Dosing changes, diagnosis, and treatment decisions stay with a clinician or pharmacist.",
"Ask about a visit or medication. When professional judgment is needed, save the question and keep guidance on who may be helpful to ask.",
points: [
"Keep answers connected to your own context",
"Prepare for a clearer care conversation",
"High-risk or unsupported questions defer to a professional",
"Capture questions as they come up",
"Keep a ready list for the next appointment",
"See whether a doctor, prescriber, or pharmacist may be helpful",
],
image: "/screenshots/product-bezel-2026-08-23-complete/ask-black.webp",
darkImage:
@@ -143,10 +143,10 @@ export function FeatureShowcase() {
onClick={() => setActiveId(feature.id)}
onKeyDown={onTabKeyDown}
className={cn(
"focus-visible:ring-primary/40 inline-flex min-h-11 shrink-0 items-center gap-2 rounded-full border px-4 py-2 text-sm font-semibold transition-colors outline-none focus-visible:ring-2",
"focus-visible:ring-primary/40 inline-flex min-h-11 shrink-0 items-center gap-2 rounded-full px-4 py-2 text-sm font-semibold transition-colors outline-none focus-visible:ring-2",
isActive
? "border-primary-button bg-primary-button text-white shadow-sm"
: "border-border-soft bg-surface/75 text-muted-foreground hover:border-primary/30 hover:text-foreground backdrop-blur-xl",
? "bg-primary-button text-white shadow-sm"
: "bg-surface/75 text-muted-foreground hover:bg-surface-soft hover:text-foreground backdrop-blur-xl",
)}
>
<Icon className="size-4" aria-hidden="true" />
@@ -190,7 +190,7 @@ export function FeatureShowcase() {
</div>
<div className="justify-self-center lg:justify-self-end">
<div className="glass-panel rounded-[2.5rem] p-5 sm:p-7">
<div className="surface-panel rounded-[2.5rem] p-5 sm:p-7">
<PhoneMockup
src={active.image}
darkSrc={active.darkImage}
+2 -3
View File
@@ -55,7 +55,7 @@ export function LoginForm({ redirectTo }: LoginFormProps) {
<div className="relative flex min-h-screen items-center justify-center px-4 py-16">
<ScreenBackground />
<Card className="w-full max-w-md border-border-soft/80 bg-surface/95 shadow-[0_20px_50px_rgba(15,23,42,0.12)] backdrop-blur-sm">
<Card className="w-full max-w-md bg-surface/95 shadow-[0_20px_50px_rgba(15,23,42,0.12)] backdrop-blur-sm">
<CardHeader className="items-center space-y-4 text-center">
<MedscribeLogo className="h-8 w-[100px] text-foreground" />
<div className="space-y-2">
@@ -81,7 +81,6 @@ export function LoginForm({ redirectTo }: LoginFormProps) {
name="password"
type="password"
autoComplete="current-password"
autoFocus
required
value={password}
onChange={(event) => setPassword(event.target.value)}
@@ -103,7 +102,7 @@ export function LoginForm({ redirectTo }: LoginFormProps) {
className="w-full"
disabled={isSubmitting || password.length === 0}
>
{isSubmitting ? "Checking..." : "Continue"}
{isSubmitting ? "Checking" : "Continue"}
</Button>
</form>
</CardContent>
+76
View File
@@ -0,0 +1,76 @@
import { ArrowUpRight, Check, MessageCircleQuestion, Plus } from "lucide-react";
import { cn } from "~/lib/utils";
const questions = [
{
question: "Could this change be related to my medication?",
recipient: "Prescriber",
},
{
question: "What should I expect at the follow-up?",
recipient: "Care team",
},
{
question: "Is this still the right time to take it?",
recipient: "Pharmacist",
},
] as const;
export function QuestionsPreview({ className }: { className?: string }) {
return (
<div
className={cn(
"surface-panel overflow-hidden rounded-[2rem] p-5 sm:p-6",
className,
)}
aria-label="Illustrative Questions list in Medscribe"
>
<div className="flex items-start justify-between gap-5 px-1 pb-5">
<div>
<p className="text-primary text-xs font-bold tracking-[0.16em] uppercase">
Questions
</p>
<h3 className="text-foreground mt-2 font-serif text-2xl font-semibold tracking-[-0.02em]">
Ready for the conversation
</h3>
</div>
<span className="bg-primary-light text-primary flex size-10 shrink-0 items-center justify-center rounded-full">
<MessageCircleQuestion className="size-5" aria-hidden="true" />
</span>
</div>
<div className="bg-canvas/70 overflow-hidden rounded-[1.35rem]">
{questions.map((item, index) => (
<div
key={item.question}
className={cn(
"grid grid-cols-[1fr_auto] gap-4 px-4 py-4 sm:px-5",
index > 0 && "border-border-soft/55 border-t",
)}
>
<div className="min-w-0">
<p className="text-foreground text-sm leading-snug font-semibold text-pretty">
{item.question}
</p>
<p className="text-muted-foreground mt-2 flex items-center gap-1.5 text-xs">
Ask your {item.recipient.toLowerCase()}
<ArrowUpRight className="size-3" aria-hidden="true" />
</p>
</div>
<span className="bg-success-light text-success mt-0.5 flex size-6 items-center justify-center rounded-full">
<Check className="size-3.5" aria-hidden="true" />
</span>
</div>
))}
</div>
<div className="text-muted-foreground mt-5 flex items-center gap-2 px-1 text-xs leading-relaxed">
<span className="bg-primary-light text-primary flex size-7 shrink-0 items-center justify-center rounded-full">
<Plus className="size-3.5" aria-hidden="true" />
</span>
Save a question the moment it comes to you.
</div>
</div>
);
}
-3
View File
@@ -2,9 +2,6 @@ export function ScreenBackground() {
return (
<div className="pointer-events-none fixed inset-0 -z-10 overflow-hidden print:hidden">
<div className="ambient-canvas absolute inset-0" />
<div className="bg-primary-light/22 absolute -top-48 -left-40 size-[34rem] rounded-full blur-3xl" />
<div className="absolute top-[28vh] -right-52 size-[38rem] rounded-full bg-[#d9ecff]/30 blur-3xl dark:bg-[#123d5b]/28" />
<div className="absolute bottom-[6vh] -left-56 size-[38rem] rounded-full bg-[#fbe9d7]/32 blur-3xl dark:bg-[#4a3026]/24" />
</div>
);
}
+1 -1
View File
@@ -11,7 +11,7 @@ const footerLinks = [
export function SiteFooter() {
return (
<footer className="print-hidden px-3 pb-3 sm:px-5 sm:pb-5">
<div className="glass-panel mx-auto grid max-w-6xl gap-10 rounded-[2rem] px-6 py-10 text-sm sm:px-8 md:grid-cols-[1.3fr_0.7fr_0.7fr]">
<div className="surface-panel mx-auto grid max-w-6xl gap-10 rounded-[2rem] px-6 py-10 text-sm sm:px-8 md:grid-cols-[1.3fr_0.7fr_0.7fr]">
<div>
<Link
href="/"
+40 -14
View File
@@ -1,5 +1,6 @@
"use client";
import { useEffect, useRef, useState } from "react";
import { Menu } from "lucide-react";
import Link from "next/link";
import { usePathname } from "next/navigation";
@@ -11,15 +12,38 @@ import { cn } from "~/lib/utils";
const navigation = [
{ href: "/", label: "Home" },
{ href: "/how-it-works", label: "How it works" },
{ href: "/#questions", label: "Questions" },
{ href: "/privacy", label: "Privacy" },
] as const;
export function SiteHeader() {
const pathname = usePathname();
const [hash, setHash] = useState("");
const mobileMenu = useRef<HTMLDetailsElement>(null);
useEffect(() => {
const updateHash = () => setHash(window.location.hash);
updateHash();
window.addEventListener("hashchange", updateHash);
return () => window.removeEventListener("hashchange", updateHash);
}, [pathname]);
const isActive = (href: (typeof navigation)[number]["href"]) => {
if (href === "/#questions") {
return pathname === "/" && hash === "#questions";
}
if (href === "/") {
return pathname === "/" && hash !== "#questions";
}
return pathname === href;
};
return (
<header className="print-hidden sticky top-0 z-50 px-3 pt-3 sm:px-5">
<div className="glass-panel-strong relative mx-auto flex h-14 max-w-6xl items-center gap-5 rounded-[1.25rem] px-3.5 sm:px-5">
<div className="surface-panel-strong relative mx-auto flex h-14 max-w-6xl items-center gap-5 rounded-[1.25rem] px-3.5 sm:px-5">
<Link
href="/"
className="text-foreground focus-visible:ring-primary/40 absolute left-1/2 flex shrink-0 -translate-x-1/2 items-center gap-2.5 rounded-md transition-opacity outline-none hover:opacity-75 focus-visible:ring-2 md:static md:translate-x-0"
@@ -39,11 +63,11 @@ export function SiteHeader() {
<Link
key={item.href}
href={item.href}
aria-current={pathname === item.href ? "page" : undefined}
aria-current={isActive(item.href) ? "page" : undefined}
className={cn(
"focus-visible:ring-primary/40 rounded-full px-3 py-2 text-sm font-medium transition-all outline-none focus-visible:ring-2",
pathname === item.href
? "text-foreground border border-white/45 bg-white/[0.48] shadow-[inset_0_1px_0_rgba(255,255,255,0.5),0_5px_16px_rgba(15,118,110,0.1)] dark:border-white/10 dark:bg-white/8"
"focus-visible:ring-primary/40 rounded-full px-3 py-2 text-sm font-medium transition-colors outline-none focus-visible:ring-2",
isActive(item.href)
? "bg-primary-light/70 text-primary"
: "text-muted-foreground hover:bg-primary-light/60 hover:text-foreground",
)}
>
@@ -55,23 +79,24 @@ export function SiteHeader() {
</Button>
</nav>
<details className="group relative ml-auto md:hidden">
<summary className="border-border-soft/70 bg-surface/70 text-foreground focus-visible:ring-primary/40 flex size-10 cursor-pointer list-none items-center justify-center rounded-full border outline-none marker:content-none focus-visible:ring-2 [&::-webkit-details-marker]:hidden">
<details ref={mobileMenu} className="group relative ml-auto md:hidden">
<summary className="bg-surface-soft text-foreground focus-visible:ring-primary/40 flex size-10 cursor-pointer list-none items-center justify-center rounded-full outline-none marker:content-none focus-visible:ring-2 [&::-webkit-details-marker]:hidden">
<Menu className="size-5" aria-hidden="true" />
<span className="sr-only">Open navigation</span>
</summary>
<nav
aria-label="Mobile navigation"
className="glass-panel-strong absolute top-12 right-0 flex w-64 flex-col rounded-[1.4rem] p-2"
className="surface-panel-strong absolute top-12 right-0 flex w-64 flex-col rounded-[1.4rem] p-2"
>
{navigation.map((item) => (
<Link
key={item.href}
href={item.href}
aria-current={pathname === item.href ? "page" : undefined}
className={cn(
"text-foreground focus-visible:ring-primary/40 rounded-xl px-4 py-3 text-sm font-medium outline-none focus-visible:ring-2",
pathname === item.href
key={item.href}
href={item.href}
onClick={() => mobileMenu.current?.removeAttribute("open")}
aria-current={isActive(item.href) ? "page" : undefined}
className={cn(
"text-foreground focus-visible:ring-primary/40 rounded-xl px-4 py-3 text-sm font-medium outline-none focus-visible:ring-2",
isActive(item.href)
? "bg-primary-light/75 shadow-[inset_0_1px_0_rgba(255,255,255,0.35)]"
: "hover:bg-primary-light/60",
)}
@@ -81,6 +106,7 @@ export function SiteHeader() {
))}
<Link
href="/access"
onClick={() => mobileMenu.current?.removeAttribute("open")}
className="bg-primary-button hover:bg-primary-button/90 focus-visible:ring-primary/40 mt-1 rounded-xl px-4 py-3 text-center text-sm font-semibold text-white outline-none focus-visible:ring-2"
>
Request access
+1 -1
View File
@@ -9,7 +9,7 @@ const badgeVariants = cva(
variants: {
variant: {
default: "bg-primary-light text-primary",
outline: "border border-border-soft bg-surface text-muted-foreground",
outline: "bg-surface-soft text-muted-foreground",
success: "bg-success-light text-success",
},
},
+3 -3
View File
@@ -5,14 +5,14 @@ import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "~/lib/utils";
const buttonVariants = cva(
"print-hidden inline-flex shrink-0 items-center justify-center gap-2 rounded-full text-sm font-semibold whitespace-nowrap transition-all outline-none focus-visible:ring-2 focus-visible:ring-primary/30 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
"print-hidden inline-flex shrink-0 items-center justify-center gap-2 rounded-full text-sm font-semibold whitespace-nowrap transition-[color,background-color,box-shadow,transform] duration-200 outline-none focus-visible:ring-2 focus-visible:ring-primary/30 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
{
variants: {
variant: {
default:
"bg-primary-button text-white shadow-[0_10px_25px_rgba(15,118,110,0.2)] hover:-translate-y-0.5 hover:bg-primary-button/90",
"bg-primary-button text-white shadow-[0_8px_22px_rgba(15,118,110,0.16)] hover:-translate-y-0.5 hover:bg-primary-button/90",
outline:
"border border-border-soft bg-surface/75 text-foreground backdrop-blur-xl hover:-translate-y-0.5 hover:bg-surface-soft",
"bg-surface/85 text-foreground shadow-[0_4px_16px_rgba(15,23,42,0.06)] backdrop-blur-xl hover:-translate-y-0.5 hover:bg-surface-soft",
secondary: "bg-primary-light text-primary hover:bg-primary-light/80",
ghost:
"text-muted-foreground hover:bg-surface-soft hover:text-foreground",
+1 -1
View File
@@ -6,7 +6,7 @@ function Card({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
className={cn(
"rounded-lg border border-border-soft bg-surface text-foreground shadow-[0_1px_4px_rgba(0,0,0,0.05)]",
"rounded-2xl bg-surface text-foreground shadow-[0_14px_40px_rgba(15,23,42,0.08)]",
className,
)}
{...props}