Skip to content

Input Agnostic Player and Native A2UI Support - #866

Merged
KetanReddy merged 43 commits into
mainfrom
feture/a2ui
Jul 17, 2026
Merged

Input Agnostic Player and Native A2UI Support#866
KetanReddy merged 43 commits into
mainfrom
feture/a2ui

Conversation

@KetanReddy

@KetanReddy KetanReddy commented May 12, 2026

Copy link
Copy Markdown
Member

What and Why

With the emergence of A2UI and other agent-driven standards, Player — in its mission to serve the broader SDUI space — should expand support for more formats beyond its own in order to broaden the scope of what Player solves for. Furthermore, this lets capabilities be built against Player itself, regardless of input format, allowing for the decoupling of implementation from the server driving it.

This PR adds the generic "unknown format" entrypoint to every platform (web, JVM, Android, iOS) and ships A2UI as the first non-Player format end-to-end.

Core Player Changes

  • New transformContent bail hook on Player's hooks. Fires at the top of start(), after plugins are registered and before resolveFlowContent. Plugins inspect a ContentMeta { format, version } and either convert the payload or pass it through.
  • Player.start() signature widened from (payload: Flow) to (payload: unknown, options?: StartOptions). Default format is "player", which preserves existing behavior (a plain Flow flows through untouched). version is free-form, so a single format plugin can dispatch across versions.

Platform Entrypoints

The hook and signature widening live in the core JS bundle every platform loads; each platform entrypoint forwards the format/version through. Default "player" keeps all existing call sites untouched.

  • ReactReactPlayer.start() mirrors the same signature (react/player/src/player.tsx) and forwards options to the underlying Player.start().
  • JVMPlayer.start() gains start(flow: String, format: String, version: String? = null) (plus a matching URL overload). HeadlessPlayer implements it and forwards { format, version } to the JS player.start(payload, options) as a bridge-encoded Map.
  • AndroidAndroidPlayer.start(flow, format, version) delegates to the wrapped HeadlessPlayer.
  • iOS — new StartOptions { format, version } value type; HeadlessPlayer.start(flow:options:completion:) appends the options object to the JS start args ([String: Any] → JS object via JavaScriptCore). Threaded through SwiftUIPlayer.init / Context.load / ManagedPlayer via a defaulted startOptions: param (source-compatible). Use StartOptions.a2ui.

Plugins

Core: @player-ui/a2ui-plugin

Includes three sub-plugins:

  • A2UIContentPlugin: Only activates when meta.format === "a2ui". Calls adaptA2UIToFlow(snapshot) to transform content.
  • A2UITransformPlugin: Per-asset transforms (Button/TextField/CheckBox/Slider/DateTimeInput/ChoicePicker/Text) that attach run()/set()/value helpers consumed by the rendering layer.
  • A2UIExpressionsPlugin: Registers the A2UI v0.9.1 standard library: validation (required, regex, length, numeric, email), formatters (formatString, formatNumber, formatCurrency, formatDate, pluralize), openUrl, and logic (and/or/not).

This package emits a native JS bundle (A2UIPlugin.native.js), which the JVM and iOS wrappers below load directly — so the adapter, transforms, and expression std-lib are shared across all platforms with zero reimplementation.

Adapter Logic

Walks the flat components[] list from id: "root", inlines child references into a nested asset tree matching Player's {asset: ...} shape, and produces a Flow with a single VIEW state plus one END per unique event name encountered. Translation rules:

  • {path: "/x/y"}"x.y" (Player binding)
  • formatString(...)"Hello, {{x.y}}!" template
  • Other {call, args}@[fn(...)]@ expression
  • checks: [...] on inputs → lifted into a synthesized Flow.schema via synthesizeSchema so Player's existing SchemaController/ValidationController pick them up unchanged
  • Templated children: {path, componentId} blocks become indexed paths scoped to <scope>._index_
  • Cycle detection throws on non-tree component graphs

Platform Renders

