File: src/blocks/hero/Hero20.astro
Inset rounded hero with an image background + configurable overlay (no slider). Same width gutter behavior as Hero19 — width="full" never goes edge-to-edge.
Config (blocks.ts → hero20)
hero20: {
width: "full",
contentWidth: "wide",
eyebrow: "Featured work",
heading: "Spaces that feel considered from the first scroll",
subheading:
"Full-bleed storytelling for hospitality, retail, and brand launches — image first, copy where it lands hardest.",
primaryCta: "View my work",
primaryCtaUrl: "/work/",
secondaryCta: "Get in touch",
secondaryCtaUrl: "/contact/",
image: photos.interior,
imageAlt: "Interior detail",
overlayColor: "#000000",
overlayOpacity: 0.45,
contentTone: "light",
height: "md",
textPlacement: "center",
textAlign: "left",
radius: "2xl",
borderBottom: false,
borderThickness: "sm",
borderColor: "soft",
},
Add to a page
---
import Hero20 from "@/blocks/hero/Hero20.astro";
---
<Hero20 />
Props override matching keys from config:
<Hero20
width="wide"
height="lg"
overlayOpacity={0.55}
textPlacement="bottom"
textAlign="center"
radius="xl"
/>
Props
| Prop | Config key | Type / values | Default / notes |
|---|---|---|---|
width |
hero20.width |
narrow | standard | wide | full |
Frame max-width; full still keeps viewport gutter |
contentWidth |
hero20.contentWidth |
standard | narrow | wide |
Inner copy wrapper max-width |
eyebrow |
hero20.eyebrow |
string |
— |
heading |
hero20.heading |
string |
— |
subheading |
hero20.subheading |
string |
— |
primaryCta |
hero20.primaryCta |
string |
— |
primaryCtaUrl |
hero20.primaryCtaUrl |
string |
— |
secondaryCta |
hero20.secondaryCta |
string |
— |
secondaryCtaUrl |
hero20.secondaryCtaUrl |
string |
— |
image |
hero20.image |
LocalImageSource |
Prefer photos.* from src/assets/images |
imageAlt |
hero20.imageAlt |
string |
— |
overlayColor |
hero20.overlayColor |
CSS color string | e.g. #000, var(--color-strong) |
contentTone |
hero20.contentTone |
light | dark |
light = light text / CTAs on dark overlay |
overlayOpacity |
hero20.overlayOpacity |
number (0–1) |
Overlay opacity |
height |
hero20.height |
auto | sm | md | lg | full |
Viewport min-height of the frame |
textPlacement |
hero20.textPlacement |
top | center | bottom |
Vertical placement of copy |
textAlign |
hero20.textAlign |
left | center | right |
Horizontal justification of copy + CTAs |
radius |
hero20.radius |
none | md | lg | xl | 2xl |
Frame border radius |
borderBottom |
hero20.borderBottom |
boolean |
Show a bottom border under the section |
borderThickness |
hero20.borderThickness |
sm (1px) | md (2px) | lg (4px) |
— |
borderColor |
hero20.borderColor |
soft | medium | hard |
— |
Notes: Use contentTone for light vs dark copy on the overlay. Prefer photos.* — Images. Pass real CSS colors for overlayColor (not Tailwind class names).
