RestructureRequires Rework
Callout Component link

A compact attention strip with neutral, info, warning, or danger intent, optional description, and an optional leading icon.

Restructure before native handoff
Rename to Callout, collapse the redundant label + label size booleans into a single labelSize enum, and expand type into a proper 4-value intent enum (info / success / warning / error). Add a leading-icon slot, a trailing action slot, and Pressed / Disabled states.
In Context

Appears beneath form fields, inside modals, or between screen sections — to clarify what happens next, flag a soft warning, or offer supplemental instructions that don't rise to Alert-level severity.

Live Preview
Add title here
This is the first sentence. This is the second sentence. This is the third sentence. This is the fourth sentence. This is the fifth sentence.
Properties
label
label size
description
type
DS Health
Reusable
Partial
Works inline across forms, modals, and flows. But the intent enum is limited to Default and Information — consumers needing Warning or Error callouts today reach for Alert, which over-weights the UI.
Self-contained
Partial
Carries its own container, label, description, and per-type tokens (main/contextual-help/color/{default|info}/*). Missing: a leading icon slot and a trailing action slot; both are standard in the industry pattern.
Consistent
Warn
Two properties encode one concept: label=yes/no + label size=small/default/no. Three Cartesian cells are invalid. The type property is also a 2-value stub of what should be a proper intent enum.
Composable
Partial
Drops into any column or modal. No interaction states means it can't host an inline "Learn more" link cleanly; consumers either link the whole container (no pressed state defined) or nest a Button, which over-pads.
Behavior
State iOS Android Figma Property Notes
Default (neutral) Yes Yes type=default Grey-blue bg #F6F9FD, border #E5EBF4, label #445C85, description #6780A9. Ambient hints.
Information Yes Yes type=information Light blue bg #E5F1FF, border #D2E5FF, label #072592. Helpful context.
Warning N/A N/A — (missing) No warning intent. Consumers reach for Alert component instead, which is heavier.
Error N/A N/A — (missing) No error intent. Same workaround as Warning.
Pressed N/A N/A — (missing) If the callout is tappable (e.g. opens a sheet with more info), there's no pressed state to reflect that affordance.
Disabled N/A N/A — (missing) No disabled state. Parent form disabled context is not reflected in the callout.
Open Issues
  • Component name "Contextual Help" is internal jargon. Industry-standard term for this shape is Callout — used by Atlassian, GitHub, Notion, and Stripe. The current name doesn't describe the anatomy and overlaps conceptually with Tooltip. Rename the component to make its purpose self-evident in picker menus and code. C1 · Layer Structure & Naming
  • Redundant label axes. label=yes/no and label size=small/default/no encode overlapping information. When label=no, label size is forced to no; two of the nine Cartesian cells (no/small, no/default) are invalid and unused. Collapse to a single labelSize: none | small | default enum. C2 · Variant & Property Naming
  • type=default | information is a two-value stub. Real-world callouts need Info / Success / Warning / Error. Today consumers escalate to Alert for Warning or Error because no Warning or Error callout exists — Alert over-weights the UI for soft messages. Expand to a 4-value intent enum. C2 · Variant & Property Naming
  • No leading icon slot. Every mature callout in the industry (Material, HIG, GitHub, Notion, Stripe) leads with an intent-bound icon — info, check, warning triangle, error circle. This component relies on colour alone, which fails WCAG 1.4.1 (Use of Color). C4 · Native Mappability
  • No interaction states. Callouts frequently host a trailing "Learn more" link or open a sheet on tap. Without Pressed / Focused / Disabled, the Figma source can't express either affordance and consumers nest a Button (too heavy) or link the whole container (no pressed feedback). C5 · Interaction State Coverage
  • No trailing action slot. A named trailing slot — for a "Learn more" TextButton or a dismiss X — is a canonical callout affordance. Consumers currently detach the instance or append a sibling, both of which break DS governance. C4 · Native Mappability
  • Icon for type=information not wired. Figma ships an Information variant with no actual information icon — only a blue tint. If the plan is to carry intent via colour, this is the C6 gap to close: add a vector icon instance bound to main/callout/info/icon. C6 · Asset & Icon Quality
  • Code Connect mappings not registered. Blocked behind the rename, property-schema collapse, intent-enum expansion, icon slot, and interaction states. No native component file exists yet. C7 · Code Connect Linkability
Design Recommendations
  • Rename Contextual HelpCallout. Industry-standard term (Atlassian, GitHub, Notion, Stripe). Describes the anatomy — an inline informational block — and doesn't collide with Tooltip, Alert, or Subtext Message. Also rename the token namespace from main/contextual-help/* to main/callout/*, and the component file to EBCallout.swift / EBCallout.kt. Rename
  • Collapse label + label size into one labelSize enum. Replace the two properties with a single labelSize: none | small | default enum. Three Cartesian cells (no/small, no/default, plus the implicit invalid combinations) disappear, and consumers pick a size directly — no more "turn label on then pick a size" two-step. Property
  • Expand type into a 4-value intent enum. Replace type=default | information with intent: .info | .success | .warning | .error. Add the corresponding token groups (main/callout/success/*, main/callout/warning/*, main/callout/error/*) and default leading icons per intent. Pushes soft-severity messages off Alert and into Callout where they belong. Property
  • Add a leading-icon slot with per-intent defaults. Every callout intent ships a default icon (info-circle, check-circle, warning-triangle, error-circle) that consumers can override or hide. Bind to main/callout/{intent}/icon. Closes the colour-only accessibility gap and matches Material, HIG, GitHub, and Notion conventions. Slot
  • Add a trailing action slot. Adopt Figma Slots to expose #trailing-action for a single TextButton (e.g. "Learn more") or a close X icon. Consumers instance-swap a Text Button into the slot; the callout handles spacing and vertical alignment. Slot
  • Add Pressed and Disabled states. When the entire callout is tappable (opens a sheet with more detail), it needs a Pressed state with a slightly darker bg token. When a parent form is disabled, the callout needs a matched Disabled state (muted label + description + 0.6 opacity border). State
  • Rename main/contextual-help/color/info/*main/callout/info/*. Token names follow the component name. Rename the whole group at once when the component rename lands; defer until native handoff so consuming files don't thrash. Token
  • Document the Callout vs Alert vs Subtext Message vs Tooltip decision tree. Designers conflate these four because the naming overlaps. Publish a one-pager: Subtext (field helper), Callout (inline block, soft intent), Alert (page-level banner, hard intent), Tooltip (hover/press popover). No Figma change — a usage doc on the guide page. Docs
Types
Default
DES DEV

Compact attention strip. Flip Type / Label / Label size / Description to walk through every variant.

Properties
Type
Label
Label Size
Description
Properties
Type Default
Label yes
Label size Default
Description yes
Colors
Surface #F6F9FD
Border #E5EBF4
Label #445C85
Description #6780A9
Layout
Padding 12 × 12
Border radius 6
Border 1px solid
Gap 8
Typography
Label style Primary/Label/Base
Label font Proxima Soft Bold · 16 / 16 · +0.25
Description style Secondary/Bold/Base
Description font BarkAda Semibold · 14 / 20
Colors by Type

All colors bound to main/contextual-help/color/* tokens (target after rename: main/callout/*). No appearance modes. No Pressed or Disabled state defined.

Role Token TOKENVALUE
Default bg main/contextual-help/color/default/bg #F6F9FD
Default border main/contextual-help/color/default/border #E5EBF4
Default label main/contextual-help/color/default/label #445C85
Default description main/contextual-help/color/default/description #6780A9
Information bg main/contextual-help/color/info/bg #E5F1FF
Information border main/contextual-help/color/info/border #D2E5FF
Information label main/contextual-help/color/info/label #072592
Information description main/contextual-help/color/info/description #6780A9
Success — (missing)
Warning — (missing)
Error — (missing)
Pressed — (missing)
Disabled — (missing)
Installation Planned API

iOS — Swift Package Manager

// In Xcode: File → Add Package Dependencies
"https://github.com/AY-Org/eb-ds-ios"

Android — Gradle (Kotlin DSL)

dependencies {
    implementation("com.eastblue.ds:feedback:1.0.0")
}

Import

import EastBlueDS  // SwiftUI
import com.eastblue.ds.feedback.*  // Compose

Package not yet published. Names reflect the proposed rename (EBCallout, not EBContextualHelp).

Property Mapping

Assumes the recommended architecture: single labelSize enum (replacing label + label size), full 4-value intent enum (replacing type), plus an optional leading icon and trailing action slot.

Figma PropertySwiftUICompose
label (yes/no) + label size (small/default/no) labelSize: EBCalloutLabelSize = .none labelSize: EBCalloutLabelSize = None
Label text title: String? title: String? = null
description (yes/no) description: String? description: String? = null
type=default | information .ebIntent(.info / .success / .warning / .error) intent: EBCalloutIntent
— (missing) leadingIcon: Image? leadingIcon: @Composable (() -> Unit)?
— (missing) trailingAction: (() -> some View)? trailingAction: @Composable (() -> Unit)?
— (missing) .disabled(true) enabled: Boolean = true
SwiftUI
ios/Components/Feedback/EBCallout.swift
Jetpack Compose
android/components/feedback/EBCallout.kt
Usage Snippets Planned API
Info callout — label + description
EBCallout(
    title: "Add title here",
    description: "This is a short helpful context message for the user."
)
    .ebIntent(.info)
    .ebLabelSize(.default)
EBCallout(
    title = "Add title here",
    description = "This is a short helpful context message for the user.",
    intent = EBCalloutIntent.Info,
    labelSize = EBCalloutLabelSize.Default
)
With trailing action (Learn more)
EBCallout(
    title: "Verify your number",
    description: "We'll send a one-time code to confirm this device."
)
    .ebIntent(.info)
    .ebTrailingAction {
        EBTextButton("Learn more") { showSheet = true }
    }
EBCallout(
    title = "Verify your number",
    description = "We'll send a one-time code to confirm this device.",
    intent = EBCalloutIntent.Info,
    trailingAction = {
        EBTextButton("Learn more", onClick = { showSheet = true })
    }
)
Warning intent (new)
EBCallout(
    description: "Transfers above ₱50,000 require ID verification."
)
    .ebIntent(.warning)
    .ebLabelSize(.none)
EBCallout(
    description = "Transfers above ₱50,000 require ID verification.",
    intent = EBCalloutIntent.Warning,
    labelSize = EBCalloutLabelSize.None
)
Accessibility
RequirementiOSAndroid
Don't rely on colour alone Pair intent with a leading icon (info / warning / error). WCAG 1.4.1. Same — both icon and color must carry intent.
Semantic grouping Wrap label + description in an accessibilityElement(children: .combine) so VoiceOver reads them as one note. Use Modifier.semantics(mergeDescendants = true).
Live-region announce If the callout appears after a user action, post a UIAccessibility.Notification.announcement with its text. Use liveRegion = LiveRegionMode.Polite when the callout mounts.
Tappable callout target Minimum 44 × 44 pt if the whole container is tappable. Minimum 48 × 48 dp same.
Dynamic type / font scaling Label and description both scale with Dynamic Type; don't hard-lock line-height to 16/20. Use sp units and respect fontScale.
Usage Guidelines

Do

Use Callout for soft, inline guidance — a flow hint, a policy reminder, a "this is what happens next" note.

Don't

Use Callout for page-level critical messages — reach for Alert when the severity warrants a dismissible banner.

Do

Pair intent colour with a leading icon. Every intent ships a default (info-circle, check-circle, warning-triangle, error-circle).

Don't

Rely on colour alone to communicate severity — fails WCAG 1.4.1 and breaks for colour-blind users.

Do

Put a single TextButton in the trailing action slot when the callout opens a sheet or links to docs.

Don't

Nest a full filled Button — it overweights the callout. If the call to action is primary, it belongs outside the callout.

Criteria Scorecard
ID Criterion Status Notes
C1 Layer Structure & Naming Requires Rework Component name "Contextual Help" is internal jargon. Rename to Callout. Inner layers are reasonable.
C2 Variant & Property Naming Requires Rework Redundant label + label size encode one concept; type is a 2-value stub of a 4-value intent.
C3 Token Coverage Ready All bg / border / label / description bound to main/contextual-help/color/*. Spacing uses space/*. Rename namespace alongside the component rename.
C4 Native Mappability Requires Rework No leading-icon slot, no trailing-action slot, no system primitive match on either platform — custom EBCallout with intent enum required.
C5 Interaction State Coverage Requires Rework No Pressed, Focused, or Disabled states. Tappable callouts and disabled-form contexts can't be expressed.
C6 Asset & Icon Quality Requires Rework No icons shipped today — Information variant carries intent via colour alone. Add vector Icon instances per intent.
C7 Code Connect Linkability Not Mapped Blocked by rename + property schema collapse + intent expansion + slot additions.
Code Connect
Aspect Status Notes
Component name Requires Rework Rename to Callout before Code Connect — otherwise the native file EBCallout.swift won't match the Figma name Contextual Help.
Property naming Requires Rework Collapse label+label size and expand type.
Slot inference Requires Rework Add #leading-icon and #trailing-action slots.
State coverage Requires Rework Add Pressed and Disabled states.
Native component file Not Mapped Planned: EBCallout.swift / EBCallout.kt.
Variants Inventory (8 total)

4 axes: Label (yes/no) × Label Size (small / default / no) × Description (yes/no) × Type (default / information). Cartesian is constrained — of the 24 combinations, only 8 are shipped as valid variants.

LabelLabel SizeDescriptionTypeNode IDDimensions
yessmallyesdefault23:179896336 × 98
yessmallyesinformation23:179899336 × 98
yesdefaultyesdefault23:179902336 × 102
yesdefaultyesinformation23:179905336 × 102
nonoyesdefault23:179908336 × 84
nonoyesinformation23:179910336 × 84
yesdefaultnodefault23:179912336 × 39
yesdefaultnoinformation23:179915336 × 39
1.0.0 — April 2026Major
Initial Assessment · node 23:179895 (source name "Contextual Help")
Component assessed — 8 variants documented across Label × Label Size × Description × Type. Source Figma name is "Contextual Help"; this assessment recommends renaming to "Callout". Documented
Initial
Rename Contextual Help → Callout — Adopt the industry-standard name used by Atlassian, GitHub, Notion, Stripe. Rename token namespace to main/callout/* and native files to EBCallout. Open
C1 Open
Redundant label axes — Collapse label + label size into a single labelSize: none | small | default enum. Three invalid Cartesian cells removed. Open
C2 Open
Expand type to 4-value intent — Replace type=default | information with intent: info | success | warning | error. Adds token groups for success / warning / error. Open
C2 Open
Add leading-icon slot — Every intent ships a default icon (info-circle, check-circle, warning-triangle, error-circle). Closes the colour-only accessibility gap. Open
C4 Open
Add trailing action slot — Figma Slot for a single TextButton or dismiss X. Consumers instance-swap into the slot. Open
C4 Open
Add Pressed and Disabled states — Pressed for tappable callouts; Disabled to mirror parent form disabled context. Open
C5 Open
No icons shipped — Information variant signals intent via colour alone. Add DS Icon library instances per intent. Open
C6 Open
Code Connect mappings — Not registered. Blocked by rename + property collapse + intent expansion + slot additions. Open
C7 Open