Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/apursley2012/cosmic-developer/llms.txt

Use this file to discover all available pages before exploring further.

The Contact page (/contact) presents the portfolio’s inquiry form as an open comms channel — a two-column interface where the left side sets the scene and the right side holds a transmission form with three fields. Submitting the form triggers a two-second “Transmitting…” state with a vertical progress bar sweeping across the panel, which then resolves into a “Transmission Received” confirmation screen with a signal strength readout.

Layout Overview

The page uses a PageTransition wrapper with a two-column responsive layout:
flex-1 flex flex-col lg:flex-row gap-12 items-center justify-center
max-w-6xl mx-auto w-full min-h-[80vh]
ColumnWidthContent
Leftw-full lg:w-1/2Intro heading + flavour copy
Rightw-full lg:w-1/2Form or success panel (animated swap)
On mobile the columns stack vertically; on large screens they sit side-by-side.

Left Column — Channel Introduction

The left panel contains:
  • A pulsing Radio icon (animate-pulse) beside the TeletypeText prompt in aurora-teal
  • An H1: “Open Channel”"Channel" in text-aurora-teal
  • Intro copy:
“Whether you have a mission proposal, need a co-pilot for a new project, or just want to discuss the Fermi Paradox, transmit your message below.”

Right Column — Form States

The right column is wrapped in a Framer Motion AnimatePresence with mode="wait", allowing a smooth transition between the form state and the success state.

Form State (idle / sending)

A glass-panel p-8 space-y-6 card contains the three form fields and submit button:

Form Fields

FieldTypeLabelPlaceholder
nametextSender CallsignCommander Shepard
emailemailFrequency for Reply (Email)shepard@normandy.sr2
messagetextarea (rows: 4)Your TransmissionWe need your expertise in the Terminus Systems...
All three fields share the same base styling:
w-full bg-cosmic-black/50 border border-star-dim/30 rounded-lg px-4 py-3
text-star-white focus:outline-none focus:border-aurora-teal transition-colors
Labels use font-mono text-xs text-star-dim uppercase tracking-wider. Fields are disabled during the sending state (disabled:opacity-50).

Submit Button

w-full bg-aurora-teal text-cosmic-black font-heading font-bold py-3 rounded-lg
hover:bg-aurora-teal/90 transition-colors flex items-center justify-center gap-2
StateButton textIcon
idle"Initiate Sequence"Send (Lucide)
sending"Transmitting..."Send (Lucide)

Transmitting Progress Bar

When status === 'sending', a Framer Motion motion.div renders as a 1px-tall bar at the very top of the form panel:
<motion.div
  className="absolute top-0 left-0 w-full h-1 bg-aurora-teal shadow-[0_0_15px_#3dd6c4] z-10"
  animate={{ y: [0, 500] }}
  transition={{ duration: 1.5, repeat: Infinity, ease: 'linear' }}
/>
The bar sweeps vertically downward from the top of the panel in a looping 1.5s cycle, simulating a progress scanner rather than a horizontal fill bar.
The transmitting state lasts exactly 2 seconds, after which status transitions to 'sent' and the form is replaced with the success panel via AnimatePresence.

Success State (sent)

After the 2-second send delay, AnimatePresence fades out the form and replaces it with a confirmation panel:
<motion.div
  initial={{ opacity: 0, scale: 0.9 }}
  animate={{ opacity: 1, scale: 1 }}
  exit={{ opacity: 0 }}
  className="glass-panel p-12 text-center flex flex-col items-center justify-center min-h-[400px]"
>
The success panel contains:
ElementDetails
Icon containerw-16 h-16 rounded-full bg-aurora-teal/20 — holds the Send icon in text-aurora-teal
Heading"Transmission Received"text-2xl font-heading font-bold text-star-white
Subtext"Signal strength: 100%. Expect a reply within 1-2 Earth days."font-mono text-sm text-star-dim
The success state auto-resets to idle after 5 additional seconds, allowing the form to be reused.

Form State Machine

The contact form uses a three-state string variable managed with React.useState:
const [status, setStatus] = useState('idle')

const handleSubmit = (e) => {
  e.preventDefault()
  setStatus('sending')
  setTimeout(() => {
    setStatus('sent')
    setTimeout(() => setStatus('idle'), 5000)
  }, 2000)
}
StateWhat is shown
idleForm — all fields enabled, button reads “Initiate Sequence”
sendingForm — all fields disabled, button reads “Transmitting…”, scan bar active
sentSuccess panel with checkmark and signal strength message

Customization

Wiring up a real backend — replace the setTimeout blocks in handleSubmit with a fetch or axios call to your API endpoint:
const handleSubmit = async (e) => {
  e.preventDefault()
  setStatus('sending')
  try {
    await fetch('/api/contact', {
      method: 'POST',
      body: new FormData(e.target),
    })
    setStatus('sent')
  } catch {
    setStatus('idle') // handle error state
  }
}
Changing the scan bar to horizontal — swap the y animation axis for x and set w-1/3 h-full instead of w-full h-1 to make the progress indicator sweep left-to-right. Adding a fourth field — add a new <div> block with label + input inside the form, following the same pattern as the existing three fields. The space-y-6 container will automatically add spacing.
Because this is a client-side portfolio, no form submission actually occurs — the setTimeout simulates the round-trip. When deploying for real use, consider integrating Resend or Formspree for serverless email delivery without a dedicated backend.

Build docs developers (and LLMs) love