Portrait Art
BackgroundsA drawn portrait for a slot that has no photograph yet: a speaker, an artist, a host, a member of a team.
Who is on: each person a drawn portrait on a colour block (PortraitArt, seeded from the name), the name and what they do, and on the back of the portrait their session: its title, the day and time, the stage. A pointer resting on a card, or the keyboard focus on its link, turns the portrait over; on a touch screen the session is a line under the name. With layout="feature" the first two people are drawn twice as large. Zero JavaScript.
Speakers
Foundry name
Letters that move
Company name
Shipping small
Independent
Drawing with code
Studio name
Fast pages
Agency name
Field notes
Studio name
Colour at scale
Live, from the library itself, at full size: scroll, hover, navigate away and back. The demo is never gated.
Variants · each row writes the attribute the prop writes; the section's own CSS answers
JavaScript of its own
0 B
CSS 14.1 kB raw including the base tokens. Measured from a production build, and again in CI for every change that can move it.
Browser support
Chrome 105 · Firefox 121 · Safari 15.4; needs has. Elsewhere: the focus ring is drawn on the name instead of around the card, and the card turns on hover alone.
The demo above is never gated; the source is. With a key in components.json (see account), the registry serves it like any other item:
npx shadcn@latest add @moonarc-pro/lineup-grid---
import LineupGrid from '@/components/moonarc/pro/LineupGrid.astro';
---
<LineupGrid
eyebrow="Speakers"
more={{ href: '/speakers/', label: 'All speakers' }}
people={[
{ name: 'Type designer', role: 'Foundry name', session: { title: 'Letters that move', when: 'Fri 10:30', where: 'Main stage' }, href: '/schedule/#letters' },
{ name: 'Product lead', role: 'Company name', session: { title: 'Shipping small', when: 'Fri 11:30', where: 'Main stage' } },
]}
>
<span slot="headline">Twenty-four speakers, <em>three stages</em></span>
</LineupGrid>Without a key the registry answers 401 with an upgrade message. Everything this section composes is free: portrait-art.
| Prop | Type | Default | Description |
|---|---|---|---|
people | { name, role?, session?: { title, when?, where? }, href?, block? }[] | none | The people, in order. The portrait is drawn from the name; block is the card's colour (the first four in turn when unset); href makes the name the card's link. |
eyebrow | string | none | A short line above the heading. |
headline | string | none | The heading. Slot "headline" wins and may hold an <em>, set in the emphasis face and colour. |
more | { href: string; label: string } | none | A link beside the heading, e.g. to everyone. |
layout | 'feature' | 'even' | 'feature' | feature: the first two people twice as large on a wide box (six or ten people fill its rows); even: one grid. |
level | 1 | 2 | 3 | 2 | Heading level of the section's heading; the names are one below (1 on a page whose own h1 is above the grid). |
tone | 'surface' | 'muted' | 'ink' | 'brand' | unset (paints nothing) | The section's ground; the portraits keep their blocks on every tone. |
density | 'compact' | 'cozy' | 'roomy' | 'cozy' | Block padding ×0.8 / ×1 / ×1.25 through --ma-density. |
The section reads the theme contract (shadcn's variable names with the base tokens as fallback), so a pasted theme or one --ma-brand recolours it. Its class names are the override surface and stay stable; a named slot replaces the matching prop with your own markup.
.ma-lineup.ma-lineup__back.ma-lineup__back-meta.ma-lineup__back-title.ma-lineup__card.ma-lineup__eyebrow.ma-lineup__front.ma-lineup__head.ma-lineup__headline.ma-lineup__link.ma-lineup__list.ma-lineup__more.ma-lineup__name.ma-lineup__photo.ma-lineup__role.ma-lineup__session.ma-lineup__session-meta.ma-lineup__titles.ma-lineup__turn
slot="eyebrow"slot="headline"
The card turns over at once, without the half-second turn.
ClientRouterCSS only; nothing to rebind.
Replaces: Speaker grids (event templates) · Flip card team sections. See the migration table.
A drawn portrait for a slot that has no photograph yet: a speaker, an artist, a host, a member of a team.
The first screen of an event, made like its poster: one colour block with the edition and the place in the mono face, the name huge, the dates, a line, two actions, three facts, a countdown to the doors (core CountdownFlip) and the days as chips, and beside them a composition of nine shapes in the block's drawing colours that pop into place one after another as the page opens and turn a quarter when a pointer rests on them, one of them turning round a quarter at a time once they are in, inside five seconds, then resting.
Schedule
Doors and badges from 09:30
10:00–10:30
Opening
10:30–11:15
Letters that move
Type designer
12:15–13:30
Lunch
14:00–16:00
Drawing with code
Illustrator
The party is in the garden from 19:00
10:00–10:45
Fast pages
Web engineer
13:30–15:30
Motion with manners
Motion designer
16:00–16:45
Everyone reads
Accessibility lead
A shorter day, done by 16:00
10:30–11:15
Words on screens
Writer
11:30–13:00
Light for products
Photographer
15:15–16:00
Closing
A programme by day: a row of day chips (radio buttons, each a weekday over its date in a colour block) picks the day, and under it the day's sessions in order, with the time in the mono face, the title, who leads it, the stage as a chip in the stage's own colour and the kind of session beside it.
Shows team members in a hairline grid: portraits that tilt toward the cursor with a glare, initials when there is no photo, names and roles revealed with a stagger..
Also: view transitions · how costs are measured · browser support · accessibility policy · five-minute setup · MCP for agents · this page as Markdown