The 1 file this component needs and nothing else, each fenced with the path it belongs at, followed by what the library's own verification covered and what it did not. No instructions attached — for placing it yourself, or handing it to something that has its own.
Read it first
Install kit: "Map contact form"
Library page: https://astro.baysixmedia.com/components/map-contact-form/
Files: 1 required, 1 supporting
Write each block below to the path named in its header, relative to the project root. A block marked (required) is one the component does not work without; (supporting) is documentation. Nothing here needs downloading except a block that says so in as many words.
===== FILE (required): src/components/MapContactForm.astro =====
---
/**
* MapContactForm
*
* A contact section: a centred orange eyebrow between two short rules and a
* big navy heading, then two columns — an embedded map on the left and a
* light grey rounded form panel on the right (name, email, phone, freight
* type, load, message, and a full-width orange "Submit Request" pill).
*
* The map is a lazy <iframe> of `mapEmbedUrl`. Unset (the default), there is
* no map and the form stands alone, centred; `mapEmbedUrl: ""` renders a
* labelled placeholder instead and makes no third-party request. No heading
* or place is assumed. The form is native: `action` is unset by default,
* every control has a real (visually hidden) label.
*
* Appear on scroll: the title rises 40px; the map slides in from −40px and
* the form from +40px. Without JS or under reduced motion all at rest.
*
* Reads --tg-* design tokens from any ancestor, with fallbacks.
*/
export interface MapContactLabels {
name?: string;
email?: string;
phone?: string;
freightType?: string;
load?: string;
message?: string;
}
export interface MapContactFormProps {
eyebrow?: string;
heading?: string;
headingLevel?: "h2" | "h3";
/** A map embed URL. Unset: no map. `""` renders the labelled placeholder instead. */
mapEmbedUrl?: string;
/** The iframe's title — what the map shows. */
mapTitle?: string;
/** Where the form posts. Unset: the browser submits to the current URL. */
action?: string;
method?: "get" | "post";
formName?: string;
submitLabel?: string;
/** Freight type options. `[]` drops the select. */
freightTypes?: string[];
/** Load options. `[]` drops the select. */
loads?: string[];
/** Accessible labels (visually hidden). */
labels?: MapContactLabels;
/** Placeholders — hints only, never the label. */
placeholders?: MapContactLabels;
background?: string;
fontStylesheet?: string;
class?: string;
/** Root id. Also seeds every field id. */
id?: string;
}
interface Props extends MapContactFormProps {}
const {
eyebrow = "Get In Touch",
heading = "",
headingLevel = "h2",
mapEmbedUrl,
mapTitle = "",
action,
method = "post",
formName,
submitLabel = "Submit Request",
freightTypes = ["Air Freight", "Sea Freight", "Road Freight", "Rail Freight"],
loads = ["Under 1 ton", "1 ton", "2 tons", "5 tons", "Full truckload"],
labels = {},
placeholders = {},
background = "#ffffff",
fontStylesheet = "https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700&family=DM+Sans:wght@400;500;600&display=swap",
class: className,
id,
} = Astro.props;
const Heading = headingLevel;
const uid = (id ?? `mcf-${Math.random().toString(36).slice(2, 9)}`).replace(/[^A-Za-z0-9_-]/g, "") || "mcf";
const fid = (name: string) => `${uid}-${name}`;
/* Only an http(s) page may be framed. */
const mapSrc = mapEmbedUrl && /^https:\/\//i.test(mapEmbedUrl.trim()) ? mapEmbedUrl.trim() : "";
/* No map at all unless one (or the placeholder, with "") is asked for. */
const showMap = mapEmbedUrl !== undefined;
const mapLabel = mapTitle || "Map";
const L: Required<MapContactLabels> = {
name: "Your name",
email: "Your email",
phone: "Phone number",
freightType: "Freight type",
load: "Load",
message: "Message",
...labels,
};
const P: Required<MapContactLabels> = {
name: "Your Name",
email: "Your Email",
phone: "Phone No:",
freightType: "Freight Type",
load: "Load",
message: "Message",
...placeholders,
};
---
{fontStylesheet && <link rel="stylesheet" href={fontStylesheet} />}
<section class:list={["mcf", className]} id={id} data-mcf-root style={`--mcf-band: ${background};`}>
<div class="mcf-inner">
{(eyebrow || heading) && (
<div class="mcf-title" data-mcf-appear>
{
eyebrow && (
<p class="mcf-eyebrow">
<span class="mcf-rule" aria-hidden="true" />
<span>{eyebrow}</span>
<span class="mcf-rule" aria-hidden="true" />
</p>
)
}
{heading && <Heading class="mcf-heading">{heading}</Heading>}
</div>
)}
<div class="mcf-body" style={showMap ? undefined : "grid-template-columns: minmax(0, 630px); justify-content: center;"}>
{showMap && (
<div class="mcf-map" data-mcf-appear="left">
{
mapSrc ? (
<iframe
src={mapSrc}
title={mapLabel}
loading="lazy"
referrerpolicy="no-referrer-when-downgrade"
allowfullscreen
/>
) : (
<div class="mcf-ph" role="img" aria-label={`Map placeholder: ${mapLabel}`}>
<div class="mcf-ph-text" aria-hidden="true">
<svg viewBox="0 0 24 24" width="28" height="28"><path fill="currentColor" d="M12 2a7 7 0 0 0-7 7c0 5 6.1 11.4 6.4 11.7a.8.8 0 0 0 1.2 0C12.9 20.4 19 14 19 9a7 7 0 0 0-7-7Zm0 9.6A2.6 2.6 0 1 1 12 6.4a2.6 2.6 0 0 1 0 5.2Z" /></svg>
<span class="mcf-ph-label">Map</span>
<span class="mcf-ph-hint">{mapLabel}</span>
<span class="mcf-ph-spec">Pass mapEmbedUrl to embed a map</span>
</div>
</div>
)
}
</div>
)}
<form class="mcf-form" action={action} method={method} name={formName} data-mcf-appear="right">
<div class="mcf-field">
<label class="mcf-sr" for={fid("name")}>{L.name}</label>
<input class="mcf-input" type="text" id={fid("name")} name="name" autocomplete="name" placeholder={P.name} required />
<svg class="mcf-icon" viewBox="0 0 12 12" aria-hidden="true"><path fill="currentColor" d="M6 6a2.6 2.6 0 1 0 0-5.2A2.6 2.6 0 0 0 6 6Zm0 1.1c-2.4 0-4.6 1.2-4.6 2.9v1.2h9.2V10c0-1.7-2.2-2.9-4.6-2.9Z" /></svg>
</div>
<div class="mcf-pair">
<div class="mcf-field">
<label class="mcf-sr" for={fid("email")}>{L.email}</label>
<input class="mcf-input" type="email" id={fid("email")} name="email" autocomplete="email" placeholder={P.email} required />
<svg class="mcf-icon" viewBox="0 0 12 12" aria-hidden="true"><path fill="currentColor" d="M1 2.5h10a.5.5 0 0 1 .5.5v.4L6 6.6.5 3.4V3a.5.5 0 0 1 .5-.5Zm-.5 2.1L6 7.8l5.5-3.2V9a.5.5 0 0 1-.5.5H1a.5.5 0 0 1-.5-.5Z" /></svg>
</div>
<div class="mcf-field">
<label class="mcf-sr" for={fid("phone")}>{L.phone}</label>
<input class="mcf-input" type="tel" id={fid("phone")} name="phone" autocomplete="tel" placeholder={P.phone} />
<svg class="mcf-icon" viewBox="0 0 12 12" aria-hidden="true"><path fill="currentColor" d="M3.3 5.3a8 8 0 0 0 3.4 3.4l1.1-1.1a.5.5 0 0 1 .5-.13 5.7 5.7 0 0 0 1.8.29.5.5 0 0 1 .5.5V10a.5.5 0 0 1-.5.5A8.5 8.5 0 0 1 1.5 2a.5.5 0 0 1 .5-.5h1.75a.5.5 0 0 1 .5.5c0 .63.1 1.23.29 1.8a.5.5 0 0 1-.13.5Z" /></svg>
</div>
</div>
{(freightTypes.length > 0 || loads.length > 0) && (
<div class="mcf-pair">
{freightTypes.length > 0 && (
<div class="mcf-field">
<label class="mcf-sr" for={fid("freight")}>{L.freightType}</label>
<select class="mcf-input mcf-select" id={fid("freight")} name="freightType">
<option value="" selected>{P.freightType}</option>
{freightTypes.map((o) => <option value={o}>{o}</option>)}
</select>
<svg class="mcf-chevron" viewBox="0 0 16 16" aria-hidden="true"><path d="m3 6 5 5 5-5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" /></svg>
</div>
)}
{loads.length > 0 && (
<div class="mcf-field">
<label class="mcf-sr" for={fid("load")}>{L.load}</label>
<select class="mcf-input mcf-select" id={fid("load")} name="load">
<option value="" selected>{P.load}</option>
{loads.map((o) => <option value={o}>{o}</option>)}
</select>
<svg class="mcf-chevron" viewBox="0 0 16 16" aria-hidden="true"><path d="m3 6 5 5 5-5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" /></svg>
</div>
)}
</div>
)}
<div class="mcf-field">
<label class="mcf-sr" for={fid("message")}>{L.message}</label>
<textarea class="mcf-input mcf-textarea" id={fid("message")} name="message" rows="5" placeholder={P.message} required></textarea>
</div>
<button class="mcf-btn" type="submit">{submitLabel}</button>
</form>
</div>
</div>
</section>
<style>
.mcf {
--mcf-navy: var(--tg-navy, #020e28);
--mcf-orange: var(--tg-orange, #fd5523);
--mcf-muted: var(--tg-muted, #61697d);
--mcf-display: var(--tg-font-display, Outfit, "Outfit Placeholder", ui-sans-serif, system-ui, sans-serif);
--mcf-body: var(--tg-font-body, "DM Sans", "DM Sans Placeholder", ui-sans-serif, system-ui, sans-serif);
--mcf-ease: cubic-bezier(0.22, 1, 0.36, 1);
box-sizing: border-box;
padding: 0 0 60px;
background: var(--mcf-band);
color: var(--mcf-navy);
font-family: var(--mcf-body);
/* The form's entrance starts 40px to the right; until it plays, that
offset must not push the page sideways on a narrow screen. `clip`, not
`hidden`: no scroll container, so nothing about focus or sticky changes. */
overflow-x: clip;
}
.mcf *,
.mcf *::before,
.mcf *::after {
box-sizing: border-box;
}
.mcf-inner {
display: flex;
flex-direction: column;
gap: 40px;
max-width: 1293px;
margin: 0 auto;
padding: 0 20px;
/* Contains the ±40px appear slides at every width. */
overflow: clip;
overflow-clip-margin: 8px;
}
.mcf-title {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
text-align: center;
}
.mcf .mcf-eyebrow {
display: inline-flex;
align-items: center;
gap: 12px;
margin: 0;
font: 600 16px/1 var(--mcf-display);
text-transform: uppercase;
color: var(--mcf-orange);
}
.mcf-rule {
display: block;
width: 40px;
height: 1px;
background: currentColor;
}
.mcf-heading {
margin: 0;
max-width: 680px;
font: 600 32px/1.2 var(--mcf-display);
color: var(--mcf-navy);
overflow-wrap: anywhere;
}
.mcf-body {
display: flex;
flex-direction: column;
gap: 10px;
}
/* On a phone the form comes first, as the reference does; the map's one
tab stop (the iframe) then follows the form in visual order too. */
.mcf-map {
order: 1;
position: relative;
height: 320px;
border-radius: 20px;
overflow: hidden;
background: #e9ecef;
}
.mcf-map iframe {
position: absolute;
inset: 0;
display: block;
width: 100%;
height: 100%;
border: 0;
}
.mcf-map:has(iframe:focus-visible) {
outline: 3px solid var(--mcf-orange);
outline-offset: 3px;
}
.mcf-ph {
position: absolute;
inset: 0;
display: grid;
place-items: center;
padding: 16px;
text-align: center;
background: repeating-linear-gradient(135deg, #e6e9ee 0 12px, #edf0f3 12px 24px);
color: rgb(2 14 40 / 0.62);
}
.mcf-ph-text {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
.mcf-ph-text svg {
color: var(--mcf-orange);
}
.mcf-ph-label {
font: 500 12px/1 var(--mcf-body);
letter-spacing: 0.08em;
text-transform: uppercase;
}
.mcf-ph-hint {
max-width: 28ch;
font: 500 14px/1.4 var(--mcf-body);
}
.mcf-ph-spec {
font: 400 12px/1.2 var(--mcf-body);
}
.mcf-form {
display: flex;
flex-direction: column;
gap: 12px;
min-width: 0;
margin: 0;
padding: 16px;
border-radius: 20px;
background: #f4f4f4;
}
.mcf-pair {
display: grid;
gap: 12px;
}
.mcf-field {
position: relative;
min-width: 0;
}
.mcf-input {
display: block;
width: 100%;
min-height: 44px;
margin: 0;
padding: 11px 44px 11px 18px;
border: 0;
border-radius: 100px;
background: #fff;
color: var(--mcf-navy);
font: 400 16px/20px var(--mcf-body);
}
.mcf-input::placeholder {
color: var(--mcf-muted);
opacity: 1;
}
/* An outline, not a shadow: it survives forced colours. */
.mcf-input:focus {
outline: 2px solid var(--mcf-orange);
outline-offset: 2px;
}
.mcf-select {
appearance: none;
-webkit-appearance: none;
cursor: pointer;
}
.mcf-select:has(option[value=""]:checked) {
color: var(--mcf-muted);
}
.mcf-select option {
color: var(--mcf-navy);
}
.mcf-textarea {
min-height: 100px;
padding: 14px 18px;
border-radius: 20px;
resize: vertical;
}
.mcf-icon,
.mcf-chevron {
position: absolute;
top: 50%;
right: 20px;
width: 12px;
height: 12px;
transform: translateY(-50%);
color: var(--mcf-orange);
pointer-events: none;
}
.mcf-chevron {
width: 18px;
height: 18px;
right: 18px;
}
.mcf-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 100%;
min-height: 48px;
padding: 16px 20px;
border: 0;
border-radius: 100px;
background: var(--mcf-orange);
color: #fff;
font: 600 14px/1 var(--mcf-body);
cursor: pointer;
transition: background-color 0.35s ease-out;
}
.mcf-btn:hover {
background: var(--mcf-navy);
}
.mcf-btn:focus-visible {
outline: 2px solid var(--mcf-navy);
outline-offset: 3px;
}
.mcf-sr {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0 0 0 0);
white-space: nowrap;
border: 0;
}
/* ---- appear ---- */
[data-mcf-appear] {
transition:
opacity 0.8s var(--mcf-ease),
transform 0.8s var(--mcf-ease);
}
.mcf[data-mcf-anim] [data-mcf-appear]:not([data-in]) {
opacity: 0;
transform: translateY(40px);
}
.mcf[data-mcf-anim] [data-mcf-appear="left"]:not([data-in]) {
transform: translateX(-40px);
}
.mcf[data-mcf-anim] [data-mcf-appear="right"]:not([data-in]) {
transform: translateX(40px);
}
/* ---- tablet ---- */
@media (min-width: 810px) {
.mcf {
padding-bottom: 90px;
}
.mcf-inner {
gap: 50px;
}
.mcf-heading {
font-size: 40px;
}
.mcf-form {
gap: 25px;
padding: 40px;
}
.mcf-pair {
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 30px;
}
/* One select left (the other's options were emptied): full width. */
.mcf-pair:has(> .mcf-field:only-child) {
grid-template-columns: minmax(0, 1fr);
}
.mcf-input {
min-height: 56px;
padding: 17px 48px 17px 24px;
}
.mcf-textarea {
min-height: 175px;
padding: 16px 24px;
}
.mcf-icon {
right: 24px;
}
.mcf-chevron {
right: 22px;
}
.mcf-btn {
min-height: 56px;
padding: 21px 20px;
}
.mcf-map {
height: 400px;
}
}
/* ---- desktop: map left, form right ---- */
@media (min-width: 1200px) {
.mcf {
padding-bottom: 120px;
}
.mcf-inner {
gap: 60px;
}
.mcf .mcf-eyebrow {
font-size: 18px;
}
.mcf-heading {
font-size: 48px;
line-height: 57.6px;
}
.mcf-body {
display: grid;
grid-template-columns: minmax(0, 589fr) minmax(0, 630fr);
padding: 0 12px;
}
.mcf-map {
order: 0;
height: auto;
min-height: 579px;
}
}
@media (prefers-reduced-motion: reduce) {
[data-mcf-appear] {
transition: none;
}
}
@media (forced-colors: active) {
.mcf-input,
.mcf-btn {
border: 1px solid ButtonText;
}
.mcf-form,
.mcf-map {
border: 1px solid CanvasText;
}
.mcf-icon,
.mcf-chevron,
.mcf-rule {
color: CanvasText;
}
.mcf-rule {
background: CanvasText;
}
}
</style>
<script>
/*
* Appear on scroll only. The form is native and the map is an iframe;
* neither needs script. One IntersectionObserver per instance; each
* watched element gets `data-in` once. Released on astro:before-swap.
*/
function initMapContactForm(root: HTMLElement) {
if (root.dataset.mcfReady !== undefined) return;
root.dataset.mcfReady = "";
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
if (!("IntersectionObserver" in window)) return;
const controller = new AbortController();
const { signal } = controller;
root.dataset.mcfAnim = "";
const observer = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
if (!entry.isIntersecting) continue;
(entry.target as HTMLElement).dataset.in = "";
observer.unobserve(entry.target);
}
},
{ threshold: 0.1 },
);
root.querySelectorAll<HTMLElement>("[data-mcf-appear]").forEach((el) => observer.observe(el));
signal.addEventListener("abort", () => observer.disconnect());
document.addEventListener(
"astro:before-swap",
() => {
controller.abort();
delete root.dataset.mcfReady;
delete root.dataset.mcfAnim;
},
{ once: true, signal },
);
}
const boot = () =>
document.querySelectorAll<HTMLElement>("[data-mcf-root]").forEach(initMapContactForm);
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", boot, { once: true });
} else {
boot();
}
document.addEventListener("astro:page-load", boot);
</script>
===== END src/components/MapContactForm.astro =====
===== FILE (supporting): src/components/MapContactForm.md =====
# Map contact form
A contact section: a centred **GET IN TOUCH** eyebrow between two short rules
and a big heading, then an embedded map on the left and a light grey rounded
form panel on the right — name, email, phone, freight type, load, message and
a full-width orange **Submit Request** pill.
Catalog page: `/components/map-contact-form`
## Purpose
The main block of a contact page, after the info cards. Part of the Northpass
(Transigo-style) family; reads the `--tg-*` tokens.
## Files required
**`MapContactForm.astro`** — the whole component. No imports, no images.
`MapContactForm.md` — this file.
## Basic usage
```astro
<MapContactForm
mapEmbedUrl="https://www.google.com/maps?q=2250%20Harbor%20Way%2C%20Oakland&output=embed"
mapTitle="Map of our Oakland depot"
action="/api/contact"
/>
```
## The map
The map is a lazy `<iframe>` of `mapEmbedUrl`. **There is no default map**:
a place is a fact about a real business, so with `mapEmbedUrl` unset there is
no map column and the form stands alone, centred (630px wide from 1200px).
The catalog demo passes an Oakland, CA embed as a prop. A framed map is a
**third-party request**: your CSP needs `frame-src https://www.google.com`,
and Google sets its own cookies inside the frame. Only `https:` URLs are
framed.
`mapEmbedUrl=""` renders a labelled striped placeholder instead and makes no
request. Use it in previews, or where a consent banner must come first.
With no props at all it renders the generic "Get In Touch" eyebrow and the
form — no heading, no map, no place name.
## It has no back end
**`action` is unset by default**, so the browser submits to the current URL.
Field names: `name`, `email`, `phone`, `freightType`, `load`, `message`.
Required: name, email, message.
## Props
| Prop | Type | Default | What it does |
| :--- | :--- | :--- | :--- |
| `eyebrow` | `string?` | `"Get In Touch"` | Between two 40px rules. `""` drops it. |
| `heading` | `string?` | none | Unset: no heading. |
| `headingLevel` | `"h2" \| "h3"?` | `"h2"` | |
| `mapEmbedUrl` | `string?` | none | Unset: no map, form centred. `""` → placeholder. |
| `mapTitle` | `string?` | `""` | The iframe's `title` (and the placeholder's label); falls back to `"Map"`. |
| `action` | `string?` | — | See above. |
| `method` | `"get" \| "post"?` | `"post"` | |
| `formName` | `string?` | — | |
| `submitLabel` | `string?` | `"Submit Request"` | |
| `freightTypes` | `string[]?` | Air, Sea, Road, Rail | `[]` drops the select. |
| `loads` | `string[]?` | five weights | `[]` drops the select; the other one then fills the row. |
| `labels` | `MapContactLabels?` | English | Visually hidden labels. |
| `placeholders` | `MapContactLabels?` | as the design | Hints only. |
| `background` | `string?` | `#ffffff` | |
| `fontStylesheet` | `string?` | Outfit + DM Sans | `""` skips the link. |
| `class` | `string?` | — | |
| `id` | `string?` | — | Root id; **also seeds every field id** (random when omitted). |
## Behaviour
| Element | Effect | Measured / chosen |
| :--- | :--- | :--- |
| Submit hover | background `#fd5523` → `#020e28` | as measured; 0.35s ease-out (no arrow on this button, as the reference) |
| Title appear | from `translateY(40px)` | as measured |
| Map appear | from `translateX(-40px)` | as measured |
| Form appear | from `translateX(+40px)` | as measured |
| Field focus | 2px orange outline | see Accessibility |
One IntersectionObserver per instance; hidden poses only while the root has
`data-mcf-anim`; released on `astro:before-swap`. The inner column is
`overflow: clip` (with an 8px clip margin for focus rings) so the ±40px
slides never cause horizontal scroll.
## Accessibility
- Every control has a real, visually hidden `<label for>`; placeholders are
hints only. Inputs are 16px.
- `autocomplete` on name, email and phone.
- The iframe has a `title`; when it has keyboard focus the map wrap shows an
orange ring.
- Focus is an outline, so it survives forced colours; under
`forced-colors: active` fields, panel and map get borders.
- On tablet and phone the form is shown before the map (as the reference);
the map's single tab stop then comes first in DOM order but second on
screen — a one-stop mismatch accepted to keep the desktop order natural.
## Reduced motion / without JavaScript
Everything at rest. The form and the iframe need no script.
## Responsive
| Width | Layout |
| :--- | :--- |
| ≥ 1200 | map 589 / 10 gap / form 630, inset 12px; map as tall as the form (579); form padding 40, gap 25, 56px pills, 175px textarea; heading 48/57.6 |
| 810–1199 | form above a 400px map; paired fields side by side |
| < 810 | form above a 320px map; every field full width, 44px min height, padding 16 |
No top padding at any width (measured: it follows the contact info cards);
bottom padding 120 / 90 / 60.
## Images and credits
None. The map comes from the embed URL you pass.
## Approximations
- **Map on phone.** The 390 capture shows the form and white space below it
(the iframe had not loaded); the map is placed below the form at 320px tall.
- **Select options.** The reference's Freight Type list repeats "Air Freight";
its Load list is "1 Ton / 2 Ton". Both are replaced with sensible lists.
- **Field focus** is an outline rather than the reference's shadow transition.
- Tablet layout is inferred.
===== END src/components/MapContactForm.md =====
--- VERIFIED IN THE COMPONENT LIBRARY ---
Enrolled for verification but never run.
No verification run has been recorded.
No checks have passed yet.
No usable source fingerprint, so these results cannot be tied to the files below.
--- NOT PROVEN ---
- ClientRouter: event-tested only. Handlers respond to dispatched lifecycle events; this has NOT been certified against a real <ClientRouter /> transition.
--- WHAT THIS DOES NOT CERTIFY ---
Verification was performed on the unmodified component, in an isolated fixture, in the
library. It says nothing about this project's CSS, routes, layout or data, and nothing
about the component once you adapt it. A verified component is a good starting point,
not a guarantee about the installation you are about to build.
--- TEST IN THIS PROJECT AFTER INSTALLING OR CUSTOMISING ---
- Horizontal overflow at 1440, 1280, 1024, 834, 390 and 320px.
- Keyboard operation end to end, including visible focus.
- The no-JavaScript render.
- prefers-reduced-motion: reduce.
- Two instances on one page, if this project renders more than one.
- If this project uses <ClientRouter />: teardown and reinitialisation across a real navigation.