12

Content

Cards Builder Component

The Content Card is a reusable 6-variant component built via buildContentCard() / .bsn-content-card-mount. Covers Admin Portal, Scheduler, End User Portal, Group, Marketplace, and Pack Management surfaces. The builder enforces the per-variant chip, status, footer mode, and body-extras matrix. NEVER hardcode .bsn-content-card markup — always use the mount point. Stat / KPI cards belong in §15 Analytics & Data Visualization — see buildKpiStrip().

§12.1 — Content Card Component

Six variants sharing a three-region chassis: thumbnail · body · footer. Chips on thumbnails use a translucent-white outline style via buildChip() with card-thumb context CSS. Status labels in footers use buildChip({ statusDot: true }). Overflow buttons use bsnIcon("ellipsis-vertical") — always fa-sharp fa-solid. Avatars in Group cards use bsnAvatar()-compatible initials with DS color tokens. All footer buttons enforce border-radius: var(--radius-pill).

Pick your variant first

Rule: Always identify the surface before setting any other property. Disallowed combinations are silently dropped by the builder. If no variant fits, do not build custom card markup — use the closest variant or flag the gap to the design system owner.
If the surface / use case is… Variant
Admin content library — flows, courses, campaigns, events browsed by adminsadmin
Flow Scheduler — date-range scheduled flowsscheduler
End User Portal — learner-facing content browseeup
Groups, teams, audiences, membershipgroup
Marketplace — pack browse, trial, purchase, acquisition statesmarketplace
Pack management — publisher/admin view of packs they create and publish (incl. private/unlisted)pack-admin
Dashboard summary card, KPI card, metric tile→ Not a content card. Use buildKpiStrip()
Profile card, people list, notification card, or any other card-like pattern→ No variant exists. Use closest or flag to DS owner

Variant matrix

Slot Admin Scheduler EUP Group Marketplace Pack Admin
Status Published · Draft · Not Published · Published by [Name] Date range (Uinta dot when active, gray when outside range) Not Started · In Progress · Finished · Registered · Not Registered Public · Private Requested · Added · Purchased · Active Trial — (moved to thumbnail chips, see below)
Chips contentType (always) · objective (flows) · duration (video) flowType (always) · priority (Course only — Campaign never) contentType · duration (video) trending · expired · expiring (max 2) packStatus · visibility (max 2 — status left, visibility right)
Footer status + ellipsis status + ellipsis status (or progress) + ellipsis status + action button. No ellipsis. Requested → status only · Added/Purchased/Active Trial → status + overflow menu · solo button · paired buttons Last modified date + overflow menu (Preview / Edit / Delete). No status, no CTA buttons.
Body extra Modified date Event date (events) Avatar stack + member count price · pricePeriod · adoption — (date moved to footer, see above)

Admin Portal Component

Content Library browse. Thumbnail: image (video/PDF) · app logo · content-type icon (fallback). Body: Modified date. Footer: always status + ellipsis.

Scheduler Component

Flow scheduling. Status is a date range — Uinta dot when today is in the active window, gray when outside. Campaign flows never receive a Priority chip. Footer: always status + ellipsis.

End User Portal Component

Learner browse. Status reflects the user's progress state. Events show a date/time line. Footer: status + ellipsis.

Group Component

Audience and membership management. Thumbnail always uses fa-users. Body shows avatar stack + member count. No chips. Status: Public or Private. Footer has a single action button — Join, Leave, or Request to join. No ellipsis.

Marketplace Component

Pack browse. Thumbnail: brand logo centered on a fixed-height (110px) cap. Chips: Trending (chip-yellow), Expired (chip-arches), Expires [date] (chip-canyonlands). Max 2 chips per card — when 2 are present they are left/right justified so neither covers the centered brand logo (justify-content: space-between on the chip container, Marketplace variant only). Body: price string + optional adoption signal. Footer rules: Requested → status only; Added/Purchased/Active Trial → status + overflow menu; solo button → full-width (Purchase only or Add to Account); paired → Trial + Purchase. Overflow menus: Added gets Manage Licenses + Remove from Account (danger); Purchased gets Purchase More Licenses + Manage Licenses (no Remove — paid packs are not removable); Active Trial gets Purchase Pack + Cancel Trial (danger).