The A2UI v0.9.1 reference catalog — 16 assets — implemented per platform: Row, Column, List, Text, Image, Icon, Divider, Card, Modal, Tabs, Button, TextField, CheckBox, Slider, DateTimeInput, ChoicePicker. Asset type strings are PascalCase to match the adapter output; transformed assets consume the shared run()/set()/currentValue helpers.

  • React: @player-ui/a2ui-plugin-react — the full catalog as React components.
  • Android: plugins/a2ui/androidA2UIPlugin : AndroidPlayerPlugin, JSPluginWrapper by <jvm wrapper> registering the catalog as Jetpack Compose renderers. Function helpers decode as Kotlin function types.
  • iOS: plugins/a2ui/swiftuiA2UIPlugin : JSBasePlugin, NativePlugin that loads the bundle and registers the catalog as SwiftUI renderers. Function helpers decode as Swift WrappedFunctions.
  • JVM: plugins/a2ui/jvm — generated Kotlin JSPluginWrapper (A2UIPlugin) that loads the A2UI JS bundle (mirrors reference-assets/jvm). Headless-capable, no UI layer.

Packages

A new folder in the repo! The goal for this folder is to ship preconfigured Player entrypoints so consumers don't have to assemble plugins themselves. The plugins/ directory exports building blocks; packages/ exports ready-to-use Players for specific content formats.

Each preset comes with the A2UI plugin pre-added and appends any consumer-supplied plugins after it. Since HeadlessPlayer/AndroidPlayer are final, the JVM/Android entries are idiomatic factory functions; iOS is a thin View wrapper that also defaults startOptions: .a2ui.

React: @player-ui/a2ui

import { A2UIReactPlayer } from "@player-ui/a2ui";

JVM: packages/a2ui/jvm

val player = A2UIHeadlessPlayer()
player.start(snapshot, "a2ui")

Android: packages/a2ui/android

val player = A2UIAndroidPlayer()
player.start(snapshot, "a2ui")

iOS: packages/a2ui/swiftui

A2UISwiftUIPlayer(flow: snapshot, result: $result)

Mocks

The canonical catalog is plugins/a2ui/mocks (21 snapshots). JS consumes it via @player-ui/a2ui-plugin-mocks; JVM/Android via //tools/mocks:jar. iOS mirrors the full set as faithful inline copies (the existing iOS demo/test convention, there is no runtime mechanism to read the canonical JSON on iOS today).

Storybook

New A2UI stories with one story per asset, driven by a createA2UIStory helper in the Player storybook extension that can render A2UI content.

Demo Apps

  • iOS — an "A2UI" screen renders the full canonical snapshot catalog, each started with .a2ui.
  • Android — the demo PlayerViewModel registers A2UIPlugin alongside the reference assets (disjoint type namespaces).

Notes

  • Android Image/Icon (no Coil / material-icons-core only) and iOS Image (deployment target iOS 14 predates AsyncImage) render labelled placeholders; iOS Icon uses SF Symbols.

To Align On

Overall Approach

  • Do we want to have this switch inside of Player or do we want to offer two exports from core, one per input format, to minimize bundle size

Change Type (required)

Indicate the type of change your pull request is:

  • patch
  • minor
  • major
  • N/A

Does your PR have any documentation updates?

  • Updated docs
  • No Update needed
  • Unable to update docs

Release Notes

TBD

📦 Published PR as canary version: 1.1.0--canary.866.38904

Try this version out locally by upgrading relevant packages to 1.1.0--canary.866.38904

@KetanReddy KetanReddy added the minor Increment the minor version when merged label May 12, 2026
@KetanReddy

Copy link
Copy Markdown
Member Author

/docs

@codecov

codecov Bot commented May 12, 2026

Copy link
Copy Markdown

Bundle Report

Changes will increase total bundle size by 676.24kB (13.07%) ⬆️⚠️, exceeding the configured threshold of 5%.

