Hero
The Hero
component is what gets used on pages with the splash
template, like the index page.
---import { Image } from 'astro:assets';import CallToAction from './CallToAction.astro';import type { Props } from '@astrojs/starlight/props';
import { PAGE_TITLE_ID } from 'starlight-ion-theme/constants';
const { data } = Astro.locals.starlightRoute.entry;const { title = data.title, tagline, image, actions = [] } = data.hero || {};
const imageAttrs = { loading: 'eager' as const, decoding: 'async' as const, width: 400, height: 400, alt: image?.alt || '',};
let darkImage: ImageMetadata | undefined;let lightImage: ImageMetadata | undefined;let rawHtml: string | undefined;if (image) { if ('file' in image) { darkImage = image.file; } else if ('dark' in image) { darkImage = image.dark; lightImage = image.light; } else { rawHtml = image.html; }}
const titleHTML = title.split(" ").map((titlePart: string) => { return `<span>${titlePart}</span>`});---
<div class="hero"> <div class="sl-flex copy"> <h1 id={PAGE_TITLE_ID} data-page-title set:html={titleHTML} /> {tagline && <div class="tagline" set:html={tagline} />} {actions.length > 0 && ( <div class="sl-flex actions"> {actions.map(({ text, ...attrs }: any) => ( <CallToAction {...attrs} set:html={text} /> ))} </div> )} </div> {darkImage && ( <Image src={darkImage} {...imageAttrs} class:list={{ 'light:sl-hidden': Boolean(lightImage) }} /> )} {lightImage && <Image src={lightImage} {...imageAttrs} class="dark:sl-hidden" />} {rawHtml && <div class="hero-html sl-flex" set:html={rawHtml} />}</div>
<style> .hero { display: flex; flex-direction: row; align-items: center; gap: 1rem; border-bottom: 1px solid var(--sl-color-gray-6); padding: 1rem; }
.hero > img, .hero > .hero-html { object-fit: contain; width: min(70%, 20rem); height: auto; margin-inline: auto; }
.stack { flex-direction: column; gap: clamp(1.5rem, calc(1.5rem + 1vw), 2rem); text-align: center; }
.copy { flex-direction: column; gap: 1rem; align-items: center; }
.copy > * { width: 100%; }
h1 { font-size: clamp(var(--sl-text-3xl), calc(0.25rem + 5vw), var(--sl-text-5xl)); line-height: var(--sl-line-height-headings); font-weight: 600; color: var(--sl-color-white); display: flex; flex-direction: row; align-items: center; gap: 1rem; flex-wrap: wrap; }
.tagline { font-size: clamp(var(--sl-text-base), calc(0.0625rem + 2vw), var(--sl-text-lg)); color: var(--sl-color-gray-2); }
.actions { gap: 1rem 2rem; flex-wrap: wrap; justify-content: center; margin-top: 1rem; }
@media screen and (max-width: 1250px) { .hero { flex-direction: column-reverse; text-align: center }
h1 { gap: 0.75rem; text-align: center; justify-content: center; }
.hero > img, .hero > .hero-html { order: 2; width: min(100%, 25rem); } }
@media (min-width: 50rem) { .hero { gap: 2rem; padding: 2rem; }
.hero > img, .hero > .hero-html { order: 2; width: min(100%, 25rem); }
.stack { text-align: start; }
.copy { align-items: flex-start; }
.actions { justify-content: flex-start; } }</style>