Image collage 02
A heading and actions beside a collage of five team photos.
Last updated
---
/**
* Image collage 02: A heading and actions beside a collage of five team photos.
*
* @block team
* @order 10
*/
import Section from '@/components/apogee/Section/Section.astro'
import SectionHeader from '@/components/apogee/SectionHeader/SectionHeader.astro'
import Image from '@/components/apogee/Image/Image.astro'
import Button from '@/components/apogee/Button/Button.astro'
import { plain, type Media } from '@/components/apogee/sections/_shared/spine.ts'
import type { TeamContent } from '@/components/apogee/sections/_shared/team.ts'
/** @composable */
interface Props extends TeamContent {
/** Five team photos for the collage (decorative, hidden from screen readers). @category content */
images?: Media[] | null
}
const {
eyebrow = 'Join our team',
heading = "We're just getting started",
description = 'We hire diverse, passionate people and build a culture that lets everyone do their best work.',
primaryAction = { label: "We're hiring!", href: '#' },
secondaryAction = { label: 'Read our principles', href: '#' },
images = [
{ src: 'https://picsum.photos/id/1027/600/600', alt: '', width: 600, height: 600 },
{ src: 'https://picsum.photos/id/856/600/600', alt: '', width: 600, height: 600 },
{ src: 'https://picsum.photos/id/832/600/600', alt: '', width: 600, height: 600 },
{ src: 'https://picsum.photos/id/91/600/600', alt: '', width: 600, height: 600 },
{ src: 'https://picsum.photos/id/64/600/600', alt: '', width: 600, height: 600 },
],
} = Astro.props
// ponytail: five fixed collage slots; photos past the fifth are ignored.
const slots = ['row-start-7 col-start-5 row-end-13 col-end-9', 'row-start-1 col-start-7 row-end-7 col-end-11', 'row-start-3 col-start-3 row-end-7 col-end-7', 'row-start-7 col-start-9 row-end-11 col-end-13', 'row-start-7 col-start-1 row-end-12 col-end-5']
---
<Section spacing="large" class="overflow-hidden">
<div class="grid items-center gap-12 lg:grid-cols-2 lg:gap-16">
<div class="flex flex-col gap-8">
<SectionHeader eyebrow={eyebrow ?? undefined} heading={plain(heading)} description={description ?? undefined} size="large" />
{(primaryAction || secondaryAction) && (
<div class="flex flex-col gap-3 sm:flex-row-reverse sm:justify-end">
{primaryAction && <Button href={primaryAction.href} size="large">{primaryAction.label}</Button>}
{secondaryAction && <Button href={secondaryAction.href} size="large" variant="outline" color="neutral">{secondaryAction.label}</Button>}
</div>
)}
</div>
{images && (
<div class="-mx-[25%] overflow-hidden sm:-mx-[10%] md:mx-0">
<div class="grid h-122 grid-cols-12 grid-rows-12 gap-2 sm:h-124 md:gap-4" aria-hidden="true">
{images.slice(0, slots.length).map((m, i) => <Image src={m.src} alt={m.alt} width={m.width ?? 600} height={m.height ?? 600} fit="cover" class:list={['size-full', slots[i]]} />)}
</div>
</div>
)}
</div>
</Section>
Show codeHide code
---
/**
* Image collage 02: A heading and actions beside a collage of five team photos.
*
* @block team
* @order 10
*/
import Section from '@/components/apogee/Section/Section.astro'
import SectionHeader from '@/components/apogee/SectionHeader/SectionHeader.astro'
import Image from '@/components/apogee/Image/Image.astro'
import Button from '@/components/apogee/Button/Button.astro'
import { plain, type Media } from '@/components/apogee/sections/_shared/spine.ts'
import type { TeamContent } from '@/components/apogee/sections/_shared/team.ts'
/** @composable */
interface Props extends TeamContent {
/** Five team photos for the collage (decorative, hidden from screen readers). @category content */
images?: Media[] | null
}
const {
eyebrow = 'Join our team',
heading = "We're just getting started",
description = 'We hire diverse, passionate people and build a culture that lets everyone do their best work.',
primaryAction = { label: "We're hiring!", href: '#' },
secondaryAction = { label: 'Read our principles', href: '#' },
images = [
{ src: 'https://picsum.photos/id/1027/600/600', alt: '', width: 600, height: 600 },
{ src: 'https://picsum.photos/id/856/600/600', alt: '', width: 600, height: 600 },
{ src: 'https://picsum.photos/id/832/600/600', alt: '', width: 600, height: 600 },
{ src: 'https://picsum.photos/id/91/600/600', alt: '', width: 600, height: 600 },
{ src: 'https://picsum.photos/id/64/600/600', alt: '', width: 600, height: 600 },
],
} = Astro.props
// ponytail: five fixed collage slots; photos past the fifth are ignored.
const slots = ['row-start-7 col-start-5 row-end-13 col-end-9', 'row-start-1 col-start-7 row-end-7 col-end-11', 'row-start-3 col-start-3 row-end-7 col-end-7', 'row-start-7 col-start-9 row-end-11 col-end-13', 'row-start-7 col-start-1 row-end-12 col-end-5']
---
<Section spacing="large" class="overflow-hidden">
<div class="grid items-center gap-12 lg:grid-cols-2 lg:gap-16">
<div class="flex flex-col gap-8">
<SectionHeader eyebrow={eyebrow ?? undefined} heading={plain(heading)} description={description ?? undefined} size="large" />
{(primaryAction || secondaryAction) && (
<div class="flex flex-col gap-3 sm:flex-row-reverse sm:justify-end">
{primaryAction && <Button href={primaryAction.href} size="large">{primaryAction.label}</Button>}
{secondaryAction && <Button href={secondaryAction.href} size="large" variant="outline" color="neutral">{secondaryAction.label}</Button>}
</div>
)}
</div>
{images && (
<div class="-mx-[25%] overflow-hidden sm:-mx-[10%] md:mx-0">
<div class="grid h-122 grid-cols-12 grid-rows-12 gap-2 sm:h-124 md:gap-4" aria-hidden="true">
{images.slice(0, slots.length).map((m, i) => <Image src={m.src} alt={m.alt} width={m.width ?? 600} height={m.height ?? 600} fit="cover" class:list={['size-full', slots[i]]} />)}
</div>
</div>
)}
</div>
</Section>Add
npx @ava-ui/apogee add team/image-collage-02
This copies the block to src/components/apogee/blocks/team/ with everything it uses: Button, Image, Section, SectionHeader. 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.
Accessibility
- The heading is an
h2by default, so the block slots into a page under itsh1; item titles are one level down. - Photos that only decorate have an empty
alt; give yours one when it carries meaning.