Bundle name Size Change
tools/storybook 114.01kB 1.89kB (1.69%) ⬆️
plugins/check-path/core 443.96kB 934 bytes (0.21%) ⬆️
plugins/async-node/core 505.62kB 934 bytes (0.19%) ⬆️
plugins/markdown/core 684.64kB 944 bytes (0.14%) ⬆️
plugins/reference-assets/core 556.26kB 934 bytes (0.17%) ⬆️
plugins/beacon/core 425.56kB 934 bytes (0.22%) ⬆️
react/player 85.26kB 888 bytes (1.05%) ⬆️
plugins/metrics/core 462.12kB 934 bytes (0.2%) ⬆️
core/player 1.02MB 2.51kB (0.25%) ⬆️
plugins/external-state/core 428.23kB 934 bytes (0.22%) ⬆️
plugins/a2ui/react 88.36kB 88.36kB (100%) ⬆️⚠️
plugins/a2ui/core 572.92kB 572.92kB (100%) ⬆️⚠️
packages/a2ui/react 3.13kB 3.13kB (100%) ⬆️⚠️

Affected Assets, Files, and Routes:

view changes for bundle: plugins/check-path/core

Assets Changed:

Asset Name Size Change Total Size Change (%)
CheckPathPlugin.native.js 934 bytes 414.48kB 0.23%
view changes for bundle: plugins/async-node/core

Assets Changed:

Asset Name Size Change Total Size Change (%)
AsyncNodePlugin.native.js 934 bytes 442.99kB 0.21%
view changes for bundle: plugins/markdown/core

Assets Changed:

Asset Name Size Change Total Size Change (%)
MarkdownPlugin.native.js 944 bytes 659.48kB 0.14%
view changes for bundle: tools/storybook

Assets Changed:

Asset Name Size Change Total Size Change (%)
index.js 993 bytes 58.84kB 1.72%
index.mjs 898 bytes 55.17kB 1.65%
view changes for bundle: plugins/metrics/core

Assets Changed:

Asset Name Size Change Total Size Change (%)
MetricsPlugin.native.js 934 bytes 429.78kB 0.22%
view changes for bundle: core/player

Assets Changed:

Asset Name Size Change Total Size Change (%)
Player.native.js 934 bytes 427.7kB 0.22%
cjs/index.cjs 517 bytes 202.97kB 0.26%
index.legacy-esm.js 529 bytes 196.26kB 0.27%
index.mjs 529 bytes 196.26kB 0.27%
view changes for bundle: plugins/beacon/core

Assets Changed:

Asset Name Size Change Total Size Change (%)
BeaconPlugin.native.js 934 bytes 411.1kB 0.23%
view changes for bundle: plugins/external-state/core

Assets Changed:

Asset Name Size Change Total Size Change (%)
ExternalStatePlugin.native.js 934 bytes 409.26kB 0.23%
view changes for bundle: react/player

Assets Changed:

Asset Name Size Change Total Size Change (%)
cjs/index.cjs 296 bytes 30.87kB 0.97%
index.legacy-esm.js 296 bytes 27.2kB 1.1%
index.mjs 296 bytes 27.2kB 1.1%
view changes for bundle: plugins/reference-assets/core

Assets Changed:

Asset Name Size Change Total Size Change (%)
ReferenceAssetsPlugin.native.js 934 bytes 518.28kB 0.18%

intuit-svc added a commit to player-ui/player-ui.github.io that referenced this pull request May 12, 2026
@intuit-svc

Copy link
Copy Markdown
Contributor

Docs Preview

A preview of your PR docs was deployed by CircleCI #36492 on Tue, 12 May 2026 07:39:49 GMT

📖 Docs (View site)

@codecov

codecov Bot commented May 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 0.00%. Comparing base (233ef9f) to head (da62578).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@     Coverage Diff     @@
##   main   #866   +/-   ##
===========================
===========================

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@KetanReddy

Copy link
Copy Markdown
Member Author

/canary

intuit-svc added a commit to player-ui/player-ui.github.io that referenced this pull request May 12, 2026
@intuit-svc

intuit-svc commented May 12, 2026

Copy link
Copy Markdown
Contributor

Build Preview

Your PR was deployed by CircleCI #38904 on Thu, 09 Jul 2026 01:07:21 GMT with this version:

1.1.0--canary.866.38904

📖 Docs (View site)

@KetanReddy

Copy link
Copy Markdown
Member Author

/canary

