East Blue v0.1.0
Component Assessment
Overview
Components
Accordion
Action List
Action List - with Counter
Action List - with Description
Ad
Ad Space
Alert
DM LM
Avatar
Avatar Group
Label Label
Badge
Banner
Bottom Sheet
Button
Callout
Generic Card
Generic Transaction Card
Carousel - Discount Card
Carousel - Item
Carousel Card
Chat Field
Checkbox
Chip
Countdown
Counter
Date Picker
Date Picker - Group
Date Picker - Item
Month and Year Picker - Item
Dropdown
Dropdown Item
Dropdown Item Group
Empty State
Amount Text Field
Input Field
Labeled Field
Recipient Field
Search Field
Select Field
Text Area
Upload File
View Only Field
Footer
Header
Header - Centered
Header - Transaction
Header - With Logo
Inline Message
Inline Text
List
List Item
List Item Asset
Menu Grid
Modal
Overlay
Progress Bar
Radio Button
Radio Button with Label
Service Item
Slider
Stepper - Bullet
Stepper - Circular
Stepper - Dash
Subtext Message
Table
Table - Scheduling
Table - Transaction
Tab Item
Tabs
Title Header
Title Bar
Toast
Toast - With Button
Segmented Control - Group
Toggle
Toggle - Segmented Control
Toggle - With Label
Onboarding - Tooltip
Tooltip Blurred and Transparent
Tooltip V2
Visual Popup
35%
Horizontal Voucher
Terms & Conditions Accordion
35%
Vertical Voucher
35%
Voucher Asset
Voucher Card Horizontal
Voucher Details
Icons Styles
RestructureRequires Rework
Carousel Card Component link

A tappable card used inside a horizontally scrolling carousel — image, title, and optional description.

Restructure — split the type enum, add slots, consolidate the family
The type property conflates a content variant (default vs with icon) with a loading state (skeleton) — these should be orthogonal axes. Banner image, dimmer, and icon badge are all hardcoded placeholders instead of instance slots. No pressed/focused state despite the card being tappable. Most importantly, this component is 1 of 5 near-duplicate "carousel card / item" components that should consolidate to 1–2 canonical primitives.
In Context

Carousel Card lives in a horizontal scroller — typically a "Featured" or "For You" rail on a home or category screen. Cards are peeked (part of the next one visible) to signal scrollability.

Live Preview

Title

Description here.
Description here.

Content
title
description
Properties
type
DS Health
Reusable
Partial
Works across "featured", "services", "articles" carousels, but is one of 5 near-duplicate Carousel components — reuse is fragmented across the family.
Self-contained
Warn
Banner ships a hardcoded "replace-this-asset" PNG + a purple #e6e1ef multiply dimmer + a hardcoded #c2c6cf icon circle. None of these are instance slots, so consumers can't swap media or icons cleanly.
Consistent
Warn
type enum mixes content axes with a loading state. Naming diverges from the sibling Carousel - Item family, which uses position and a different anatomy.
Composable
Partial
Stacks cleanly into a horizontal scroller. Skeleton state is first-class (good), but the icon badge isn't an Icon instance so it can't be composed with the DS icon set.
Behavior
State iOS Android Figma Property Notes
Default Yes Yes type=default Banner image + title + 2-line description. No overlay.
With icon Yes Yes type=with icon Adds a bottom gradient shadow on the banner and a circular icon badge (30×30, blue fill) at the bottom-left of the banner.
Skeleton (loading) Yes Yes type=skeleton loader Gray block for the banner; bar placeholders for title + 2 description lines.
Pressed N/A N/A Not built Card is tappable (navigates to detail) — needs a pressed state: scale-down 0.98 or a subtle bg tint.
Focused N/A N/A Not built Keyboard/D-pad navigation — needs an outline ring for TV/tablet surfaces and accessibility.
Open Issues
  • type enum conflates a content variant with a loading state. default and with icon describe content shape; skeleton loader describes a loading state. Split into two orthogonal axes: variant = default | with-icon and isLoading: Boolean (or a sibling CarouselCardSkeleton component). C2 · Variant & Property Naming
  • Banner is a hardcoded raster placeholder. Ships a static replace-this-asset PNG plus a purple #e6e1ef mix-blend-multiply dimmer layer. Neither is a Figma Slot — designers must detach and redraw to swap media. Expose an image slot and drop the fixed dimmer (tint should be optional + tokenized). C6 · Asset & Icon Quality
  • Icon badge on "with icon" variant is a filled circle, not an Icon instance. A #c2c6cf 24×24 circle sits inside a 30×30 blue pill — there's no instance swap, so brand icons, service glyphs, or Avatars can't be dropped in without detaching. C6 · Asset & Icon Quality
  • No pressed or focused state. Carousel cards are tappable and navigate somewhere — pressed feedback (scale or tint) is expected, and focused is needed for keyboard/D-pad surfaces. Only Default + skeleton are modeled today. C5 · Interaction State Coverage
  • Code Connect mappings not registered. Blocked until the type split, the image/icon slots, and the family consolidation land. C7 · Code Connect Linkability
