5.4 KiB
Team
Function
The people section: a header over a responsive grid of members — photo, name, role and links.
Composition map
| Slot | Composes | Notes |
|---|---|---|
| root | bare <section> |
Section + Container place it; align drives the header and travels to the members |
Header |
Box (measure 48rem) + Motion |
the app supplies a Heading (level 2) and a Text |
Members |
AutoGrid + data-stagger |
fluid via minChildWidth (default 12rem) or fixed columns |
Member |
Motion (trigger="viewport") + Stack |
direct child of the stagger grid, so it gets its structural index |
| the photo | — (app: Avatar composed directly) |
the block does NOT wrap it — nothing to add over its API |
MemberName |
Heading level={3} size="sm" |
|
MemberRole |
Text size="sm" color="muted" |
quieter by size AND ink, without another heading level |
MemberLinks |
Group (marginTop: auto) |
justify follows the section; pinned to the card bottom so uneven bios still line up |
Form: compound, and the one thing the parts coordinate
Member repeats (the app maps over N) → compound, same admission rule as
feature-grid. But unlike feature-grid, these parts also coordinate on one
thing: the cross-axis. The section's align travels through context to every
Member and to its links row, so the photo, the name, the role and the links
share one axis without the app repeating align on every card. An explicit
align on a part always wins.
That is why there is a context here and not in feature-grid — the rule is
applied part by part, not block by block.
Coordination
Position under the 2026-07-31 doctrine (architecture/blocks.md §«Coordination»).
Shares configuration, not state. The section's align travels by context to
every Member and to its link row, so the app does not repeat the axis on each
card — the same use content-section makes of its measure. There is no machine
here: nothing about a team grid can be blocked.
Decisions
2026-07-31 — reference floor (dossier: Tailwind Plus «Team» 9 · PrimeBlocks 12 · Untitled UI):
- Adopted: the portrait grid with a centred header — the arrangement all the
references lead with — and the
startvariant, which is the one that reads when each member carries a bio. - Adopted: the links row per member (the references ship social icons there).
- No
MemberAvatarpart. The plan sketched one; it would add nothing over<Avatar size radius>and would hide its API (Image,Fallback, the load states). The app composes the canon component straight insideMember. Wrap what the block DEFAULTS (typography, grid, axis), not what it merely passes through — registered deviation. - The name is a real heading (
level={3}), stepped down withsize, so a screen reader can jump person to person. Level is structure; size is typography. - No stock faces. The framework ships no people, so the demo renders only
Avatar.Fallbackwith initials — an honest initial beats a brokensrc. When an app DOES pass a photo, theAvatar.Imagetakesalt="": the name is right underneath, and repeating it makes a screen reader say it twice. - The links row is pinned to the bottom (
marginTop: auto). With bios of different length the rows would sit at different heights and the grid would read crooked; without bios the cards already match and the rule changes nothing.
Demo
web/routes/blocks/team/ — the block full-bleed on the page, with live control
of alignment, column count, the bio line and direction, and the device widths
served from preview/. Mini-page in TeamSite.svelte, shared by both surfaces.
Gaps
| Gap | Disposition |
|---|---|
| Full-bleed rectangular portrait (the tall-photo card) | deferred — Avatar is a circle / rounded square; a fixed-ratio portrait is Image / Mockup territory. Enters when a demo asks |
| Horizontal row with a long bio | deferred — photo left, text right is another arrangement, not a variant of this one. The short bio fits in the card today |
| Stock photography | app-land — no faces in the framework |
Found while composing
- (recorded here as they surface.)