Campaign Card

Mobile feed card for a campaign — tap anywhere on the card to open the campaign detail page. Hero image uses a framer-motion `layoutId` for a shared-element transition (App Store / Airbnb pattern). Bound to the `CampaignCard` component set (4 variants across Breakpoint × supporter × State) in the Product Figma library.

Installation

npx chilli@latest add campaign-card

Default (supporter=false)

new from creator you like

@seaspiracy

Tell Thailand's Energy Ministry: Renewables needed amid Hormuz Crisis

Trump wants to rollback the protections for the Northeast Canyons & Seamounts Marine National Monument. We have to stop him!

3.4k
12

Supporter — in progress

new from creator you like

@seaspiracy

Tell Thailand's Energy Ministry: Renewables needed amid Hormuz Crisis

Trump wants to rollback the protections for the Northeast Canyons & Seamounts Marine National Monument. We have to stop him!

3.4k
12

Supporter — just started

@seaspiracy

Tell Thailand's Energy Ministry: Renewables needed amid Hormuz Crisis

Trump wants to rollback the protections for the Northeast Canyons & Seamounts Marine National Monument. We have to stop him!

3.4k
12

Supporter — almost done

@seaspiracy

Tell Thailand's Energy Ministry: Renewables needed amid Hormuz Crisis

Trump wants to rollback the protections for the Northeast Canyons & Seamounts Marine National Monument. We have to stop him!

3.4k
12

Minus — compact mini card

Minus — without creator label

API Reference

CampaignCard

PropTypeDefaultDescription
type"default" | "minus""default"Card variant. `default` renders the full 343×363 card. `minus` renders the compact 160×236 mini card used in carousels (image + title + optional creator label).
campaignIdstringStable ID used as `layoutId` for the shared-element hero transition. Must match the `layoutId` on the campaign detail page's hero image.
imagestringURL of the hero image.
creator{ name, avatar, verified? }Campaign creator. `name` is the handle (e.g. `@seaspiracy`), `avatar` is the URL, `verified` adds the blue check.
titlestringCampaign title — clamped to 2 lines.
bodystringSupporting description — faded out via mask gradient after ~2 lines.
supporters{ count: number, avatars: string[] }Social proof. `count` is formatted (e.g. `3.4k`, `1.2M`). `avatars` shows up to 3 overlapping.
commentCountnumberNumber of comments on the campaign.
sectionLabelstringOptional label rendered above the card (e.g. `"new from creator you like"`).
supporterbooleanfalseWhen true, the footer switches from social proof to a progress bar, and the CTA micro-copy adapts.
progress{ done: number, total: number }Required when `supporter=true`. Drives the progress bar and the CTA label: `start` (0), `continue` (1..total-2), `finish` (total-1).
onOpen() => voidFires when the user taps anywhere on the card. Navigate to the campaign detail page.
onCta() => voidFires on the primary button tap. `supporter=false` → same as `onOpen`. `supporter=true` → should launch the next undone action directly.
hideCreatorLabelbooleanfalse`type="minus"` only — hide the creator avatar + handle below the title (useful when the parent already displays the creator, e.g. in a "more from @X" carousel).
classNamestringAdditional classes applied to the outer wrapper.