Components
Major components in src/components/. shadcn/ui primitives in src/components/ui/ are not listed individually.
| Component | Used in | Props |
|---|---|---|
AppShell | Wraps every authenticated route (now-playing, upcoming, movie, profile) | children: ReactNode. Subscribes to realtime, gates auth → invite → onboarding → app, renders TabBar. |
TabBar | Bottom nav inside AppShell | No props. Renders Now Playing / Upcoming / Profile tabs with active state. |
TopBar | Header on most app pages | title, subtitle?, back?: { to: string }, trailing?: ReactNode, large?: boolean |
MovieCard | Now Playing list + featured pick | movie: Movie, votes: Vote[], members: Member[], featured?: boolean. Shows poster, title, vote button, voter avatars. |
VoteButton | MovieCard, movie detail page | movieId: string, voted: boolean, count: number, size?: 'sm'|'md'|'lg'. Optimistic heart toggle via supabase upsert/delete. |
AmcShowtimes | Movie detail page | movieId: string. Fetches AMC showtimes filtered to the member's preferred AMC theaters; groups by theater and format; handles RSVP. |
ShowtimeCard | Upcoming page, movie detail (legacy member-proposed plans) | showtime: Showtime, attendees: Attendee[], members: Member[], proposer: Member, showMovieTitle?: boolean |
Avatar | Everywhere a member is shown | name, initial, url?, size?: number = 32, className? |
AvatarStack | MovieCard, ShowtimeCard, watch logs | members: { name, avatar_initial, avatar_url? }[], max?: number = 4, size?: number = 24 |
DocsPage / Table | Docs section (this page) | title, lead?, children for DocsPage; headers: string[], rows: ReactNode[][] for Table. |
Conventions
- All colors come from semantic tokens in
src/styles.css— never hardcoded hex/RGB. - Components are presentational + a small amount of inline data fetching when scoped (e.g.
AmcShowtimes). Page-level data is fetched in routes via React Query hooks. - Mutations live in the component that owns the action, and invalidate the relevant query keys directly.