intuit-svc added a commit to player-ui/player-ui.github.io that referenced this pull request May 22, 2026
@KetanReddy KetanReddy changed the title [WIP] Native A2UI Support Native A2UI Support May 22, 2026
@intuit-svc

intuit-svc commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results

Comparison against baseline from main. ⚠️ = regression (>10% slower), ✅ = improvement (>5% faster)

core/player ⚠️

Benchmark Current Baseline Change
core/player/src/binding/__tests__/parser.bench.ts > parser benchmarks > Resolving binding: foo.bar 642.36K ops/s 588.82K ops/s +9.1% ✅
core/player/src/binding/__tests__/parser.bench.ts > parser benchmarks > Resolving binding: foo.pets.1.name 432.37K ops/s 405.31K ops/s +6.7% ✅
core/player/src/binding/__tests__/parser.bench.ts > parser benchmarks > Resolving binding: foo.pets.01.name 376.93K ops/s 471.42K ops/s -20.0% ⚠️
core/player/src/binding/__tests__/parser.bench.ts > parser benchmarks > Resolving binding: foo.pets['01'].name 384.67K ops/s 470.61K ops/s -18.3% ⚠️
core/player/src/binding/__tests__/parser.bench.ts > parser benchmarks > Resolving binding: foo.pets[01].name 348.26K ops/s 445.26K ops/s -21.8% ⚠️
core/player/src/binding/__tests__/parser.bench.ts > parser benchmarks > Resolving binding: foo.pets[name = "frodo"].type 218.48K ops/s 243.29K ops/s -10.2% ⚠️
core/player/src/binding/__tests__/parser.bench.ts > parser benchmarks > Resolving binding: foo.pets["name" = "sprinkles"].type 187.90K ops/s 221.16K ops/s -15.0% ⚠️
core/player/src/binding/__tests__/parser.bench.ts > parser benchmarks > Resolving binding: foo.pets["isDog" = false].type 216.52K ops/s 295.56K ops/s -26.7% ⚠️
core/player/src/binding/__tests__/parser.bench.ts > parser benchmarks > Resolving binding: foo.pets["isDog" = true].type 224.13K ops/s 308.99K ops/s -27.5% ⚠️
core/player/src/binding/__tests__/parser.bench.ts > binding creation benchmarks > Resolving binding: foo.bar 419.89K ops/s 610.26K ops/s -31.2% ⚠️
core/player/src/binding/__tests__/parser.bench.ts > binding creation benchmarks > Resolving binding: foo.pets.1.name 312.43K ops/s 405.96K ops/s -23.0% ⚠️
core/player/src/binding/__tests__/parser.bench.ts > binding creation benchmarks > Resolving binding: foo.pets.01.name 239.24K ops/s 393.83K ops/s -39.3% ⚠️
core/player/src/binding/__tests__/parser.bench.ts > binding creation benchmarks > Resolving binding: foo.pets['01'].name 264.01K ops/s 341.83K ops/s -22.8% ⚠️
core/player/src/binding/__tests__/parser.bench.ts > binding creation benchmarks > Resolving binding: foo.pets[01].name 266.15K ops/s 314.81K ops/s -15.5% ⚠️
core/player/src/binding/__tests__/parser.bench.ts > binding creation benchmarks > Resolving binding: foo.pets[name = "frodo"].type 232.64K ops/s 234.36K ops/s -0.7%
core/player/src/binding/__tests__/parser.bench.ts > binding creation benchmarks > Resolving binding: foo.pets["name" = "sprinkles"].type 171.20K ops/s 189.09K ops/s -9.5%
core/player/src/binding/__tests__/parser.bench.ts > binding creation benchmarks > Resolving binding: foo.pets["isDog" = false].type 216.68K ops/s 240.22K ops/s -9.8%
core/player/src/binding/__tests__/parser.bench.ts > binding creation benchmarks > Resolving binding: foo.pets["isDog" = true].type 239.39K ops/s 246.26K ops/s -2.8%
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = 1 + 3 (sync) 426.02K ops/s 449.48K ops/s -5.2%
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = 1 + 3 (async) 305.90K ops/s 362.75K ops/s -15.7% ⚠️
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: conditional(true, true, false) (sync) 372.92K ops/s 439.45K ops/s -15.1% ⚠️
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: conditional(true, true, false) (async) 414.39K ops/s 308.90K ops/s +34.2% ✅
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = conditional({{bar}} > 0, true, false) (sync) 197.04K ops/s 171.19K ops/s +15.1% ✅
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = conditional({{bar}} > 0, true, false) (async) 175.58K ops/s 172.45K ops/s +1.8%
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = conditional(conditional(true = false, false, true), conditional(false = false, true, false), conditional(true = true, false, true)) (sync) 141.79K ops/s 154.78K ops/s -8.4%
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = conditional(conditional(true = false, false, true), conditional(false = false, true, false), conditional(true = true, false, true)) (async) 152.34K ops/s 106.34K ops/s +43.3% ✅
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = await(asyncTestFunction(1)) (sync) N/A N/A N/A
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = await(asyncTestFunction(1)) (async) 288.36K ops/s 243.43K ops/s +18.5% ✅
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = asyncTestFunction(1) (sync) 322.27K ops/s 227.29K ops/s +41.8% ✅
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = asyncTestFunction(1) (async) 207.69K ops/s 242.15K ops/s -14.2% ⚠️
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: asyncTestFunction(1) (sync) 815.81K ops/s 698.81K ops/s +16.7% ✅
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: asyncTestFunction(1) (async) 513.46K ops/s 532.75K ops/s -3.6%
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = conditional(!{{bar}} == false, await(asyncTestFunction(1)), false) (sync) 183.16K ops/s 168.02K ops/s +9.0% ✅
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = conditional(!{{bar}} == false, await(asyncTestFunction(1)), false) (async) 113.92K ops/s 153.84K ops/s -26.0% ⚠️
core/player/src/view/resolver/__tests__/index.bench.ts > resolver benchmarks > initial resolve 543.81 ops/s 556.80 ops/s -2.3%
core/player/src/view/resolver/__tests__/index.bench.ts > resolver benchmarks > Resolving from cache 13.51K ops/s 13.26K ops/s +1.8%
core/player/src/view/resolver/__tests__/index.bench.ts > resolver benchmarks > data changes 2.21K ops/s 2.33K ops/s -5.1%
core/player/src/view/resolver/__tests__/index.bench.ts > resolver benchmarks > data changes slow 587.28 ops/s 465.52 ops/s +26.2% ✅

