Adaptive Cards Mobile SDK - Implementation Plan

March 15, 2026 · View on GitHub

Last Updated: March 14, 2026 Target Schema: Adaptive Cards v1.6 Reference: Web/Desktop Parity Analysis

Project Overview

This document tracks the implementation progress across all phases of the Adaptive Cards Mobile SDK. For detailed property-level gap analysis against the web/desktop SDK, see WEB_DESKTOP_PARITY_ANALYSIS.md.


Phase 1: Templating Engine — 100% ✅

Status: Complete

Both iOS (ACTemplating) and Android (ac-templating) have full feature parity:

  • Complete AST-based expression parsing with type-safe evaluation
  • 60+ built-in functions across 5 categories (String, Math, Logic, Date, Collection)
  • Full template expansion with ${...} syntax, $when conditionals, $data iteration
  • Nested data contexts with $root, $data, $index
  • 40+ iOS tests, 50+ Android tests

Phase 2: Advanced Elements + Markdown + Fluent Theming — 100% ✅

Status: Complete

ItemiOSAndroidTestsNotes
2A. Markdown Rendering✅ ACMarkdown✅ ac-markdownCommonMark subset: bold, italic, links, lists, inline code, headings, blockquotes
2B. ListView Element✅ ListItemView✅ ListItemViewOrdered/unordered lists with markers, nested support
2C. DataGridInput✅ DataGridInputView✅ DataGridInputViewEditable columns, rows, sorting
2D. CompoundButton✅ CompoundButtonView✅ CompoundButtonViewTitle, description, icon, badge (v1.6)
2E. Charts✅ ACCharts (4 types)✅ ac-charts (4 types)Donut, Bar, Line, Pie with accessibility
2F. Fluent UI Theming✅ ACFluentUI✅ ac-fluent-uiFluentTheme, color tokens, HostConfig integration
2G. Schema Validation✅ SchemaValidator✅ SchemaValidatorv1.6 schema validation, structured errors
2H. Model Updates✅ targetWidth✅ targetWidthResponsive layout (narrow/standard/wide), themed URLs

Phase 3: Advanced Actions + Copilot Extensions + Teams — 100% ✅

Status: Complete

ItemiOSAndroidTestsNotes
3A. Action.Popover✅ .sheet()✅ ModalBottomSheetTitle, body elements, dismiss behavior
3A. Action.RunCommandsCommand dispatch to host
3A. Action.OpenUrlDialogURL in dialog with title
3B. Menu Actions / Overflow✅ SwiftUI Menu✅ Compose DropdownMenuPrimary/secondary mode, maxActions overflow
3C. Copilot Extensions✅ ACCopilotExtensions✅ ac-copilot-extensionsCitationView, StreamingCardView
3D. Teams Integration✅ ACTeams✅ ac-teamsTeamsCardHost, deep links, theming

Phase 4: Sample Apps — 100% ✅

Status: Complete

