Platform crew
Basinworks · Design systems
5 online
KQ-1277 · TEAM/FAN
A team card whose overlapping faces fan into a readable row on hover or keyboard focus: each face springs to its slot on springs.snap a cascade beat after the last, its first name rolls up beneath it and its presence dot pops in on flick, the "+12" bubble flips about its axis to the full count and an invite button springs out to the end; leaving gathers them back in reverse on glide. Pressing a face lifts it on snap while the rest recede on glide, and opens a details disclosure whose measured height glides open with role, presence, local time and Message. The row is a toolbar with a roving tabindex: arrows move, Home and End jump, Enter focuses a person and moves focus into the details, Escape hands it back.
Basinworks · Design systems
5 online
18 members · 5 online · hover or tab in
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/team-fan
| Prop | Type | Default | Description |
|---|---|---|---|
| members | TeamMember[] | defaultTeam | Everyone on the team (id, name, role, presence, utcOffset, image); the first max are the faces in the stack. |
| total | number | members.length | The team's size when members is only a page of it; the count bubble reads it. |
| max | number | 6 | Faces in the stack before the count bubble; four under 26rem of container width. |
| title | string | "Platform crew" | The card's heading, and the toolbar's name. |
| subtitle | string | "Basinworks · Design systems" | The line under the heading. |
| headingLevel | 2 | 3 | 4 | 3 | The heading's level. |
| value / defaultValue | string | null | null | The focused member's id, controlled or initial; null when nobody is focused. |
| onValueChange | (id: string | null) => void | — | Fires from the press that focused a face or let it go. |
| onInvite | () => void | — | The invite button at the end of the fan. |
| onShowAll | () => void | — | The count bubble: show everyone. |
| onMessage | (id: string) => void | — | Message, in a focused person's details. |
| inviteLabel | string | "Invite" | The invite button's label, under it in the fan. |
| countLabel | string | "members" | The word under the flipped count. |
| spread | number | 0.5 | How much air the fan puts between faces, 0 to 1; always clamped to the card's width. |
| cascade | number | 40 | The beat between one face landing and the next, in ms. |
| focus | number | 0.6 | How far the rest of the team recedes behind a focused face, 0 to 1: opacity, scale and colour. |
| size | "sm" | "md" | "lg" | "md" | Faces 28, 36 or 44 px across. |
| now | Date | number | 2 Oct 2026, 13:02 UTC | The clock each person's local time is read from. |
| accent | string | "var(--accent-bright)" | The focused face's ring and the invite tint; any CSS colour. |
| sound | boolean | false | A swish as a key or a tap opens the fan (hover opens it silently), a pop as a face is focused. |
| disabled | boolean | false | Keeps the stack closed and its buttons inert. |
| className | string | — | Classes for the article. |