plugins/async-node/core ⚠️

Benchmark Current Baseline Change
plugins/async-node/core/src/__tests__/index.bench.ts > async node benchmarks > Resolve Async Node 1 times 13.41K ops/s 13.42K ops/s -0.0%
plugins/async-node/core/src/__tests__/index.bench.ts > async node benchmarks > Resolve Async Node 5 times 13.27K ops/s 13.20K ops/s +0.5%
plugins/async-node/core/src/__tests__/index.bench.ts > async node benchmarks > Resolve Async Node 10 times 9.65K ops/s 9.64K ops/s +0.1%
plugins/async-node/core/src/__tests__/index.bench.ts > async node benchmarks > Resolve Async Node 50 times 2.82K ops/s 3.19K ops/s -11.5% ⚠️
plugins/async-node/core/src/__tests__/index.bench.ts > async node benchmarks > Resolve Async Node 100 times 1.66K ops/s 1.78K ops/s -6.8%
plugins/async-node/core/src/__tests__/transform.bench.ts > async transform benchmarks > Resolve Async Node 1 times 6.00K ops/s 6.13K ops/s -2.1%
plugins/async-node/core/src/__tests__/transform.bench.ts > async transform benchmarks > Resolve Async Node 5 times 7.16K ops/s 6.49K ops/s +10.4% ✅
plugins/async-node/core/src/__tests__/transform.bench.ts > async transform benchmarks > Resolve Async Node 10 times 5.86K ops/s 6.34K ops/s -7.5%
plugins/async-node/core/src/__tests__/transform.bench.ts > async transform benchmarks > Resolve Async Node 50 times 2.30K ops/s 2.60K ops/s -11.8% ⚠️
plugins/async-node/core/src/__tests__/transform.bench.ts > async transform benchmarks > Resolve Async Node 100 times 1.48K ops/s 1.60K ops/s -7.1%

