Swap to shadcn components and polish the design
Components (added via the shadcn MCP/CLI): - Navbar: NavigationMenu on desktop, Sheet on mobile; drops Navbar.module.css and the hand-rolled slide-down menu - Buttons: shadcn Button via a shared ContactButtons component (replaces Button.js and its CSS module) - Card for price cards, testimonials, the business block and plan; Table for prices; Input/Textarea/Label/NativeSelect/RadioGroup and Alert in the quote form; Separator in the footer - Components import cn from @/lib/utils (not the new "cn" package); accordion moved to the unified radix-ui package Design tweaks: - Geist Sans is actually applied (font variables were on <body>, but Tailwind reads them on <html>, so the site fell back to system fonts) - Theme primary set to the existing brand blue; slightly smaller radius - Balanced, tighter heading tracking; muted secondary text - 44px contact buttons; 16px FAQ text; tighter homepage spacing - Full-width selects with 16px text on phones (no iOS zoom) Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
f6846ebaae
commit
f916f058fc
36 files changed
+2888
-823
No files matched your search
+44
-49
@@ -2,8 +2,9 @@ import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import styles from "./page.module.css";
|
||||
import bgimage from "./assets/header-bg.jpg";
|
||||
import Button from "./components/Button";
|
||||
import ContactButtons from "./components/ContactButtons";
|
||||
import MapEmbed from "./components/MapEmbed";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import ContactForm from "./components/ContactForm";
|
||||
import FaqList from "./components/FaqList";
|
||||
import CtaBand from "./components/CtaBand";
|
||||
@@ -18,10 +19,8 @@ import {
|
||||
HardDrive,
|
||||
Laptop,
|
||||
MapPin,
|
||||
MessageSquare,
|
||||
Monitor,
|
||||
MonitorCog,
|
||||
Phone,
|
||||
Power,
|
||||
ShieldAlert,
|
||||
Star,
|
||||
@@ -103,7 +102,7 @@ const steps = [
|
||||
function SectionCta() {
|
||||
return (
|
||||
<p className="text-center mt-8">
|
||||
<a href={links.tel} className="font-bold text-sky-800 hover:underline">
|
||||
<a href={links.tel} className="font-semibold text-primary hover:underline">
|
||||
Call or text {business.phone}
|
||||
</a>
|
||||
</p>
|
||||
@@ -138,16 +137,7 @@ export default function Home() {
|
||||
tell you what it costs before I start. Local, honest help
|
||||
for West Auckland.
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-3 mb-6">
|
||||
<Button href={links.tel}>
|
||||
<Phone aria-hidden="true" />
|
||||
Call {business.phone}
|
||||
</Button>
|
||||
<Button href={links.sms} variant="outline">
|
||||
<MessageSquare aria-hidden="true" />
|
||||
Text me
|
||||
</Button>
|
||||
</div>
|
||||
<ContactButtons onDark className="mb-6" />
|
||||
<p className="flex flex-wrap items-center gap-x-2 gap-y-1 text-sm">
|
||||
<Star
|
||||
aria-hidden="true"
|
||||
@@ -169,30 +159,31 @@ export default function Home() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="container mx-auto mb-32">
|
||||
<section className="container mx-auto mb-24">
|
||||
<h2 className="text-center text-3xl font-bold mb-2">
|
||||
Common fixes & prices
|
||||
</h2>
|
||||
<p className="text-center mb-8 text-slate-600">
|
||||
<p className="text-center mb-8 text-muted-foreground">
|
||||
Labour prices. Parts are extra, and I'll always quote before
|
||||
starting.
|
||||
</p>
|
||||
<ul className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
{commonFixes.map(({ icon: Icon, title, price, href }) => (
|
||||
<li key={title}>
|
||||
<Link
|
||||
href={href}
|
||||
className="flex h-full items-center gap-4 rounded-lg border p-4 transition hover:border-sky-800 hover:shadow-sm"
|
||||
>
|
||||
<Icon
|
||||
aria-hidden="true"
|
||||
className="size-8 shrink-0 text-sky-800"
|
||||
strokeWidth={1.5}
|
||||
/>
|
||||
<span>
|
||||
<span className="block font-bold">{title}</span>
|
||||
<span className="block text-sky-800">{price}</span>
|
||||
</span>
|
||||
<Link href={href} className="group block h-full rounded-xl">
|
||||
<Card className="h-full flex-row items-center gap-4 p-4 shadow-none transition-colors group-hover:border-primary">
|
||||
<Icon
|
||||
aria-hidden="true"
|
||||
className="size-7 shrink-0 text-primary"
|
||||
strokeWidth={1.5}
|
||||
/>
|
||||
<span>
|
||||
<span className="block font-semibold">{title}</span>
|
||||
<span className="block text-sm text-muted-foreground">
|
||||
{price}
|
||||
</span>
|
||||
</span>
|
||||
</Card>
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
@@ -200,7 +191,7 @@ export default function Home() {
|
||||
<SectionCta />
|
||||
<Link
|
||||
href="/windows-10"
|
||||
className="mt-8 flex items-center justify-between gap-4 rounded-lg bg-sky-900 p-4 text-white hover:bg-sky-800"
|
||||
className="mt-8 flex items-center justify-between gap-4 rounded-lg bg-sky-900 p-4 text-white transition-colors hover:bg-primary"
|
||||
>
|
||||
<span>
|
||||
<span className="block font-bold">Still on Windows 10?</span>
|
||||
@@ -212,15 +203,15 @@ export default function Home() {
|
||||
</Link>
|
||||
</section>
|
||||
|
||||
<section className="bg-slate-100 py-16 mb-32">
|
||||
<section className="bg-slate-100 py-16 mb-24">
|
||||
<div className="container mx-auto">
|
||||
<h2 className="text-center text-3xl font-bold mb-8">
|
||||
How it works
|
||||
</h2>
|
||||
<ol className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
{steps.map(({ title, text }, i) => (
|
||||
<li key={title} className="text-center max-w-sm mx-auto">
|
||||
<span className="mx-auto mb-4 flex size-12 items-center justify-center rounded-full bg-sky-800 text-xl font-bold text-white">
|
||||
<li key={title} className="border-t border-slate-300 pt-4">
|
||||
<span className="mb-3 flex size-8 items-center justify-center rounded-full bg-primary text-sm font-semibold text-primary-foreground">
|
||||
{i + 1}
|
||||
</span>
|
||||
<h3 className="text-xl font-bold mb-2">{title}</h3>
|
||||
@@ -232,7 +223,7 @@ export default function Home() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="container mx-auto mb-32 max-w-3xl text-center">
|
||||
<section className="container mx-auto mb-24 max-w-3xl text-center">
|
||||
<h2 className="text-3xl font-bold mb-4">
|
||||
Hi, I'm {business.ownerName}
|
||||
</h2>
|
||||
@@ -249,22 +240,26 @@ export default function Home() {
|
||||
<SectionCta />
|
||||
</section>
|
||||
|
||||
<section className="container mx-auto mb-32">
|
||||
<section className="container mx-auto mb-24">
|
||||
<h2 className="text-center text-3xl font-bold mb-8">
|
||||
What customers say
|
||||
</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 max-w-4xl mx-auto">
|
||||
{business.testimonials.map(({ name, quote }) => (
|
||||
<figure key={name} className="rounded-lg border p-6">
|
||||
<blockquote className="mb-3">“{quote}”</blockquote>
|
||||
<figcaption className="font-bold">{name}</figcaption>
|
||||
</figure>
|
||||
<Card key={name} className="shadow-none">
|
||||
<CardContent>
|
||||
<figure>
|
||||
<blockquote className="mb-3">“{quote}”</blockquote>
|
||||
<figcaption className="font-semibold">{name}</figcaption>
|
||||
</figure>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
<p className="text-center mt-8">
|
||||
<a
|
||||
href={business.googleBusinessProfileUrl}
|
||||
className="inline-flex items-center gap-1 font-bold text-sky-800 hover:underline"
|
||||
className="inline-flex items-center gap-1 font-semibold text-primary hover:underline"
|
||||
>
|
||||
Read all reviews on Google
|
||||
<ArrowRight aria-hidden="true" className="size-4" />
|
||||
@@ -272,7 +267,7 @@ export default function Home() {
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="container mx-auto mb-32 flex flex-col gap-8 lg:flex-row">
|
||||
<section className="container mx-auto mb-24 flex flex-col gap-8 lg:flex-row">
|
||||
<div className="w-full">
|
||||
<h2 className="text-3xl font-bold mb-4">Areas I serve</h2>
|
||||
<p className="mb-4 flex items-start gap-2">
|
||||
@@ -293,7 +288,7 @@ export default function Home() {
|
||||
{page ? (
|
||||
<Link
|
||||
href={`/areas/${page.slug}`}
|
||||
className="text-sky-800 hover:underline"
|
||||
className="text-primary hover:underline"
|
||||
>
|
||||
{area}
|
||||
</Link>
|
||||
@@ -311,7 +306,7 @@ export default function Home() {
|
||||
<p className="mt-4">
|
||||
<a
|
||||
href={links.tel}
|
||||
className="font-bold text-sky-800 hover:underline"
|
||||
className="font-semibold text-primary hover:underline"
|
||||
>
|
||||
Call or text {business.phone}
|
||||
</a>
|
||||
@@ -322,11 +317,11 @@ export default function Home() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="container mx-auto mb-32">
|
||||
<div className="rounded-lg border p-6 md:p-8 flex flex-col md:flex-row gap-6 md:items-center">
|
||||
<section className="container mx-auto mb-24">
|
||||
<Card className="flex-col gap-6 p-6 shadow-none md:flex-row md:items-center md:p-8">
|
||||
<Briefcase
|
||||
aria-hidden="true"
|
||||
className="size-12 shrink-0 text-sky-800"
|
||||
className="size-12 shrink-0 text-primary"
|
||||
strokeWidth={1.5}
|
||||
/>
|
||||
<div className="flex-1">
|
||||
@@ -339,16 +334,16 @@ export default function Home() {
|
||||
</div>
|
||||
<Link
|
||||
href="/business"
|
||||
className="inline-flex items-center gap-1 font-bold text-sky-800 hover:underline"
|
||||
className="inline-flex items-center gap-1 font-semibold text-primary hover:underline"
|
||||
>
|
||||
Business IT plans
|
||||
<ArrowRight aria-hidden="true" className="size-4" />
|
||||
</Link>
|
||||
</div>
|
||||
</Card>
|
||||
</section>
|
||||
|
||||
<section
|
||||
className="container mx-auto max-w-3xl mb-32 scroll-mt-20"
|
||||
className="container mx-auto max-w-3xl mb-24 scroll-mt-20"
|
||||
id="faq"
|
||||
>
|
||||
<h2 className="text-center text-3xl font-bold mb-8">
|
||||
|
||||
Reference in new issue
Block a user