Components¶
Every reusable UI primitive in frontend/components/ui/. These are theme-aware, presentation-only — no service calls, no business logic. Feature composites belong in higher-level folders (components/auth/, components/chat/, etc.).
This page is the catalog. For implementation details (the makeStyles(theme) factory pattern, how useTheme() flows in), see Frontend → Architecture.
Foundational¶
Button
Primary (gold gradient), secondary (surface high), tertiary (ghost). Loading and disabled states. Always uses the
md border radius.
Input
Text input with floating label, validation, leading/trailing icon slots. Focus shifts background to
surfaceContainerHighest and label to primary — no border swap.
Chip
Tag / filter pill. Uses
sm radius. Supports campfire-palette tinting for categorical accent.
Logo
App mark, SVG, theme-aware. The only sanctioned brand mark in the codebase.
Layout & containers¶
ActionBar
Sticky bottom action bar. Used inside modals and sheets when the primary action should always be reachable. Auto-respects safe-area insets on iOS.
GlassView
Frosted/blurred surface.
expo-blur on native, CSS backdrop-filter on web. Use sparingly — every glass surface is a moment.
NavBottomSheet
Bottom sheet that hides the bottom nav while open (toggles
isNavHidden via SheetContext). Pair with rich content that wants the full screen.
SnapBottomSheet
Bottom sheet with snap detents (half-screen / full-screen). Pure UI gesture, no nav coupling.
AnchoredPopover
Popover anchored to a target element. Auto-flips position to stay in viewport.
Tooltip
Hover tooltip on web, long-press tooltip on native. Same API;
Platform.OS handles dispatch.
Feedback¶
Toast
Notification rendered by
ToastContext. Single queue. Variants: success, warning, error, info.
ConfirmationModal
Yes/no destructive-action modal. Default-focuses the safe (cancel) button on open.
ShareOptionsMenu
Share-target sheet — system share API + copy link + (optionally) per-app deep links.
Media & social¶
UserAvatar
Avatar with online indicator and initials fallback. Three sizes:
sm, md, lg.
GroupAvatar
Composite avatar for group chats — tessellates up to 4 participant avatars in a single circle.
GalleryCard
Media gallery tile used in moments / events. Handles single image, multi-image carousel, and video preview.
StatCard
Numeric stat tile (label + value + optional delta). Used on profile and admin dashboards.
Decorative & motion¶
FadeInView
Mount animation wrapper. Default ease-out 240ms.
ScrollRevealView
Reveals children as they enter the viewport on scroll. Used on landing / website surfaces, not in-product.
VoxelSlot
Decorative animated tile (used on landing pages and brand-moment screens). The "physical display box" that grounds the 3D-toy aesthetic into the 2D UI.
Composition rules¶
- Use the primitive as-is. If you need a variant, add it to the primitive — don't fork.
- Stylesheet factories. Every component declares
const makeStyles = (theme) => StyleSheet.create({...})at the top. Components readthemeviauseTheme()once and memoize the resulting sheet — the factory runs on theme change, not on every render. - Compose, don't extend. Build feature components by composing primitives. A
ChatMessageBubbleis aViewwrappingUserAvatar+body-lgtext + (optional)Toast-style reaction tray. It doesn't subclass anything.
Adding a primitive¶
- Drop the file in
frontend/components/ui/. - Follow the
makeStyles(theme)pattern. No service calls inside, no business logic — just rendering. - Add an entry to this page in the same PR, under the appropriate grouping above. Include: purpose, key variants, sizing if relevant.
- If the new primitive uses a previously-unused color token, also update Color.
- If it introduces a new motion duration or easing, also update Motion.
Storybook?¶
Not today. The catalog above + the source files are the canonical references. A live Storybook is a candidate future addition; for now, pull the component into a temporary playground screen if you need to iterate visually.