Components / Content Card

Content Card

The generated-post card: 9:16 media rendered through MediaPlayer with the two-cell ContentCardFooter (account and schedule) beneath, wrapped in the gradient hover glow.

import { ContentCard, ContentCardSkeleton, type ContentDestination } from '@layers/ui/content-card'

Rendered stock

House rules

  • Feed it the post shape (id, media_urls, media_type); the footer comes from one destinations array, each entry pairing an account with the time it goes out.
  • onMediaClick opens the post; onFooterClick opens assignment and scheduling. They are separate targets on purpose.
  • unassigned and needsApproval are the two accountless states, and they are NOT interchangeable: unassigned means nothing owns this piece yet, needsApproval means an owner is waiting on a human verdict. Both are read only when destinations is empty — with a destination the pill itself carries the state.
  • hideFooter rounds the media region into a full card and stops it stretching, so a footerless card can sit in a MIXED grid beside footered ones without painting a blank band under its media.
  • Styles ship with the component (content-card.css is self-imported).
  • ContentRenderer is a near duplicate that accepts nullable post fields; prefer ContentCard when your data is non-nullable.
  • While a grid is loading, render ContentCardSkeleton tiles — the same shell (9:16 media plus footer), so tiles do not change size on load.

See also