Trending + Trial + Purchase / Purchase only

Add to Account / Request Pack — paid price / free (NEW) / no price

Post-acquisition states — Added / Purchased / Requested

Active Trial — status + overflow (Purchase Pack / Cancel Trial)

Expired / Expiring states — Renew CTA

Pack Admin Component

Publisher-facing sibling of Marketplace — same packs, same brand-logo thumbnail treatment (fixed 110px height), but this is the view a pack's creator sees while managing it, not the public browse surface. Status (Draft/Published) and visibility (Private) are thumbnail chips instead of a footer status — packStatus (chip-arches / chip-uinta) left, visibility (chip-alpine, Private only — Public renders no chip) right, same 2-chip space-between layout as Marketplace. Footer always shows last-modified date + the DS overflow menu (Preview / Edit / Delete) — never a status chip or purchase CTA. Unlike Admin/Scheduler/EUP's inert , this menu carries real actions on every card regardless of status; gate a Published-pack Delete confirmation at the page level, not in the card. Thumbnails prefer imageUrl over logo for real packs — publishers span far more brands than the fixed LOGO_BRANDS allowlist covers.

Published — public

Published — private (unlisted from the public marketplace)

Draft — logo is required at pack creation, so every card (including Drafts) always has one

Selection Patterns Component

Cards support two selection modes. Add data-select-mode="multi" or "single" to the grid container — the builder wires the behavior automatically. The multi-select pattern is an atomic pair: data-select-mode="multi" on the grid and .bsn-bulk-toolbar above it must always be deployed together — never one without the other. This rule applies to all five card variants. Per-card configs must also include "selectMode":"multi" to render per-card checkboxes. data-select-mode="single" is for picker/chooser flows only — never pair it with bulk action buttons.

Single-select — click the card; Wasatch ring + 2px outline. No explicit checkbox control.

Multi-select — hover to reveal checkbox; click to enter selection mode. Pair with bulk toolbar above the grid.

0 of 4 selected

Builder API

Set variant and the builder enforces the matrix. Disallowed combinations are logged and dropped.

<div class="bsn-content-card-mount" data-bsn-content-card='{
  "variant":     "admin",
  "publisher":   "BrainStorm",
  "title":       "My Content Title",
  "description": "Short description of this content item.",
  "thumbnail":   { "contentType": "course" },
  "chips":       [
    { "type": "contentType", "value": "Course" },
    { "type": "objective",   "value": "Optimization" }
  ],
  "date":        { "label": "Modified", "value": "05/12/2026" },
  "status":      { "value": "Published" },
  "ellipsis":    true
}'></div>

<!-- Grid container: wrap mount points for auto-fill layout -->
<div class="bsn-content-card-grid">
  <div class="bsn-content-card-mount" data-bsn-content-card='{...}'></div>
</div>

<!-- Selection modes on the grid container -->
<div class="bsn-content-card-grid" data-select-mode="multi"> ... </div>
<div class="bsn-content-card-grid" data-select-mode="single"> ... </div>
Spec: 12px radius, white bg, 1px border, shadow-sm. Hover: shadow-md + 2px Y lift. Thumbnail: 16:9 aspect ratio, neutral gray (#f0f0f2) with dot-grid texture, brand logo or content-type icon centered. Chips on thumb: translucent-white pill with 1px border (card-thumb context override applied automatically). Status: buildChip({ statusDot: true }) — never hardcoded dot+text markup. Buttons: always --radius-pill (999px). Icons: always fa-sharp fa-solid. Selection: Wasatch outline ring. See builders.md §buildContentCard() for full config schema.