Design Recommendations
  • Consolidate Carousel Card + Carousel - Discount Card into a single Carousel Card. The two are the same anatomy — 140-wide vertical card with banner + block-content — differing only in visual treatment. Merge into one component with a variant prop (default / discount) and let the discount-specific overlay (price tag, strikethrough, etc.) live as an overlay slot. Today's 5-component family collapses to 2: Carousel Card and Carousel Item. Family
  • Consolidate Carousel - Item + Carousel Item - Center + Carousel Item - Side into a single Carousel Item. "Center" and "side" describe a peek carousel's runtime layout position, not a component variant — a carousel layout computes which item is center vs side, it shouldn't be baked into the component as an enum. Merge these 3 into one Carousel Item and let the parent carousel apply the peek transform. Family
  • Split type into variant + isLoading. variant = default | with-icon describes content shape. isLoading: Boolean (or a dedicated CarouselCardSkeleton sibling) describes the loading state. Keeps content and state axes orthogonal and matches how Generic Card proposes to handle skeleton. Property
  • Adopt Figma Slots for banner and icon badge. Banner becomes an image slot accepting any frame; icon badge becomes an Icon / Avatar instance slot. Native maps banner → AsyncImage / AsyncImage slot and icon → @ViewBuilder (SwiftUI) or @Composable (Compose). Slot
  • Replace the hardcoded purple dimmer with an optional tint token. The #e6e1ef mix-blend-multiply layer is a loudly-colored overlay that shouldn't ship as a default on every banner. Make it an optional overlay prop bound to main/carousel/color/overlay (currently unbound). Token
  • Add pressed + focused states. Pressed: scale 0.98 or bg tint on the full card. Focused: 2px outline ring in border/focus. Tappable components need both. State
  • Rename to clarify hierarchy. After consolidation, Carousel Card (this component + Discount Card) handles the full-width banner pattern; Carousel Item (peek variants) handles the peek pattern. Avoid overlap in naming between the two. Rename
  • Document the skeleton treatment as a shared DS convention. Carousel Card, Generic Card, and other card primitives all ship first-class skeletons — call out the pattern in the guidelines so card-family consistency holds as more components adopt it. Docs
  • See siblings: Generic Card (horizontal list row) — same "card + skeleton + tappable" pattern, different layout. Keep skeleton treatment aligned across both. Family
Types
Default
DES DEV

Banner image + title + 2-line description. The banner ships a placeholder PNG dimmed by a purple multiply layer — replace both with your real media.

Title

Description here.
Description here.

Properties
Type default
Aspect 3:2 hero image
Pagination dots
Colors
Heading #2340A9
Description #6780A9
Surface #FFFFFF
Active dot #005CE5
Inactive dot #EEF2F9
Layout
Card width 140px
Banner size 140 × 140px
Banner radius radius/radius-1 (4px)
Banner gap 12px
Title → desc gap 4px
Total height 215px
Typography
Title style Primary/Headlines/Block
Title font Proxima Soft Bold · 18 / 23 · +0.25
Description style Secondary/Bold/Caption
Description font BarkAda Semibold · 12 / 18 · 0
EBCarousel(items: cards) { card in
    EBCarouselCard(card)
}
Default — Colors

Promotional carousel card with heading, description, and pagination dots.

Role Token Default
Surface bg/color-bg-main #FFFFFF
Heading carousel/color/label-header #2340A9
Description carousel/color/description #6780A9
Active dot bg/color-bg-primary #005CE5
Inactive dot bg/color-bg-strong #EEF2F9
With icon
DES DEV

Default layout + a bottom-left icon badge on the banner. A gradient shadow along the lower third improves icon contrast against bright imagery.

Title

Description here.
Description here.

Properties
Type with-icon
Has icon Yes
Has description Yes
Colors
Surface bg #FFFFFF
Icon container bg #E8F1FF
Title #0A2757
Description #3C4A5C
Layout
Width 280px
Min height 160px
Padding 20px
Corner radius 16px
Icon container 48 × 48px
Icon size 24 × 24px
Gap 12px
Typography
Title style Heading/Small
Description style Body/Small
EBCarouselCard(
    title: "Send money",
    description: "Free transfers to GCash users",
    leadingIcon: Image(systemName: "paperplane.fill"))
)
With Icon — Colors

Icon-led carousel card with a tinted icon container and stacked title/description.

