Image glass 03
A heading and actions beside four portraits with details on glass panels.
Last updated
---
/**
* Image glass 03: A heading and actions beside four portraits with details on glass panels.
*
* @block team
* @order 13
*/
import { ArrowUpRight, AtSign, BriefcaseBusiness, Globe } from '@lucide/astro'
import Section from '@/components/apogee/Section/Section.astro'
import SectionHeader from '@/components/apogee/SectionHeader/SectionHeader.astro'
import Heading from '@/components/apogee/Heading/Heading.astro'
import Image from '@/components/apogee/Image/Image.astro'
import Link from '@/components/apogee/Link/Link.astro'
import Button from '@/components/apogee/Button/Button.astro'
import { plain } from '@/components/apogee/sections/_shared/spine.ts'
import type { TeamContent } from '@/components/apogee/sections/_shared/team.ts'
/** @composable */
interface Props extends TeamContent {}
const {
eyebrow = 'Our team',
heading = 'Leadership team',
description = "We're a cross-disciplinary team that loves to create great experiences for our customers.",
primaryAction = { label: 'Open positions', href: '#' },
secondaryAction = { label: 'About us', href: '#' },
items = [
{ name: 'Maya Okafor', role: 'Founder and CEO', avatar: 'https://picsum.photos/id/1027/800/1000', bio: 'Started the company after ten years building tools for small teams.', links: [{ label: "Maya's social profile", href: '#' }, { label: "Maya's work history", href: '#' }, { label: "Maya's website", href: '#' }] },
{ name: 'Tomas Lindqvist', role: 'Engineering Manager', avatar: 'https://picsum.photos/id/856/800/1000', bio: 'Keeps the team shipping and the pager quiet.', links: [{ label: "Tomas's social profile", href: '#' }, { label: "Tomas's work history", href: '#' }, { label: "Tomas's website", href: '#' }] },
{ name: 'Priya Raman', role: 'Product Manager', avatar: 'https://picsum.photos/id/832/800/1000', bio: 'Turns customer calls into roadmaps people can read.', links: [{ label: "Priya's social profile", href: '#' }, { label: "Priya's work history", href: '#' }, { label: "Priya's website", href: '#' }] },
{ name: 'Jonah Weiss', role: 'Frontend Developer', avatar: 'https://picsum.photos/id/91/800/1000', bio: 'Cares about fast pages and buttons that feel right.', links: [{ label: "Jonah's social profile", href: '#' }, { label: "Jonah's work history", href: '#' }, { label: "Jonah's website", href: '#' }] },
],
} = Astro.props
const icons = [AtSign, BriefcaseBusiness, Globe]
---
<Section spacing="large">
<div class="grid gap-12 lg:grid-cols-[22.5rem_1fr] 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>
<ul class="grid list-none p-0 gap-x-8 gap-y-6 sm:grid-cols-2 md:gap-y-8">
{items.map((p) => (
<li><div class="relative isolate flex flex-col justify-end overflow-hidden rounded-2xl aspect-[4/5] md:aspect-[3/4]">
<div class="absolute inset-0 -z-10">{p.avatar && <Image src={p.avatar} alt="" width={800} height={1000} fit="cover" class="size-full" />}</div>
<div class="m-3 rounded-xl bg-page/80 px-4 pt-5 pb-6 ring-1 ring-inset ring-neutral backdrop-blur-md md:m-4 md:px-5">
<div class="flex items-start justify-between gap-2"><Heading as="h3" size="h5">{p.name}</Heading><ArrowUpRight class="size-6 shrink-0" aria-hidden="true" /></div>
<p class="font-semibold">{p.role}</p>{p.bio && <p class="mt-2 text-sm text-neutral-faded md:text-base">{p.bio}</p>}{p.links && <ul class="flex list-none gap-4 p-0 mt-4 gap-5">{p.links.map((l, j) => { const Icon = icons[j % icons.length]!; return <li><Link href={l.href} color="neutral" underline="none" aria-label={l.label} class="text-neutral-faded hover:text-neutral"><Icon class="size-5" aria-hidden="true" /></Link></li> })}</ul>}
</div>
</div></li>
))}
</ul>
</div>
</Section>
Show codeHide code
---
/**
* Image glass 03: A heading and actions beside four portraits with details on glass panels.
*
* @block team
* @order 13
*/
import { ArrowUpRight, AtSign, BriefcaseBusiness, Globe } from '@lucide/astro'
import Section from '@/components/apogee/Section/Section.astro'
import SectionHeader from '@/components/apogee/SectionHeader/SectionHeader.astro'
import Heading from '@/components/apogee/Heading/Heading.astro'
import Image from '@/components/apogee/Image/Image.astro'
import Link from '@/components/apogee/Link/Link.astro'
import Button from '@/components/apogee/Button/Button.astro'
import { plain } from '@/components/apogee/sections/_shared/spine.ts'
import type { TeamContent } from '@/components/apogee/sections/_shared/team.ts'
/** @composable */
interface Props extends TeamContent {}
const {
eyebrow = 'Our team',
heading = 'Leadership team',
description = "We're a cross-disciplinary team that loves to create great experiences for our customers.",
primaryAction = { label: 'Open positions', href: '#' },
secondaryAction = { label: 'About us', href: '#' },
items = [
{ name: 'Maya Okafor', role: 'Founder and CEO', avatar: 'https://picsum.photos/id/1027/800/1000', bio: 'Started the company after ten years building tools for small teams.', links: [{ label: "Maya's social profile", href: '#' }, { label: "Maya's work history", href: '#' }, { label: "Maya's website", href: '#' }] },
{ name: 'Tomas Lindqvist', role: 'Engineering Manager', avatar: 'https://picsum.photos/id/856/800/1000', bio: 'Keeps the team shipping and the pager quiet.', links: [{ label: "Tomas's social profile", href: '#' }, { label: "Tomas's work history", href: '#' }, { label: "Tomas's website", href: '#' }] },
{ name: 'Priya Raman', role: 'Product Manager', avatar: 'https://picsum.photos/id/832/800/1000', bio: 'Turns customer calls into roadmaps people can read.', links: [{ label: "Priya's social profile", href: '#' }, { label: "Priya's work history", href: '#' }, { label: "Priya's website", href: '#' }] },
{ name: 'Jonah Weiss', role: 'Frontend Developer', avatar: 'https://picsum.photos/id/91/800/1000', bio: 'Cares about fast pages and buttons that feel right.', links: [{ label: "Jonah's social profile", href: '#' }, { label: "Jonah's work history", href: '#' }, { label: "Jonah's website", href: '#' }] },
],
} = Astro.props
const icons = [AtSign, BriefcaseBusiness, Globe]
---
<Section spacing="large">
<div class="grid gap-12 lg:grid-cols-[22.5rem_1fr] 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>
<ul class="grid list-none p-0 gap-x-8 gap-y-6 sm:grid-cols-2 md:gap-y-8">
{items.map((p) => (
<li><div class="relative isolate flex flex-col justify-end overflow-hidden rounded-2xl aspect-[4/5] md:aspect-[3/4]">
<div class="absolute inset-0 -z-10">{p.avatar && <Image src={p.avatar} alt="" width={800} height={1000} fit="cover" class="size-full" />}</div>
<div class="m-3 rounded-xl bg-page/80 px-4 pt-5 pb-6 ring-1 ring-inset ring-neutral backdrop-blur-md md:m-4 md:px-5">
<div class="flex items-start justify-between gap-2"><Heading as="h3" size="h5">{p.name}</Heading><ArrowUpRight class="size-6 shrink-0" aria-hidden="true" /></div>
<p class="font-semibold">{p.role}</p>{p.bio && <p class="mt-2 text-sm text-neutral-faded md:text-base">{p.bio}</p>}{p.links && <ul class="flex list-none gap-4 p-0 mt-4 gap-5">{p.links.map((l, j) => { const Icon = icons[j % icons.length]!; return <li><Link href={l.href} color="neutral" underline="none" aria-label={l.label} class="text-neutral-faded hover:text-neutral"><Icon class="size-5" aria-hidden="true" /></Link></li> })}</ul>}
</div>
</div></li>
))}
</ul>
</div>
</Section>Add
npx @ava-ui/apogee add team/image-glass-03
This copies the block to src/components/apogee/blocks/team/ with everything it uses: Button, Heading, Image, Link, 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.