기본·커스텀 컴포넌트
UI Runtime v2 node는 공통으로 type, 선택적 id, props, children,
visible_when을 가집니다. action은 명확한 탭 영역을 제공하는 surface, card, button,
chip에서만 허용됩니다. 구조·표시·입력 node에 action을 붙이면 Host, CLI, MCP 검증이 모두
거부하므로 버튼이나 탭 가능한 surface로 감싸세요. Host가 Material 3 widget으로 렌더링하며
플러그인은 Flutter widget이나 HTML을 전달하지 않습니다.
아래 모든 node는 현재 Android Host에서 지원됩니다. iOS·Desktop도 같은 JSON 계약을 재사용하도록 설계되어 있지만 Host 구현과 실기기 검증 전에는 지원 완료로 표시하지 않습니다. 플랫폼별 상태는 Android, iOS, Desktop 호환을 참고하세요.
레이아웃 컴포넌트
row의 stack_at은 01200이고, 0은 자동 세로 전환을 끕니다. 600입니다. grid의
min_item_width는 96expanded.flex는 1~24입니다.
Surface와 구조
surface가 Runtime v2의 커스텀 컴포넌트 경계입니다. 허용된 primitive와 Material token을 조합할
수 있지만 실행 코드, HTML, CSS, WebView, native view, 임의 shader는 넣을 수 없습니다. surface
props는 spacing, padding, margin, 크기 제약, alignment, 색상, border,
elevation, opacity, clip, enabled, tooltip, semantics로 제한됩니다.
{
"type": "surface",
"props": {
"padding": {"horizontal": 16, "vertical": 12},
"background_color": "primary_container",
"foreground_color": "on_primary_container",
"border_radius": 20
},
"children": [
{"type": "text", "props": {"text": "오늘 일정 3개", "style": "heading"}}
]
}
텍스트와 데이터 표시
image와 avatar는 source를 정확히 하나만 가집니다.
asset: package 안의assets/GIF/JPEG/PNG/WebP 경로url:{{data.<source>...}}또는 목록 안의{{item...}}전체 binding 하나
literal 외부 URL, data:, file:, javascript:는 사용할 수 없습니다. url binding에는 capability
결과의 이미지 URL만 넣습니다. 이 이미지를 쓰는 package는 Manifest permissions에 network를
요청해야 하며 활성 Instance에도 network grant가 있어야 합니다.
앱은 binding으로 해석한 URL을 직접 요청하지 않습니다. Host가 인증된 이미지 proxy를 통해 공개
HTTPS URL만 가져오며 DNS/IP SSRF 검사와 redirect 차단을 적용합니다. 응답은 PNG/JPEG/GIF/WebP 중
하나여야 하고 MIME type, magic byte, 실제 이미지 포맷이 일치해야 합니다. 최대 크기는 512 KiB,
가로·세로는 각각 4096 px 이하입니다. 정적 이미지는 1 frame, 애니메이션은 최대 128 frame이며
width × height × frame 수로 계산한 frame 합산 pixel이 16,000,000 이하이어야 합니다. 조건을
통과하지 못하면 해당 이미지에만 오류 fallback을 표시하며 다른 UI와 capability 결과는 유지합니다.
중요한 이미지에는 semantic_label을 쓰고 순수 장식 이미지는 exclude_semantics: true를 사용합니다.
Icon token
icon, App bar action, navigation item의 icon과 selected_icon은 아래 Host token만 사용합니다.
임의 Material icon 이름이나 code point는 허용하지 않습니다. 목록에 없는 값은 Host, CLI, MCP와 앱
schema parser가 거부하며 다른 아이콘으로 조용히 바꾸지 않습니다. 모든 token은 현재 Android
Host에서 같은 의미의 Material 3 아이콘으로 표시되고, iOS·Desktop Host도 이름과 의미를 그대로
유지해야 합니다.
호환 alias는 각각 arrow_forward, clock, settings와 같은 의미입니다. 새 화면은 의미가 더
명확한 기본 token을 우선 사용하되 기존 서명 package의 alias도 계속 렌더링됩니다. 아이콘만 있는
action에는 반드시 label, 일반 icon node에는 semantic_label을 함께 제공합니다.
행동과 입력
field, select, switch의 state_key는 initial_state에 먼저 선언해야 합니다. select options는
1~32개의 { "value": ..., "label": "..." } 객체입니다. 정적과 source 옵션을 둘 다 선언할 수
없습니다. required, 문자열 길이, 숫자 범위와 error_text는 Host form validation에
사용됩니다. enabled: false는 이유를 주변 문구로 설명할 때만 사용합니다.
action은 surface, card, button, chip, form, field, select, switch에만 붙일 수
있습니다. 입력 action 직전에 Host가 IME composition과 controller를 commit하며,
validate: true는 잘못된 form의 Tool·navigation 실행을 차단합니다.
반복과 데이터 시각화
반복 template 안에서는 {{item.title}}처럼 item binding을 사용합니다. 큰 목록을 한 번에 렌더링하지
말고 capability에서 페이지나 기간을 나눕니다.
공통 UX 프리셋
프리셋은 새 실행 타입이 아니라 검증된 primitive 조합입니다. 그래서 Preview와 Flutter Host가 같은 node를 렌더링하고 기존 플러그인도 별도 migration 없이 사용합니다.
목록·검색의 최소 tree:
{
"type": "column",
"props": {"spacing": 12},
"children": [
{"type": "field", "props": {"state_key": "query", "label": "검색", "placeholder": "검색어"}},
{
"type": "button",
"props": {"label": "찾기", "icon": "search"},
"action": {"type": "invoke", "capability": "com.example.search", "query": "{{state.query}}", "arguments": {}, "store": "results"}
},
{
"type": "list",
"props": {"source": "data.results.data.items", "empty_text": "검색 결과가 없어요.", "limit": 50},
"children": [
{"type": "card", "props": {"title": "{{item.title}}", "subtitle": "{{item.summary}}"}}
]
}
]
}
권한 요청, 연결 필요, 첫 loading, capability error와 retry는 플러그인이 비슷한 경고 카드를 다시
만들지 않고 Host 공통 상태를 사용합니다. Plugin 상세의 권한/Connection 화면으로 이동한 뒤 같은
route state와 persisted control을 복원합니다. 데이터가 정상적으로 비었을 때만 empty 또는
empty_text를 사용하며 오류를 빈 목록으로 숨기지 않습니다.
모든 프리셋은 light/dark, 320px 폭, tablet/desktop 폭, 큰 글자에서 확인합니다. node별 tooltip, semantic label, 최소 탭 영역과 색 이외의 상태 표시는 Host Material 3 규칙을 따릅니다.
A2UI Response catalog와의 관계
위 node는 Plugin Runtime을 구성하는 primitive입니다. AI가 직접 선택하는 Response catalog는
weather, world_clock, chart, image_gallery,
exchange_rate, article_list, article_card, file_result, image_preview, video_preview와 활성
Plugin이 등록한 plugin.<extension-id>로 구성됩니다. 최종 답변 모델은 같은 Registry Skill과 Native
Tool에서 출처(builtin/plugin), mode(provider/generated/result), 용도와 Schema를 확인합니다.
provider mode는 조회 조건만, generated mode는 답변에 근거한 표시 값만 전달하며 Host가 검증한 뒤
Runtime tree에 주입합니다. 특정 키워드만으로 Tool을 강제하지 않습니다.
구조화 표는 A2UI 전용 컴포넌트 대신 Markdown table을 사용합니다. 위 표의
Runtime table node는 플러그인 화면 호환성을 위한 primitive로 계속 지원합니다.
자세한 등록·fallback 규칙은 Response UI와 Agent Timeline을
참고하세요.
공통 크기·정렬·접근성 props
- 크기:
width,height,min_width,max_width,min_height,max_height - 여백:
padding,margin,spacing - 정렬:
alignment,main_axis_alignment,cross_axis_alignment,main_axis_size - 시각:
color,background_color,foreground_color,border_color,border_width,border_radius,elevation,opacity - 이미지:
aspect_ratio,fit - 접근성:
tooltip,semantic_label,exclude_semantics
텍스트 align의 실제 렌더 값은 start, end, left, right, center, justify입니다. 이전
UI v2 package가 사용한 다른 안전한 identifier도 호환을 위해 검증 단계에서는 수용하지만 Host는
기본 정렬로 처리합니다. 새 manifest에는 위 열거 값만 사용하세요.
크기와 색상 범위는 토큰과 반응형에 정리되어 있습니다.