Files
homepage_relaunch/src/components/home/Contact.astro
T
2026-10-05 21:04:51 +02:00

126 lines
4.5 KiB
Plaintext

---
import Toast from '../Toast.astro';
import { t, type Lang } from '../../i18n/ui';
interface Props { lang: Lang }
const { lang } = Astro.props;
const ui = t(lang);
const f = ui.contact.form;
---
<section class="section contact" id="contact" aria-labelledby="contact-title">
<div class="container grid">
<div class="contact__text">
<h2 id="contact-title" class="h2">{ui.contact.title}</h2>
<p class="contact__body">{ui.contact.body}</p>
<address class="contact__address">
<p>{ui.contact.address[0]}<br />{ui.contact.address[1]}</p>
<p><a href={ui.contact.phoneHref}>{ui.contact.phone}</a><br /><a href={`mailto:${ui.contact.email}`}>{ui.contact.email}</a></p>
</address>
</div>
<form
class="contact__form"
id="contact-form"
action="/contact"
method="post"
lang={lang}
data-contact
data-sent={f.sent}
data-invalid={f.invalid}
data-failed={f.failed}
>
<input type="hidden" name="lang" value={lang} />
<p class="visually-hidden" aria-hidden="true">
<label for="website">{f.honeypot}</label>
<input type="text" id="website" name="website" tabindex="-1" autocomplete="off" />
</p>
<div class="field">
<label for="first_name">{f.firstName} <span aria-hidden="true">*</span></label>
<input id="first_name" name="first_name" type="text" autocomplete="given-name" required />
</div>
<div class="field">
<label for="last_name">{f.lastName} <span aria-hidden="true">*</span></label>
<input id="last_name" name="last_name" type="text" autocomplete="family-name" required />
</div>
<div class="field field--full">
<label for="email">{f.email} <span aria-hidden="true">*</span></label>
<input id="email" name="email" type="email" autocomplete="email" required />
</div>
<div class="field field--full">
<label for="message">{f.message} <span aria-hidden="true">*</span></label>
<textarea id="message" name="message" rows="5" required></textarea>
</div>
<div class="field--full contact__actions">
<button class="button" type="submit">{f.submit}</button>
<p class="small muted"><span aria-hidden="true">* </span>{f.required}</p>
</div>
<noscript><p class="field--full small">{f.noscript}</p></noscript>
</form>
</div>
<Toast for="contact-form" labels={{ ...f.toast }} />
</section>
<style>
.contact { border-top: var(--hairline) solid var(--line); }
.contact__text {
grid-column: 1 / -1;
display: grid;
gap: var(--space-6);
align-content: start;
}
.contact__body { max-width: 28em; color: var(--ink-muted); }
.contact__address { font-style: normal; display: grid; gap: var(--space-4); }
.contact__address a { text-decoration: none; }
.contact__address a:hover { text-decoration: underline; }
.contact__form {
grid-column: 1 / -1;
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: var(--space-6) var(--gap);
align-content: start;
}
.field { display: grid; gap: var(--space-2); }
.field--full { grid-column: 1 / -1; }
.field label { font-size: var(--step-small); line-height: var(--leading-small); color: var(--ink-muted); }
.field input, .field textarea {
width: 100%;
background: transparent;
border: 0;
border-bottom: var(--hairline) solid var(--line);
padding: var(--space-2) 0 var(--space-3);
border-radius: 0;
transition: border-color var(--dur-fast) var(--ease);
}
.field input:focus-visible, .field textarea:focus-visible {
border-bottom-color: currentColor;
}
.field textarea { resize: vertical; min-height: 8rem; }
.contact__actions {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--space-5);
margin-top: var(--space-2);
}
.contact__form[aria-busy='true'] .button { opacity: 0.6; cursor: progress; }
@media (min-width: 48rem) {
.contact__text { grid-column: 1 / span 5; }
.contact__form { grid-column: 7 / span 6; }
}
@media (max-width: 30rem) {
.contact__form { grid-template-columns: 1fr; }
.field { grid-column: 1 / -1; }
}
</style>
<script>
// Sends in place and answers in the toast; see scripts/send-form.ts. Without scripting the
// server refuses the post and redirects to /contact/error, which points to the email address.
import { sendInPlace } from '../../scripts/send-form';
const form = document.querySelector<HTMLFormElement>('[data-contact]');
if (form) sendInPlace(form);
</script>