Halftone glow 01
A centred heading, line and two round buttons on a band that runs from dark through the primary hue into the page, with a halftone dot texture and a logo strip below.
Last updated
---
/**
* Halftone glow 01: A centred heading, line and two round buttons on a band that runs from dark through the primary hue into the page, with a halftone dot texture and a logo strip below.
*
* @block hero
* @order 65
*/
import { ChevronRight, Atom, Hexagon, Mountain, Sprout, Waves, Wind } from '@lucide/astro'
import Section from '@/components/apogee/Section/Section.astro'
import Heading from '@/components/apogee/Heading/Heading.astro'
import Button from '@/components/apogee/Button/Button.astro'
import Marquee from '@/components/apogee/Marquee/Marquee.astro'
import { plain, type HeroContent } from '@/components/apogee/sections/_shared/spine.ts'
/** @composable */
interface Props extends HeroContent {
/** The line above the logo strip. @category content */
trustedBy?: string | null
}
const {
heading = 'The AI platform for travel data, decisions and savings',
description = 'One system for travel and finance teams to move faster, spend less and automate the busywork.',
primaryAction = { label: 'Request a demo', href: '#' },
secondaryAction = { label: 'See how it works', href: '#' },
trustedBy = 'Trusted by teams running travel programmes worldwide',
} = Astro.props
const logos = [
{ name: 'Lumen', icon: Hexagon },
{ name: 'Quanta', icon: Atom },
{ name: 'Fieldwork', icon: Sprout },
{ name: 'Northpeak', icon: Mountain },
{ name: 'Arcwave', icon: Waves },
{ name: 'Kitestring', icon: Wind },
]
---
<!--
--glow-to is the outer page colour, read before the band turns dark, so the band
ends in the page whatever the theme.
-->
<Section spacing="none" container={false} class="overflow-hidden" style="--glow-to: var(--background-page)">
<div data-theme="dark" class="relative isolate text-neutral" style="background: linear-gradient(to bottom, var(--background-page), color-mix(in oklab, var(--background-primary) 75%, var(--background-page)) 45%, color-mix(in oklab, var(--background-primary) 45%, var(--glow-to)) 75%, var(--glow-to))">
<!-- Halftone dots, strongest in the middle. -->
<div class="absolute inset-0 -z-10 bg-[radial-gradient(circle,color-mix(in_oklab,var(--foreground-neutral)_35%,transparent)_1px,transparent_1.5px)] bg-size-[6px_6px] mask-[radial-gradient(ellipse_50%_40%_at_50%_70%,black,transparent)]" aria-hidden="true"></div>
<div class="mx-auto flex max-w-4xl flex-col items-center gap-6 px-gutter pb-56 pt-(--spacing-section-lg) text-center md:pb-72">
<Heading as="h1" size="display" class="font-medium text-balance">{plain(heading)}</Heading>
{description && <p class="max-w-2xl text-lg md:text-xl text-neutral-faded">{description}</p>}
{(primaryAction || secondaryAction) && (
<div class="mt-2 flex flex-col gap-3 sm:flex-row">
{primaryAction && <Button href={primaryAction.href} size="large" rounded color="neutral" variant="outline">{primaryAction.label}</Button>}
{secondaryAction && <Button href={secondaryAction.href} size="large" rounded variant="ghost" color="neutral">{secondaryAction.label}<ChevronRight slot="end" class="rtl:-scale-x-100" aria-hidden="true" /></Button>}
</div>
)}
</div>
</div>
<div class="flex flex-col gap-8 pb-16">
{trustedBy && <p class="px-gutter text-center text-neutral-faded">{trustedBy}</p>}
<Marquee label="Customers">
{logos.map((l) => <span class="flex items-center gap-2 px-6 text-lg font-semibold text-neutral-faded"><l.icon class="size-6" aria-hidden="true" />{l.name}</span>)}
</Marquee>
</div>
</Section>
Show codeHide code
---
/**
* Halftone glow 01: A centred heading, line and two round buttons on a band that runs from dark through the primary hue into the page, with a halftone dot texture and a logo strip below.
*
* @block hero
* @order 65
*/
import { ChevronRight, Atom, Hexagon, Mountain, Sprout, Waves, Wind } from '@lucide/astro'
import Section from '@/components/apogee/Section/Section.astro'
import Heading from '@/components/apogee/Heading/Heading.astro'
import Button from '@/components/apogee/Button/Button.astro'
import Marquee from '@/components/apogee/Marquee/Marquee.astro'
import { plain, type HeroContent } from '@/components/apogee/sections/_shared/spine.ts'
/** @composable */
interface Props extends HeroContent {
/** The line above the logo strip. @category content */
trustedBy?: string | null
}
const {
heading = 'The AI platform for travel data, decisions and savings',
description = 'One system for travel and finance teams to move faster, spend less and automate the busywork.',
primaryAction = { label: 'Request a demo', href: '#' },
secondaryAction = { label: 'See how it works', href: '#' },
trustedBy = 'Trusted by teams running travel programmes worldwide',
} = Astro.props
const logos = [
{ name: 'Lumen', icon: Hexagon },
{ name: 'Quanta', icon: Atom },
{ name: 'Fieldwork', icon: Sprout },
{ name: 'Northpeak', icon: Mountain },
{ name: 'Arcwave', icon: Waves },
{ name: 'Kitestring', icon: Wind },
]
---
<!--
--glow-to is the outer page colour, read before the band turns dark, so the band
ends in the page whatever the theme.
-->
<Section spacing="none" container={false} class="overflow-hidden" style="--glow-to: var(--background-page)">
<div data-theme="dark" class="relative isolate text-neutral" style="background: linear-gradient(to bottom, var(--background-page), color-mix(in oklab, var(--background-primary) 75%, var(--background-page)) 45%, color-mix(in oklab, var(--background-primary) 45%, var(--glow-to)) 75%, var(--glow-to))">
<!-- Halftone dots, strongest in the middle. -->
<div class="absolute inset-0 -z-10 bg-[radial-gradient(circle,color-mix(in_oklab,var(--foreground-neutral)_35%,transparent)_1px,transparent_1.5px)] bg-size-[6px_6px] mask-[radial-gradient(ellipse_50%_40%_at_50%_70%,black,transparent)]" aria-hidden="true"></div>
<div class="mx-auto flex max-w-4xl flex-col items-center gap-6 px-gutter pb-56 pt-(--spacing-section-lg) text-center md:pb-72">
<Heading as="h1" size="display" class="font-medium text-balance">{plain(heading)}</Heading>
{description && <p class="max-w-2xl text-lg md:text-xl text-neutral-faded">{description}</p>}
{(primaryAction || secondaryAction) && (
<div class="mt-2 flex flex-col gap-3 sm:flex-row">
{primaryAction && <Button href={primaryAction.href} size="large" rounded color="neutral" variant="outline">{primaryAction.label}</Button>}
{secondaryAction && <Button href={secondaryAction.href} size="large" rounded variant="ghost" color="neutral">{secondaryAction.label}<ChevronRight slot="end" class="rtl:-scale-x-100" aria-hidden="true" /></Button>}
</div>
)}
</div>
</div>
<div class="flex flex-col gap-8 pb-16">
{trustedBy && <p class="px-gutter text-center text-neutral-faded">{trustedBy}</p>}
<Marquee label="Customers">
{logos.map((l) => <span class="flex items-center gap-2 px-6 text-lg font-semibold text-neutral-faded"><l.icon class="size-6" aria-hidden="true" />{l.name}</span>)}
</Marquee>
</div>
</Section>Add
npx @ava-ui/apogee add hero/halftone-glow-01
Every piece of copy is a prop, with the sample copy as its default. Pass yours, or null to hide a part; see copy is props.