Role Token Default
Surface bg main/card/bg #FFFFFF
Icon container bg main/card/icon/bg #E8F1FF
Title main/card/title #0A2757
Description main/card/description #3C4A5C
Skeleton loader
DES DEV

Loading placeholder: banner becomes a flat light-gray block; title and description become bar placeholders. Card total height drops to 212 (vs 215 default) due to the 16 top gap in the content block.

Properties
Type skeleton
State Loading
Has content No
Colors
Skeleton bg #EEF2F9
Surface bg #FFFFFF
Layout
Width 280px
Min height 160px
Padding 20px
Corner radius 16px
Bar 1 size 120 × 12px
Bar 2 size 180 × 8px
Typography
— No text in skeleton state
EBCarouselCard(isLoading: true)
Skeleton — Colors

Loading state — content slots become rounded grey rectangles on the card surface.

Role Token Default
Skeleton bg main/skeleton/bg #EEF2F9
Surface bg main/card/bg #FFFFFF
Property Mapping
Figma PropertySwiftUICompose
type: default | with icon | skeleton loader variant: default | with-icon + isLoading: Boolean variant: EBCarouselCardVariant + isLoading: Bool
(hardcoded raster) image: Frame (slot) image: () -> Image
(hardcoded text) title: String title: String
(hardcoded text) description: String description: String?
(hardcoded circle) icon?: Icon (slot) icon: EBIcon?
(hardcoded purple multiply) overlay?: Color (token) overlay: Color?
(not modeled) onTap?: () -> Void onTap: (() -> Void)?
Accessibility
RequirementiOSAndroid
Card as a button Whole card wrapped in Button with combined accessibilityLabel (title + description). Modifier.clickable { onClick() }.semantics(mergeDescendants = true) on the column.
Combined announcement "Send Money, Locally or abroad, same day" — VoiceOver reads title then description. Same reading order — TalkBack follows composition.
Image alt If the banner carries meaning, pass accessibilityLabel on the image; otherwise mark as decorative. contentDescription set when banner is content-bearing, null when decorative.
Min touch target Card is 140×215 — comfortably above 44 pt ✓ 140 dp × 215 dp — above 48 dp ✓
Loading state Announce "Loading" once on mount; suppress per-placeholder announcements. contentDescription = "Loading" on the skeleton container.
Focus ring Add a .focused() modifier → 2 px outline for tvOS/iPad keyboard. Modifier.focusable() + border in border/focus token.
Criteria Scorecard
ID Criterion Status Notes
C1 Layer Structure & Naming Ready Clean container / banner / block-content hierarchy. Layer names are semantic.
C2 Variant & Property Naming Needs Refinement type conflates content variant with loading state — split into variant + isLoading.
C3 Token Coverage Needs Refinement Title / description / skeleton fills bound to tokens. Banner PNG, purple dimmer, and icon glyph color are not.
C4 Native Mappability Needs Refinement Maps cleanly to VStack / Column in a horizontal scroller once image/icon slots and skeleton split land.
C5 Interaction State Coverage Needs Refinement Default + skeleton built. Missing pressed + focused.
C6 Asset & Icon Quality Needs Refinement Banner is a raster placeholder PNG; icon is a drawn circle, not an Icon instance; purple dimmer is hardcoded.
C7 Code Connect Linkability Not Mapped Blocked on property split, slot adoption, and family consolidation.
Variants Inventory (3 total)

type (3) = 3 variants. default and with icon share the same overall dimensions (140 × 215); skeleton loader is 140 × 212 due to a different content padding.

typeNodeDimensionsAnatomy
default23:121312140 × 215Banner + title + 2-line description.
with icon23:121322140 × 215Default + gradient shadow + bottom-left 30×30 icon badge on banner.
skeleton loader23:121334140 × 212Flat banner + 3 bar placeholders (title 16, desc 10, desc 10 @ 97w).
1.0.0 — April 2026Major
Initial Assessment · node 23:121311
Verdict: Restructure — Split type into variant + isLoading, adopt image + icon slots, drop the hardcoded purple dimmer, add pressed/focused states, and consolidate the 5-component Carousel family. Open
Schema
Skeleton pattern acknowledged — First-class skeleton variant is valuable; keep it when restructuring into EBCarouselCardSkeleton. Noted
Praise
Family consolidation — 5 Carousel components collapse to 2: Carousel Card (default / discount) and Carousel Item (peek). Open
Family
C2 — Type split — variant for content, isLoading for state. Open
C2
C6 — Image + icon slots — Replace banner PNG and hardcoded icon circle with Figma Slots. Open
C6
C5 — Pressed / focused — Tappable card needs both. Open
C5
C7 — Code Connect — Blocked on above. Open
C7
On this page
Are you looking for Components?
esc