ContactsSection

apps/www/src/components/ContactsSection.astro · 173 lines · group Contact

Used by

Live sites: skattedosan.se.

Samples 2

skattedosan.se/en/contacts/

Contact us

Phone number
+46 73 302 92 51
Email
ask@codeexpert.se
MDX of this sample
<ContactsSection
  title="Contact us"
  alertTitle="Thank you!"
  alertText="We`ve received your message. Someone from our team will contact you soon."
/>
skattedosan.se/contacts/history: commit 1396f74 (2026-08-18)

Contact us

Phone number
+46 73 302 92 51
Email
ask@codeexpert.se
MDX of this sample
<ContactsSection
  title="Contact us"
  alertTitle="Thank you!"
  alertText="We`ve received your message. Someone from our team will contact you soon."
/>

Props

NameTypeRequiredDefaultDescription
titlestringyes
emailstringyes
phonestring
firstNameLabelstring'First name'
emailLabelstring'Email'
phoneLabelstring'Phone number'
messageLabelstring'Message'
submitButtonstring'Submit'
subjectMailstring'Request from Contacts'
alertTitlestring'Thank you!'
alertTextstring'We`ve received your message. Someone from our team will contact you soon'

Source apps/www/src/components/ContactsSection.astro @ gitt.one

---
import Envelope from 'astro-heroicons/solid/Envelope.astro';
import Phone from 'astro-heroicons/solid/Phone.astro';
import pagesConfig from '../../pages.config.js';

interface Props {
  title: string;
  email: string;
  phone?: string;
  firstNameLabel?: string;
  emailLabel?: string;
  phoneLabel?: string;
  messageLabel?: string;
  submitButton?: string;
  subjectMail?: string;
  alertTitle?: string;
  alertText?: string;
}

const {
  title,
  email,
  phone,
  firstNameLabel = 'First name',
  emailLabel = 'Email',
  phoneLabel = 'Phone number',
  messageLabel = 'Message',
  submitButton = 'Submit',
  subjectMail = 'Request from Contacts',
  alertTitle = 'Thank you!',
  alertText = 'We`ve received your message. Someone from our team will contact you soon',
} = Astro.props;

const contactPhone = phone || pagesConfig.defaultPhone;
const contactEmail = email || pagesConfig.defaultEmail;
const turnstileSiteKey = pagesConfig.turnstileSiteKey;

const CAPTCHA_MESSAGE =
  'The captcha check has not finished yet. Please wait a moment and try again.';

const inputClass =
  'w-full rounded-md border border-gray-200 px-5 py-3 shadow-md focus:outline-none focus:ring-2 focus:ring-primary-500';
---

<section class="bg-white">
  <div class="relative my-16 bg-white sm:my-20">
    <div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
      <div
        data-form-success
        class="mb-6 hidden rounded-md bg-green-50 p-4"
        role="status"
      >
        <h3 class="text-sm font-medium text-green-800">{alertTitle}</h3>
        <div class="mt-2 text-sm text-green-700">
          <p>{alertText}</p>
        </div>
      </div>

      <div class="relative bg-white shadow-xl">
        <div class="grid grid-cols-1 lg:grid-cols-3">
          <div
            class="relative overflow-hidden bg-gradient-to-b from-primary-500 to-primary-alt-600 px-6 py-10 sm:px-10 xl:p-12"
          >
            {Boolean(title) && <h3 class="text-lg font-medium text-white">{title}</h3>}
            <dl class="mt-8 space-y-6">
              <dt><span class="sr-only">{phoneLabel}</span></dt>
              <dd class="flex text-base text-white">
                <Phone class="h-6 w-6 flex-shrink-0 text-white" aria-hidden="true" />
                <a class="ml-3" href={`tel:${contactPhone}`}>{contactPhone}</a>
              </dd>
              <dt><span class="sr-only">{emailLabel}</span></dt>
              <dd class="flex text-base text-white">
                <Envelope class="h-6 w-6 flex-shrink-0 text-white" aria-hidden="true" />
                <a class="ml-3" href={`mailto:${contactEmail}`}>{contactEmail}</a>
              </dd>
            </dl>
          </div>

          <div class="px-6 py-10 sm:px-10 lg:col-span-2 xl:p-12">
            <form
              data-contact-form
              data-api={pagesConfig.contactFormReceiverURL}
              data-site-host={new URL(pagesConfig.siteUrl).host}
              data-captcha-message={CAPTCHA_MESSAGE}
              method="POST"
              class="mt-6"
              novalidate={false}
            >
              <div
                data-form-fields
                class="grid grid-cols-1 gap-y-6 sm:grid-cols-2 sm:gap-x-8"
              >
                <div class="sm:col-span-2">
                  <label for="name" class="block text-sm font-medium text-gray-900">
                    {firstNameLabel} <span aria-hidden="true">*</span>
                  </label>
                  <input type="text" id="name" name="name" required class:list={['mt-1', inputClass]} />
                </div>

                <div class="col-span-1 sm:col-span-2 lg:col-span-1">
                  <label for="phone" class="block text-sm font-medium text-gray-900">
                    {phoneLabel} <span aria-hidden="true">*</span>
                  </label>
                  <input type="tel" id="phone" name="phone" required class:list={['mt-1', inputClass]} />
                </div>

                <div class="col-span-1 sm:col-span-2 lg:col-span-1">
                  <label for="email" class="block text-sm font-medium text-gray-900">
                    {emailLabel} <span aria-hidden="true">*</span>
                  </label>
                  <input type="email" id="email" name="email" required class:list={['mt-1', inputClass]} />
                </div>

                <div class="sm:col-span-2">
                  <label for="message" class="block text-sm font-medium text-gray-900">
                    {messageLabel} <span aria-hidden="true">*</span>
                  </label>
                  <textarea id="message" name="message" rows="4" required class:list={['mt-1', inputClass]}
                  ></textarea>
                </div>

                <!-- Honeypot: real users never see or fill this field. -->
                <input
                  type="text"
                  name="website"
                  tabindex="-1"
                  autocomplete="off"
                  aria-hidden="true"
                  class="hidden"
                />
                <input type="hidden" name="subject" value={subjectMail} />

                <div class="sm:col-span-2 sm:flex sm:items-center sm:justify-end sm:gap-x-4">
                  {
                    Boolean(turnstileSiteKey) && (
                      <div class="cf-turnstile" data-sitekey={turnstileSiteKey} />
                    )
                  }
                  <p data-form-preview-note class="hidden text-sm text-gray-500">
                    Preview environment — the contact form works only on the
                    production site.
                  </p>
                  <p data-form-error class="hidden text-sm text-red-500">
                    Something went wrong. Please try again later.
                  </p>
                  <button
                    type="submit"
                    class="inline-flex min-h-full items-center justify-center rounded-md bg-primary-500 px-4 py-3 font-medium text-white shadow hover:bg-primary-600 focus:outline-none focus:ring-1 focus:ring-primary-700 disabled:bg-gray-200"
                  >
                    {submitButton}
                  </button>
                </div>
              </div>
            </form>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>

{
  Boolean(turnstileSiteKey) && (
    <script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer is:inline />
  )
}

<script>
  import { initContactForms } from '../lib/contact-form';

  initContactForms();
</script>

Source links point to engine-astro@e857a859. Samples are cut from the sites' own content by scripts/gallery-extract.mjs; nothing is merged or removed yet.