Overview
The ContactCTA component is a standalone section that encourages visitors to reach out for collaboration opportunities. It combines a heading with a prominent call-to-action button and icon, styled to stand out on the page. This component is typically placed at the bottom of pages as a conversion element.
Props
This component does not accept any props. The content and mailto link are hardcoded within the component.
Usage
Basic Implementation
import ContactCTA from '../components/ContactCTA.astro';
<ContactCTA />
At End of Page
import BaseLayout from '../layouts/BaseLayout.astro';
import ContactCTA from '../components/ContactCTA.astro';
<BaseLayout title="About" description="About me">
<main>
<section>
<!-- Main content -->
</section>
</main>
<ContactCTA />
</BaseLayout>
Between Content Sections
<div class="stack gap-20">
<section class="portfolio">
<!-- Portfolio items -->
</section>
<ContactCTA />
<section class="testimonials">
<!-- Testimonials -->
</section>
</div>
Real-World Examples
Homepage (src/pages/index.astro):
<BaseLayout>
<div class="stack gap-20 lg:gap-48">
<!-- Hero section -->
<main class="wrapper stack gap-20 lg:gap-48">
<!-- Selected work -->
<!-- Mentions -->
</main>
<ContactCTA />
</div>
</BaseLayout>
Work Detail Pages (src/pages/work/[...slug].astro):
<BaseLayout title={entry.data.title} description={entry.data.description}>
<div class="stack gap-20">
<div class="stack gap-15">
<header>
<Hero title={entry.data.title} align="start" slug={entry.slug}>
<!-- Project details -->
</Hero>
</header>
<main class="wrapper">
<Content />
</main>
</div>
<ContactCTA />
</div>
</BaseLayout>
About Page (src/pages/about.astro):
<BaseLayout title="About" description="About Juan Roccia">
<div class="stack gap-20">
<main class="wrapper about">
<!-- About content -->
<!-- Skills section -->
</main>
<ContactCTA />
</div>
</BaseLayout>
Component Structure
The component consists of:
<aside>
<h2>Interested in working together?</h2>
<CallToAction href="mailto:juanroccia@gmail.com">
Send Me a Message
<Icon icon="paper-plane-tilt" size="1.2em" />
</CallToAction>
</aside>
Elements
- Aside element: Semantic container for tangential content
- H2 heading: Engaging question to prompt action
- CallToAction: Styled button with gradient and hover effects
- Icon: Visual indicator (paper plane) for sending message
Styling Features
Layout
Mobile (< 50em):
- Vertical flexbox layout
- Centered alignment
- 3rem gap between heading and button
- 5rem vertical padding
- 1.5rem horizontal padding
Desktop (≥ 50em):
- Horizontal flexbox layout
- Space-between justification
- Wraps if needed
- 7.5rem padding all around
- Left-aligned heading text
Visual Design
- Background: Semi-transparent gray (
--gray-999_40)
- Borders: Top and bottom 1px solid borders (
--gray-800)
- Shadow: Subtle box shadow (
--shadow-sm)
- Typography:
- Mobile:
var(--text-xl) heading
- Desktop:
var(--text-3xl) heading
- Max width of 15ch on mobile for readability
Customization
Change Email Address
Modify the mailto link:
<CallToAction href="mailto:your-email@example.com">
Send Me a Message
<Icon icon="paper-plane-tilt" size="1.2em" />
</CallToAction>
Change Heading Text
<h2>Let's collaborate on your next project!</h2>
Change Button Text
<CallToAction href="mailto:juanroccia@gmail.com">
Get In Touch
<Icon icon="envelope" size="1.2em" />
</CallToAction>
Instead of mailto, link to a contact page:
<CallToAction href="/contact">
Contact Me
<Icon icon="arrow-right" size="1.2em" />
</CallToAction>
Add Multiple CTAs
<aside>
<h2>Interested in working together?</h2>
<div class="cta-group">
<CallToAction href="mailto:juanroccia@gmail.com">
Send Email
<Icon icon="paper-plane-tilt" size="1.2em" />
</CallToAction>
<CallToAction href="/contact">
Contact Form
<Icon icon="pencil" size="1.2em" />
</CallToAction>
</div>
</aside>
Make It Dynamic
Accept props for customization:
---
import CallToAction from './CallToAction.astro';
import Icon from './Icon.astro';
interface Props {
heading?: string;
buttonText?: string;
href?: string;
icon?: string;
}
const {
heading = "Interested in working together?",
buttonText = "Send Me a Message",
href = "mailto:juanroccia@gmail.com",
icon = "paper-plane-tilt"
} = Astro.props;
---
<aside>
<h2>{heading}</h2>
<CallToAction href={href}>
{buttonText}
<Icon icon={icon} size="1.2em" />
</CallToAction>
</aside>
Then use it:
<ContactCTA
heading="Ready to start your project?"
buttonText="Let's Talk"
href="/contact"
icon="chat"
/>
Best Practices
Place ContactCTA at the end of content-heavy pages to capture interested visitors at the moment they finish reading.
The mailto link opens the user’s email client. Consider also providing an alternative like a contact form for users who prefer web forms.
The component uses <aside> which is semantically for tangential content. If this is the primary call-to-action, consider using <section> instead.
Accessibility
- Semantic
<aside> element for proper document structure
- Clear, actionable heading as
<h2>
- CallToAction component provides full keyboard accessibility
- Icon is decorative and doesn’t interfere with screen readers
- Sufficient color contrast for text readability
Integration
The component depends on:
import CallToAction from './CallToAction.astro';
import Icon from './Icon.astro';
Ensure both components are available in your project.
Conversion Optimization
This component is designed for conversion. Consider:
- Placement: Most effective at natural break points or page endings
- Timing: After the user has consumed enough content to be interested
- Copy: Action-oriented, benefit-focused language
- Visual hierarchy: Prominent but not overwhelming
- Single CTA: One clear action reduces decision paralysis
Analytics Tracking
Add tracking to measure effectiveness:
<CallToAction
href="mailto:juanroccia@gmail.com"
data-analytics="contact-cta-click"
>
Send Me a Message
<Icon icon="paper-plane-tilt" size="1.2em" />
</CallToAction>
Then track with your analytics tool of choice.