Components · Events

RSVP & capacity

The RSVP affordance and the "who's coming" read-outs. RsvpControl is presentational — the parent holds the authoritative status and reacts to onChange, with pending greying the controls mid-mutation. CapacityMeter escalates tone (accent → warn → bad) as the event fills, and the avatar cluster caps with a "+N" overflow chip.

RsvpControl · viewer state — no response / going / maybe / declined / waitlisted / closed
status = null
status = going
Going
status = maybe
Maybe
status = declined
Can't go
going · waitlisted (event full)
Waitlisted · #3
pending — RSVP closed / in flight

Maybe → I'm going is pinned :hover. The control owns no server state: each button reports the requested next status via onChange; pending disables the row at 45% opacity while the parent's mutation lands.

CapacityMeter · fill tone escalates with fullness
filling · < 75% → accent
128 / 250 confirmed
nearly full · ≥ 75% → warn
210 / 250 confirmed
full + waitlist → bad
Full12 waitlisted
uncapped · plain count (no bar)
47 going

fillTone(ratio): < 0.75 accent · < 1 warn · ≥ 1 bad. An uncapped event (capacity == null) renders a running count instead of a meter.

AttendeeAvatars · overflow-aware "who's going" cluster
DW ML PP SR AO +181
188 going

The DS AvatarGroup caps at max visible avatars (default 5, each with a 2px surface ring) and collapses the rest into a +N chip; pass total to drive the overflow when the list is a sampled head (here 5 of 188).

RsvpControl
status: going|maybe|declined|null; onChange(next); waitlisted swaps the "Going" badge for the Waitlisted chip; pending greys + disables the row. Holds no server state.
CapacityMeter
confirmed + capacity (null/0 = uncapped → plain count); waitlist surfaced once full; hideLabel. Tone escalates accent → warn → bad. Built on the DS Meter.
WaitlistBadge
Warn-tone chip with a clock glyph; optional position renders "Waitlisted · #3". Surfaced when a "going" RSVP lands past capacity.
AttendeeAvatars
attendees: { id, name, avatarUrl? }[]; max caps visible avatars; total overrides the "+N"; size; label. Renders nothing when empty.

Source · ds/events/RsvpControl.tsx · CapacityMeter.tsx · WaitlistBadge.tsx · AttendeeAvatars.tsx (DS Avatar / AvatarGroup / Meter / Badge / Button).