PlatformStatusFeatures
iOS (AC Visualizer)Card gallery, deep link navigation (adaptivecards://card/...), category browsing, card rendering with all element types
Android (AC Visualizer)Card gallery, deep link navigation, category browsing, card rendering with all element types

Both apps support:

  • Deep link navigation for automated testing
  • 43+ shared test cards across all categories
  • Teams Official Samples rendering
  • Template card rendering with data binding

Phase 5: Production Readiness — 40% 🚧

Status: Partially complete

ItemStatusNotes
5A. Visual Regression Tests🚧 ScaffoldingiOS: swift-snapshot-testing scaffolding + 10 baseline tests; Android: Paparazzi scaffolding. Not fully integrated into CI
5B. CI/CD Hardening⚠️ PartialWorkflows exist (parity-gate, ios-tests, android-tests, lint, validate-test-cards). Missing: snapshot test jobs, build matrix for multiple OS versions
5C. SDK Publishing❌ Not startediOS: Package.swift products defined but no version tagging/release workflow. Android: no maven-publish plugin or POM metadata
5D. API Documentation❌ Not startedNo DocC catalog (iOS) or Dokka generation (Android). Public APIs have doc comments but no generated docs
5E. Performance Benchmarks❌ Not startedNo formal benchmark suites. PerformanceGuardrails exist (parse <5ms, template <10ms, render <16ms budgets) but no automated benchmarks
5F. CHANGELOG❌ Not startedNo CHANGELOG.md
5G. MIGRATION Guide✅ DoneMIGRATION.md in repo root
5H. README✅ DoneComprehensive README with architecture, build instructions, demo

Phase 6: Web/Desktop Spec Parity Gaps — 100% ✅

Status: Complete

These are features that were present in the official Adaptive Cards spec (adaptivecards.io) and the web/desktop SDK that were missing or incomplete in the mobile SDK. All have been implemented.

P0 — Functional Gaps

ItemiOSAndroidEffortDescription
6A. fallback + requires mechanismMediumFeatureFlags.meetsRequirements() evaluates element requires against host capabilities; rendering pipeline renders fallback element or drops. .unknown elements also render their fallback.
6B. Data.Query (dynamic typeahead)MediumDataQuery model, DataQueryProvider protocol/interface, choicesData on ChoiceSetInput/InputChoiceSet. Host implements provider for search-as-you-type.
6C. CaptionSource on MediaSmallCaptionSource model (mimeType, url, label) added to Media on both platforms.

P1 — Property Rendering Gaps

ItemiOSAndroidEffortDescription
6D. TextBlock.style (heading/columnHeader)Smallheading renders with large+bold, columnHeader with default+bold. Accessibility header trait added. columnHeader case added to TextBlockStyle enum.
6E. BackgroundImage repeat modesMediumiOS uses .resizable(resizingMode: .tile). Android uses Canvas with painter tiling. repeat, repeatHorizontally, repeatVertically all work.
6F. Input labelPosition/labelWidthSmalllabelPosition ("inline"/"above") and labelWidth (string or number) added to all 6 input types on both platforms. Flexible decoder handles both string and numeric labelWidth.
6G. Refresh auto-refresh logicMediumonRefreshNeeded callback on AdaptiveCardView. Timer fires at refresh.expires timestamp. iOS uses .task(id:), Android uses LaunchedEffect + delay().

P2 — Low Priority / Host Responsibility

ItemStatusNotes
Authentication flowModel onlyCorrectly deferred to host app
speak (SSML)Model onlyHost responsibility per spec
langModel onlyCould enhance date formatting; minimal impact
Input.inputStyle (revealOnHover)N/ANo hover on mobile — can skip

Phase 7: Desktop R4 Parity — 100% ✅

Status: Complete — identified via WorkIQ research on David Claux's desktop AC team (March 2026), implemented March 14, 2026

These are features shipped or in-progress on the desktop/web renderer (R4 release) that were parity gaps with the mobile SDK. All have been implemented.

Desktop R4 Feature Gaps

ItemiOSAndroidEffortDescription
7A. Scrollable ContainersMediummaxHeight + overflow (scroll/hidden/visible) on Container, Column, TableCell. iOS: OverflowModifier with ScrollView/.clipped(). Android: verticalScroll/clipToBounds.
7B. Popover Drawer ResizingSmallContent-measured detents capped at 80% screen height. iOS: GeometryReaderpresentationDetents. Android: skipPartiallyExpanded=false + wrapContentHeight() + heightIn(max=80%).
7C. Streaming Fade-in AnimationSmallFade-in via .transition(.opacity) (iOS) / AnimatedVisibility(fadeIn) (Android). Composable-lambda elementRenderer for full element rendering without circular module dependency.
7D. Card Diagnostics OverlayMediumDiagnosticsOverlayView (iOS) / DiagnosticsOverlay (Android) — floating badge + expandable panel. Enabled via CardConfiguration.diagnosticsEnabled.

7A. Scrollable Containers — Engineering Detail

Problem: Desktop containers support maxHeight with vertical scrollbar. Mobile containers only support minHeight, never scroll.

Model changes — Add to Container, Column, TableCell on both platforms:

  • maxHeight: String? (e.g. "200px") — parsed same as existing minHeight
  • overflow: Overflow? — new enum: visible (default), hidden, scroll

Files:

  • iOS model: ios/Sources/ACCore/Models/ContainerTypes.swift + Enums.swift
  • Android model: android/ac-core/.../models/CardElement.kt
  • iOS rendering: ios/Sources/ACRendering/Views/ContainerView.swift
    • overflow == .scrollScrollView(.vertical, showsIndicators: true) { content }.frame(maxHeight: maxH)
    • overflow == .hiddencontent.frame(maxHeight: maxH).clipped()
  • Android rendering: android/ac-rendering/.../composables/ContainerView.kt
    • Overflow.ScrollBox(Modifier.heightIn(max = maxHeight)) { Column(Modifier.verticalScroll(rememberScrollState())) { items } }
    • Overflow.HiddenBox(Modifier.heightIn(max = maxHeight).clipToBounds()) { items }
  • Accessibility: accessibilityScrollView (iOS) / scroll semantics (Android)
  • Test card: NEW shared/test-cards/element-samples/container-scrollable.json

7B. Popover Drawer Resizing — Engineering Detail

Problem: iOS always .presentationDetents([.large]). Android skipPartiallyExpanded = true. Desktop: resize to content with max height.

No model changes — rendering only.

Files:

  • iOS: ios/Sources/ACRendering/Views/PopoverContentView.swift
    • Replace .presentationDetents([.large]) with content-measured detent
    • @State private var contentHeight: CGFloat = 0
    • Measure via GeometryReader on content → .presentationDetents([.height(min(contentHeight + 80, screenHeight * 0.8)), .large])
    • Add .presentationContentInteraction(.scrolls) for tall content
  • Android: PopoverBottomSheet in android/ac-rendering/.../composables/ActionSetView.kt
    • Change skipPartiallyExpanded = truefalse
    • Add Modifier.wrapContentHeight() to content Column
    • Cap height: .heightIn(max = (screenHeightDp * 0.8f).dp)

7C. Streaming Fade-in Animation — Engineering Detail

Problem: StreamingCardView is a stub on both platforms — shows placeholder text instead of actual rendered elements. Desktop has fade-in animation.

No model changes — rendering only.

Files:

  • iOS: ios/Sources/ACCopilotExtensions/StreamingCardView.swift
    • Replace stub Text("Element: ...") with ElementView(element:hostConfig:)
    • Add .transition(.opacity.animation(.easeIn(duration: 0.3))) per element
    • Animate on partialContent.count changes
  • Android: android/ac-copilot-extensions/.../StreamingCardView.kt
    • Replace stub with RenderElement(element = element, ...)
    • Wrap in AnimatedVisibility(visible = true, enter = fadeIn(tween(300)))
  • Test card: Existing shared/test-cards/streaming-card.json

7D. Card Diagnostics Overlay — Engineering Detail

Problem: Desktop has Ctrl+Alt+Shift+double-click diagnostic tool. Mobile has CardPerformanceMetrics + CardLifecycleEvent callbacks but no visual inspector.

Model changes: Add diagnosticsEnabled: Bool = false to CardConfiguration on both platforms.

Files:

  • iOS: NEW ios/Sources/ACRendering/Views/DiagnosticsOverlayView.swift
    • Floating badge (element count + render time) → expandable panel
    • 4 tabs: Performance (all CardPerformanceMetrics fields), Elements (hierarchical tree), JSON (pretty-printed), Errors (unknownElementTypes, failedImageUrls)
    • Show as .overlay(alignment: .topTrailing) on AdaptiveCardView when configuration.diagnosticsEnabled
    • Modify AdaptiveCardView.swift and CardConfiguration.swift
  • Android: NEW android/ac-rendering/.../composables/DiagnosticsOverlay.kt
    • Same pattern using Box overlay
    • Modify AdaptiveCardView.kt and CardConfiguration.kt

Mobile Ahead of Desktop

These elements are already implemented on mobile but still in development on desktop:

ElementMobile StatusDesktop Status
ProgressBar✅ ShippedIn development
ProgressRing/Spinner✅ ShippedIn development
Badge✅ Shipped (CompoundButton)Canary
Carousel✅ ShippedCanary

Test Card Coverage

GapExisting Test CardNeeds New Card
7A. Scrollable ContainersYes — element-samples/container-scrollable.json
7B. Popover Resizing❌ (use existing popover cards)Optional — tall-content popover card
7C. Streaming Animationstreaming-card.jsonNo
7D. DiagnosticsN/AAny card works

Files Changed Summary

GapiOS FilesAndroid FilesNew Files
7A (Scrollable)ContainerTypes.swift, Enums.swift, ContainerView.swiftCardElement.kt, ContainerView.kt
7B (Popover)PopoverContentView.swiftActionSetView.kt
7C (Streaming)StreamingCardView.swiftStreamingCardView.kt
7D (Diagnostics)CardConfiguration.swift, AdaptiveCardView.swiftCardConfiguration.kt, AdaptiveCardView.ktDiagnosticsOverlayView.swift, DiagnosticsOverlay.kt

Implementation Sequence

PhaseGapsEst. Hours
P7.1: Desktop layout features7A (Scrollable), 7B (Popover)6-9h
P7.2: Streaming + tooling7C (Streaming), 7D (Diagnostics)9-12h

API impact: All changes additive — new optional properties with nil/false defaults. No breaking changes. Hosts opt-in to new features (e.g., diagnosticsEnabled).


Overall Completion Summary

PhaseStatusCompletion
Phase 1: Templating Engine✅ Complete100%
Phase 2: Advanced Elements + Markdown + Theming✅ Complete100%
Phase 3: Advanced Actions + Copilot + Teams✅ Complete100%
Phase 4: Sample Apps✅ Complete100%
Phase 5: Production Readiness🚧 In Progress45%
Phase 6: Web/Desktop Spec Parity Gaps✅ Complete100%
Phase 7: Desktop R4 Parity✅ Complete100%

Overall Feature Completeness vs Official Spec: ~99% (property-level, verified in source code) Overall Feature Completeness vs Teams Extended Spec: ~99% (mobile has additional Teams/Copilot extensions) Overall Feature Completeness vs Desktop R4: ~99% (all 4 desktop R4 gaps closed — scrollable containers, popover resizing, streaming animation, diagnostics)


Remaining Effort Estimate

PhaseEstimated Hours
Phase 5 remaining (publishing, docs, benchmarks, changelog)15-20 hours
Phase 7A: Scrollable Containers4-6 hours
Phase 7B: Popover Drawer Resizing2-3 hours
Phase 7C: Streaming Fade-in Animation3-4 hours
Phase 7D: Card Diagnostics Overlay6-8 hours
Total remaining15-20 hours (Phase 5 only)

Success Criteria

Functional Requirements

  • Templating works with all expression types
  • All 43+ test cards render correctly on both platforms
  • 100% cross-platform naming consistency
  • Full accessibility compliance (WCAG 2.1 AA)
  • Responsive design on phone and tablet
  • fallback + requires mechanism working
  • Data.Query dynamic typeahead working
  • Scrollable containers (Desktop R4 parity)
  • Streaming fade-in animation (Desktop R4 parity)
  • Popover drawer resizing (Desktop R4 parity)
  • Card diagnostics overlay (Desktop R4 parity)

Quality Requirements

  • Graceful error handling (never crash on malformed JSON)
  • <16ms render time for all cards (guardrails exist, benchmarks not automated)
  • 80%+ code coverage (tests exist, coverage reporting not in CI)
  • All public APIs documented (DocC/Dokka)

Publishing Requirements

  • iOS Package.swift ready for SPM (products defined)
  • Android modules ready for Maven Central
  • Generated API documentation
  • Migration guide from legacy SDK
  • Sample apps demonstrating features

Risk Mitigation

Technical Risks

  • fallback mechanism complexity: RESOLVED — implemented and working on both platforms
  • Data.Query host integration: RESOLVED — DataQueryProvider protocol/interface implemented
  • Scrollable containers: RESOLVED — OverflowModifier wraps nested ScrollView cleanly; tested on both platforms
  • Popover resizing: RESOLVED — GeometryReader uses onAppear (not continuous); availability-checked presentationContentInteraction with fallback modifier
  • Streaming animation: RESOLVED — used composable-lambda elementRenderer pattern to avoid circular module dependency (ACCopilotExtensions → ACRendering)
  • SwiftUI/Compose compatibility: Tested on iOS 16+ and Android API 26+

Schedule Risks

  • Phase 5 publishing: Maven Central publishing has bureaucratic steps (Sonatype account, GPG signing)
  • DocC/Dokka generation: First-time setup can be time-consuming

Quality Risks

  • Accessibility: Tested with VoiceOver/TalkBack throughout development
  • Error handling: Never crash on malformed JSON — validated across 43+ test cards
  • Thread safety: Parsing on background threads, UI on main thread (verified)