react/player ⚠️

Benchmark Current Baseline Change
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Render asset nested in 1 ReactAssets 543.91 ops/s 631.66 ops/s -13.9% ⚠️
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Bubble errors nested in 1 ReactAssets 787.06 ops/s 1.12K ops/s -30.0% ⚠️
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Render asset nested in 5 ReactAssets 575.28 ops/s 634.01 ops/s -9.3%
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Bubble errors nested in 5 ReactAssets 867.34 ops/s 1.03K ops/s -16.1% ⚠️
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Render asset nested in 10 ReactAssets 504.97 ops/s 640.33 ops/s -21.1% ⚠️
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Bubble errors nested in 10 ReactAssets 707.88 ops/s 908.95 ops/s -22.1% ⚠️
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Render asset nested in 50 ReactAssets 413.47 ops/s 521.80 ops/s -20.8% ⚠️
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Bubble errors nested in 50 ReactAssets 211.57 ops/s 271.20 ops/s -22.0% ⚠️
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Render asset nested in 100 ReactAssets 328.12 ops/s 422.33 ops/s -22.3% ⚠️
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Bubble errors nested in 100 ReactAssets 89.75 ops/s 120.76 ops/s -25.7% ⚠️

Comment thread plugins/a2ui/core/src/a2ui/adapter.ts Outdated
JSPluginWrapper by Transforms() {
/** register the A2UI assets — type strings are PascalCase to match the adapter output */
override fun apply(androidPlayer: AndroidPlayer) {
androidPlayer.registerAsset("Row", ::Row)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need new assets for it? Is the purpose to give a meaningful demo? These look usable for reference assets too

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically yeah, so that there is an off the shelf way for you to use A2UI with Player. Most other renderers have similar OTS assets.

@OptIn(ExperimentalPlayerApi::class)
@JvmOverloads
@Suppress("ktlint:standard:function-naming")
public fun A2UIHeadlessPlayer(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm where is this going to get used, is there a config that says when to use this vs when to use regular HeadlessPlayer when creating an Android Player?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea here is to start offering more off the shelf configured versions of Player. With this, if you know you want to use A2UI with player you should just be able to start with this package and have something production grade.

Comment thread plugins/a2ui/swiftui/Sources/SwiftUI/A2UIIconAsset.swift Outdated
Comment thread plugins/a2ui/swiftui/Sources/SwiftUI/A2UIDividerAsset.swift Outdated
JunDangIntuit
JunDangIntuit previously approved these changes Jul 8, 2026
@KetanReddy

Copy link
Copy Markdown
Member Author

/canary

intuit-svc added a commit to player-ui/player-ui.github.io that referenced this pull request Jul 9, 2026
tmarmer
tmarmer previously approved these changes Jul 9, 2026
JunDangIntuit
JunDangIntuit previously approved these changes Jul 9, 2026
@KetanReddy
KetanReddy dismissed stale reviews from JunDangIntuit and tmarmer via b3c7f29 July 13, 2026 16:22
@brocollie08

brocollie08 commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

i'd be okay with this PR assuming 2 points

  1. The A2UIPlayer is the pattern we want to proceed with "packaged x-player"
  2. There's a plan going forward for asset organization (OOB A2UI assets vs reference assets)

@KetanReddy

KetanReddy commented Jul 13, 2026

Copy link
Copy Markdown
Member Author

i'd be okay with this PR assuming 2 points

1. The A2UIPlayer is the pattern we want to proceed with "packaged x-player"

2. There's a plan going forward for asset organization (OOB A2UI assets vs reference assets)

I'll leave it up to @player-ui/reviewers, does anyone feel strongly about another naming scheme? For the Assets, let me start a discussion post about it so we can figure out what we want to do.

https://github.com/orgs/player-ui/discussions/903

@KetanReddy
KetanReddy merged commit 234b749 into main Jul 17, 2026
20 checks passed
@KetanReddy
KetanReddy deleted the feture/a2ui branch July 17, 2026 17:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor Increment the minor version when merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants