Goal
Create Contact: a centered, accessible form with name, email, and message fields that look clear in light and dark mode.
function Contact() {
return (
<section id="contact" className="bg-white py-20 dark:bg-slate-900">
<div className="mx-auto flex max-w-5xl flex-col items-center px-6">
<h2 className="mb-2 text-center text-3xl font-bold text-slate-900 dark:text-slate-100">
Contact
</h2>
<p className="mb-10 max-w-2xl text-center text-slate-600 dark:text-slate-400">
Have a project or question? Send a message: I usually reply within a
few days.
</p>
<form
className="mx-auto grid w-full max-w-2xl gap-4"
onSubmit={(event) => {
event.preventDefault();
alert("Thanks! Wire this form to an API or email service later.");
}}
>
<label className="grid gap-1 text-sm font-medium text-slate-700 dark:text-slate-200">
Name
<input
type="text"
required
className="w-full rounded-md border border-slate-300 bg-white px-3 py-2 text-slate-900 shadow-sm outline-none transition focus:border-blue-500 focus:ring-2 focus:ring-blue-200 dark:border-slate-600 dark:bg-slate-900 dark:text-slate-100"
/>
</label>
<label className="grid gap-1 text-sm font-medium text-slate-700 dark:text-slate-200">
Email
<input
type="email"
required
className="w-full rounded-md border border-slate-300 bg-white px-3 py-2 text-slate-900 shadow-sm outline-none transition focus:border-blue-500 focus:ring-2 focus:ring-blue-200 dark:border-slate-600 dark:bg-slate-900 dark:text-slate-100"
/>
</label>
<label className="grid gap-1 text-sm font-medium text-slate-700 dark:text-slate-200">
Message
<textarea
rows={5}
required
className="w-full rounded-md border border-slate-300 bg-white px-3 py-2 text-slate-900 shadow-sm outline-none transition focus:border-blue-500 focus:ring-2 focus:ring-blue-200 dark:border-slate-600 dark:bg-slate-900 dark:text-slate-100"
/>
</label>
<button
type="submit"
className="w-full rounded-md bg-blue-600 px-5 py-3 text-sm font-semibold text-white transition hover:bg-blue-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500 active:scale-95"
>
Send message
</button>
</form>
</div>
</section>
);
}
export default Contact;
The alert is a stand-in. Later you can post to Formspree, Netlify Forms, or your own API.
Tailwind chunks explained: centered section
| Class |
Meaning |
flex flex-col items-center |
Center heading, blurb, and form as a column |
text-center |
Center the heading and intro text |
max-w-2xl |
Comfortable reading / form width |
w-full |
Form still fills that max width on phones |
| Class |
Meaning |
grid gap-4 |
Stack fields with even spacing |
grid gap-1 on <label> |
Small gap between label text and input |
text-sm font-medium |
Clear field labels |
wrapping control in <label> |
Clicking the label focuses the input |
| Class |
Meaning |
w-full |
Full width of the form |
rounded-md border |
Soft outlined field |
border-slate-300 / dark:border-slate-600 |
Theme-aware border |
bg-white / dark:bg-slate-900 |
Field background |
px-3 py-2 |
Typing space inside the control |
shadow-sm |
Slight depth |
outline-none |
Remove default focus outline (we replace it) |
transition |
Smooth focus style change |
focus:border-blue-500 |
Blue border when focused |
focus:ring-2 focus:ring-blue-200 |
Soft focus ring for visibility |
| Class |
Meaning |
w-full |
Full-width primary action |
bg-blue-600 / hover:bg-blue-700 |
Default + hover fill |
transition |
Animate hover and active |
focus-visible:outline |
Keyboard-only focus ring (mouse clicks stay clean) |
focus-visible:outline-2 |
Ring thickness |
focus-visible:outline-offset-2 |
Gap between button and ring |
focus-visible:outline-blue-500 |
Ring color |
active:scale-95 |
Slight press-in on click |
Wire into App.jsx
import Navbar from "./components/Navbar";
import Hero from "./components/Hero";
import Skills from "./components/Skills";
import Projects from "./components/Projects";
import Contact from "./components/Contact";
function App() {
return (
<div className="min-h-screen bg-surface font-sans text-ink antialiased dark:bg-slate-950 dark:text-slate-100">
<Navbar />
<main>
<Hero />
<Skills />
<Projects />
<Contact />
</main>
</div>
);
}
export default App;
Check
Next: add Footer and finish the page.