@adia-ai/a2ui-corpus 0.6.34 → 0.6.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/catalog-a2ui_0_9.json +3699 -333
- package/catalog-a2ui_0_9_rules.txt +134 -4
- package/chunk-embeddings.json +1 -1
- package/package.json +1 -1
package/catalog-a2ui_0_9.json
CHANGED
|
@@ -2024,6 +2024,16 @@
|
|
|
2024
2024
|
"type": "string",
|
|
2025
2025
|
"default": ""
|
|
2026
2026
|
},
|
|
2027
|
+
"amount": {
|
|
2028
|
+
"description": "Dunning mode only — the unpaid amount as a decimal major-unit number (`24.50`, not minor units like `2450`). Formatted via `Intl.NumberFormat` using [currency] and [lang]. Ignored when [pattern] is not `dunning`.",
|
|
2029
|
+
"type": "number",
|
|
2030
|
+
"default": 0
|
|
2031
|
+
},
|
|
2032
|
+
"cardLast4": {
|
|
2033
|
+
"description": "Dunning mode only — last 4 digits of the declined card. Rendered as \"ending 4242\". Ignored when [pattern] is not `dunning`. Attribute spelling: `card-last4`.",
|
|
2034
|
+
"type": "string",
|
|
2035
|
+
"default": ""
|
|
2036
|
+
},
|
|
2027
2037
|
"closable": {
|
|
2028
2038
|
"description": "Whether a close button is displayed. Alias [dismissible] is also accepted (same semantics, different spelling — the corpus and many libraries use both; both map to the same state).",
|
|
2029
2039
|
"type": "boolean",
|
|
@@ -2032,16 +2042,47 @@
|
|
|
2032
2042
|
"component": {
|
|
2033
2043
|
"const": "Alert"
|
|
2034
2044
|
},
|
|
2045
|
+
"currency": {
|
|
2046
|
+
"description": "Dunning mode only — ISO 4217 currency code driving the `Intl.NumberFormat` style=\"currency\" rendering. Defaults to `USD`.",
|
|
2047
|
+
"type": "string",
|
|
2048
|
+
"default": "USD"
|
|
2049
|
+
},
|
|
2035
2050
|
"dismissible": {
|
|
2036
2051
|
"description": "Public alias for [closable] — same semantics. Both attributes render the close button. Use whichever spelling matches your authoring style.",
|
|
2037
2052
|
"type": "boolean",
|
|
2038
2053
|
"default": false
|
|
2039
2054
|
},
|
|
2055
|
+
"dueAt": {
|
|
2056
|
+
"description": "Dunning mode only — ISO 8601 due / failed-at timestamp. Formatted via `Intl.DateTimeFormat`. Ignored when [pattern] is not `dunning`. Attribute spelling: `due-at`.",
|
|
2057
|
+
"type": "string",
|
|
2058
|
+
"default": ""
|
|
2059
|
+
},
|
|
2040
2060
|
"icon": {
|
|
2041
2061
|
"description": "Icon identifier displayed before the message content",
|
|
2042
2062
|
"type": "string",
|
|
2043
2063
|
"default": ""
|
|
2044
2064
|
},
|
|
2065
|
+
"pattern": {
|
|
2066
|
+
"description": "Domain pattern mode. Default is empty (standard alert). Setting `pattern=\"dunning\"` switches to billing dunning render mode — stamps a formatted amount + due-date + decline-reason from props and re-dispatches descendant `[data-dunning-action]` button clicks as a unified `dunning-action` event. Spec: SPEC-006.",
|
|
2067
|
+
"type": "string",
|
|
2068
|
+
"enum": [
|
|
2069
|
+
"",
|
|
2070
|
+
"dunning"
|
|
2071
|
+
],
|
|
2072
|
+
"default": ""
|
|
2073
|
+
},
|
|
2074
|
+
"reason": {
|
|
2075
|
+
"description": "Dunning mode only — decline reason. Drives the leading icon (declined → `x-circle`, expired → `clock`, insufficient → `wallet`, network → `wifi-slash`). One of: `declined`, `expired`, `insufficient`, `network`, or empty.",
|
|
2076
|
+
"type": "string",
|
|
2077
|
+
"enum": [
|
|
2078
|
+
"",
|
|
2079
|
+
"declined",
|
|
2080
|
+
"expired",
|
|
2081
|
+
"insufficient",
|
|
2082
|
+
"network"
|
|
2083
|
+
],
|
|
2084
|
+
"default": ""
|
|
2085
|
+
},
|
|
2045
2086
|
"text": {
|
|
2046
2087
|
"description": "Single-line alert message. For two-line \"headline + body\" alerts, use [title] + [description] instead. For rich content (links, formatting), use the [slot=\"content\"] slot.",
|
|
2047
2088
|
"type": "string",
|
|
@@ -2067,12 +2108,26 @@
|
|
|
2067
2108
|
],
|
|
2068
2109
|
"unevaluatedProperties": false,
|
|
2069
2110
|
"x-adiaui": {
|
|
2070
|
-
"anti_patterns": [
|
|
2111
|
+
"anti_patterns": [
|
|
2112
|
+
{
|
|
2113
|
+
"fix": "<alert-ui pattern=\"dunning\" variant=\"danger\">",
|
|
2114
|
+
"why": "Dunning is always a failure surface; info mis-signals severity.",
|
|
2115
|
+
"wrong": "<alert-ui pattern=\"dunning\" variant=\"info\">"
|
|
2116
|
+
},
|
|
2117
|
+
{
|
|
2118
|
+
"fix": "<alert-ui pattern=\"dunning\" amount=\"24.50\" currency=\"USD\" due-at=\"2026-05-20\">",
|
|
2119
|
+
"why": "Amount baked into title defeats Intl formatting + telemetry.",
|
|
2120
|
+
"wrong": "<alert-ui pattern=\"dunning\" title=\"Payment failed $24.50\">"
|
|
2121
|
+
}
|
|
2122
|
+
],
|
|
2071
2123
|
"category": "container",
|
|
2072
2124
|
"composes": [],
|
|
2073
2125
|
"events": {
|
|
2074
2126
|
"close": {
|
|
2075
2127
|
"description": "Fired when the close button is clicked"
|
|
2128
|
+
},
|
|
2129
|
+
"dunning-action": {
|
|
2130
|
+
"description": "Dunning pattern only — fired when a descendant button with `[data-dunning-action]` is clicked. Detail shape `{ action, amount, currency, dueAt }`; the action string is the value of the `data-dunning-action` attribute (typically `\"update\"` or `\"retry\"`)."
|
|
2076
2131
|
}
|
|
2077
2132
|
},
|
|
2078
2133
|
"examples": [
|
|
@@ -2085,6 +2140,11 @@
|
|
|
2085
2140
|
"description": "Card with error alert and a retry button for error state display.",
|
|
2086
2141
|
"a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"Card\",\n \"children\": [\n \"sec\",\n \"ftr\"\n ]\n },\n {\n \"id\": \"sec\",\n \"component\": \"Section\",\n \"children\": [\n \"alert\"\n ]\n },\n {\n \"id\": \"alert\",\n \"component\": \"Alert\",\n \"variant\": \"error\",\n \"title\": \"Something went wrong\",\n \"description\": \"We encountered an error while loading the data. Please try again.\"\n },\n {\n \"id\": \"ftr\",\n \"component\": \"Footer\",\n \"children\": [\n \"retry\"\n ]\n },\n {\n \"id\": \"retry\",\n \"component\": \"Button\",\n \"text\": \"Retry\",\n \"icon\": \"refresh\",\n \"variant\": \"primary\"\n }\n]",
|
|
2087
2142
|
"name": "error-state"
|
|
2143
|
+
},
|
|
2144
|
+
{
|
|
2145
|
+
"description": "Billing dunning banner — declined card with retry + update-card actions (SPEC-006).",
|
|
2146
|
+
"a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"Alert\",\n \"pattern\": \"dunning\",\n \"variant\": \"danger\",\n \"amount\": 24.5,\n \"currency\": \"USD\",\n \"dueAt\": \"2026-05-20T00:00:00Z\",\n \"cardLast4\": \"4242\",\n \"reason\": \"declined\",\n \"children\": [\"btn-update\", \"btn-retry\"]\n },\n {\n \"id\": \"btn-update\",\n \"component\": \"Button\",\n \"text\": \"Update payment method\",\n \"variant\": \"primary\",\n \"slot\": \"actions\"\n },\n {\n \"id\": \"btn-retry\",\n \"component\": \"Button\",\n \"text\": \"Retry charge\",\n \"variant\": \"outline\",\n \"slot\": \"actions\"\n }\n]",
|
|
2147
|
+
"name": "dunning-payment-failed"
|
|
2088
2148
|
}
|
|
2089
2149
|
],
|
|
2090
2150
|
"keywords": [
|
|
@@ -2113,6 +2173,9 @@
|
|
|
2113
2173
|
"action": {
|
|
2114
2174
|
"description": "Optional trailing action button (e.g. \"Refresh\", \"Status page\"). Right-aligned in the flex layout. See system-banners pattern for examples."
|
|
2115
2175
|
},
|
|
2176
|
+
"actions": {
|
|
2177
|
+
"description": "Dunning pattern only — action button stack (typically two `<button-ui>` with `data-dunning-action=\"update\"` and `data-dunning-action=\"retry\"`). Sits below the formatted message in the col layout when `pattern=\"dunning\"`."
|
|
2178
|
+
},
|
|
2116
2179
|
"close": {
|
|
2117
2180
|
"description": "Close button. Stamped automatically when `closable` is set; the stamped element is `<button-ui slot=\"close\" icon=\"x\" variant=\"ghost\" size=\"sm\">`. Override by passing a custom `slot=\"close\"` button."
|
|
2118
2181
|
},
|
|
@@ -2886,6 +2949,285 @@
|
|
|
2886
2949
|
"version": 1
|
|
2887
2950
|
}
|
|
2888
2951
|
},
|
|
2952
|
+
"BillingOverview": {
|
|
2953
|
+
"title": "BillingOverview",
|
|
2954
|
+
"description": "Module-tier billing dashboard that stitches the seven Wave A+B\nbilling primitives into the canonical \"all-billing-on-one-page\"\nsurface — current plan + status header, a KPI strip (monthly\nspend · seats · next invoice), an optional dunning banner when the\naccount is past-due, a plan-picker section for in-app plan changes,\na payment-method-list section, and an invoice-history section.\n\nData-driven via the `account` property — an aggregate snapshot of\nthe customer's billing state ({plan, status, billingCycle,\ncurrentSpend, seats, nextInvoiceDate, paymentMethods[],\ninvoices[], dunning?}). The composite stamps a fixed five-region\nskeleton once on first connect — header · kpis · dunning ·\nplan-picker · payment-methods · invoice-history — then mutates\nper-region nodes via id-keyed in-place diff on every property\nchange. Children primitives (plan-picker, payment-method-list,\ninvoice-history, alert-ui) are stamped as composed tags; this\ncomposite owns the orchestration, not the row chrome.\n\nHigher-level account-action event surfaces consumer-actionable\nintents from descendant primitives. Children carrying\n[data-account-action=\"X\"] or descendant events\n(`plan-action`, `payment-action`, `invoice-action`, `dunning-action`)\nare normalised into a single `account-action` event with\n`detail.action` ∈ {change-plan, add-payment-method, pay-now,\ndownload-invoice, update-card, retry, custom}. The composite\ndoes NOT mutate the data source; consumers wire `account-action`\nagainst their billing backend.\n\nDisplay surface. Extends UIElement, not UIFormElement — child\nprimitives are individually form-bearing (plan-picker,\npayment-method-list) while the host is not.\n\nSpec: docs/specs/implementation-ready/SPEC-004-billing-overview.md.\n",
|
|
2955
|
+
"type": "object",
|
|
2956
|
+
"allOf": [
|
|
2957
|
+
{
|
|
2958
|
+
"$ref": "#/$defs/ComponentCommon"
|
|
2959
|
+
},
|
|
2960
|
+
{
|
|
2961
|
+
"$ref": "#/$defs/CatalogComponentCommon"
|
|
2962
|
+
}
|
|
2963
|
+
],
|
|
2964
|
+
"properties": {
|
|
2965
|
+
"account": {
|
|
2966
|
+
"description": "Aggregate billing snapshot — source of truth for the whole\ndashboard. Shape:\n {plan: {id, name, price, cycle, currency, status},\n status: \"active\" | \"trialing\" | \"past_due\" | \"canceled\" | \"paused\",\n billingCycle: \"month\" | \"year\",\n currentSpend: number,\n seats: {used: number, total: number},\n nextInvoiceDate: ISO 8601 date string,\n paymentMethods: [...], // forwarded to payment-method-list\n invoices: [...], // forwarded to invoice-history\n plans?: [...], // forwarded to plan-picker; omitted when planSection is \"hidden\"\n dunning?: {amount, currency, dueAt, cardLast4?, reason?}}\nNull + no `data-stream-src` renders the empty state.\n",
|
|
2967
|
+
"type": "object",
|
|
2968
|
+
"default": null
|
|
2969
|
+
},
|
|
2970
|
+
"component": {
|
|
2971
|
+
"const": "BillingOverview"
|
|
2972
|
+
},
|
|
2973
|
+
"currency": {
|
|
2974
|
+
"description": "Default ISO 4217 currency for all amount formatting. Overridable\nper-record (plan.currency, invoice.currency, etc.).\n",
|
|
2975
|
+
"type": "string",
|
|
2976
|
+
"default": "USD"
|
|
2977
|
+
},
|
|
2978
|
+
"data-stream-src": {
|
|
2979
|
+
"description": "Optional endpoint returning the full account snapshot. On\nsuccessful load, `account` is replaced and a `load` event fires;\non failure an `error` event fires.\n",
|
|
2980
|
+
"type": "string",
|
|
2981
|
+
"default": ""
|
|
2982
|
+
},
|
|
2983
|
+
"loading": {
|
|
2984
|
+
"description": "Renders skeleton placeholders in the header + KPI strip while\ndata is fetching. Sets aria-busy on the host. Forwarded to\nchild composites that accept [loading] (plan-picker,\npayment-method-list, invoice-history).\n",
|
|
2985
|
+
"$ref": "#/$defs/DynamicBoolean"
|
|
2986
|
+
},
|
|
2987
|
+
"locale": {
|
|
2988
|
+
"description": "Locale for Intl.NumberFormat (currency) and Intl.DateTimeFormat\n(dates). Defaults to document.documentElement.lang (or \"en-US\"\nwhen absent).\n",
|
|
2989
|
+
"type": "string",
|
|
2990
|
+
"default": ""
|
|
2991
|
+
},
|
|
2992
|
+
"variant": {
|
|
2993
|
+
"description": "Layout variant. `full` shows every section. `compact` collapses\nthe plan-picker section and renders only the KPI strip + payment\nmethods + invoice history (the canonical \"settings billing\"\nshape). `enterprise` hides plan-picker entirely (no self-serve\nplan changes) and keeps the rest.\n",
|
|
2994
|
+
"type": "string",
|
|
2995
|
+
"enum": [
|
|
2996
|
+
"full",
|
|
2997
|
+
"compact",
|
|
2998
|
+
"enterprise"
|
|
2999
|
+
],
|
|
3000
|
+
"default": "full"
|
|
3001
|
+
}
|
|
3002
|
+
},
|
|
3003
|
+
"required": [
|
|
3004
|
+
"component",
|
|
3005
|
+
"account"
|
|
3006
|
+
],
|
|
3007
|
+
"unevaluatedProperties": false,
|
|
3008
|
+
"x-adiaui": {
|
|
3009
|
+
"anti_patterns": [
|
|
3010
|
+
{
|
|
3011
|
+
"fix": "{\"component\": \"BillingOverview\", \"account\":\n {\"plan\": {\"id\":\"p_pro\",\"name\":\"Pro\",\"price\":48,\"cycle\":\"month\",\"currency\":\"USD\",\"status\":\"active\"},\n \"status\": \"active\",\n \"billingCycle\": \"month\",\n \"currentSpend\": 48,\n \"seats\": {\"used\": 4, \"total\": 10},\n \"nextInvoiceDate\": \"2026-06-01\",\n \"paymentMethods\": [...],\n \"invoices\": [...]}}\n",
|
|
3012
|
+
"why": "Missing the required `account` prop. The composite renders the\nempty state. A dashboard without data has nothing to show.\n",
|
|
3013
|
+
"wrong": "{\"component\": \"BillingOverview\"}\n"
|
|
3014
|
+
},
|
|
3015
|
+
{
|
|
3016
|
+
"fix": "Render the BillingOverview composite on its own route\n(typically `/settings/billing` or `/billing`).\n",
|
|
3017
|
+
"why": "The dashboard is a route, not a modal. Modal traps focus + clips\ncontent; the composite is designed for the full /billing page.\n",
|
|
3018
|
+
"wrong": "{\"component\": \"Modal\", \"children\":\n [{\"component\": \"BillingOverview\", \"account\": {...}}]}\n"
|
|
3019
|
+
},
|
|
3020
|
+
{
|
|
3021
|
+
"fix": "Provide a dunning object alongside the past_due status:\n<billing-overview-ui account='{\"status\":\"past_due\",\"dunning\":{\"amount\":48,\"currency\":\"USD\",\"dueAt\":\"2026-05-20\"}}'></billing-overview-ui>\n",
|
|
3022
|
+
"why": "Past-due status without an `account.dunning` payload. The\ncomposite cannot render the dunning banner (it needs amount +\ndue-at + currency to format the alert message).\n",
|
|
3023
|
+
"wrong": "<billing-overview-ui account='{\"status\":\"past_due\"}'></billing-overview-ui>\n"
|
|
3024
|
+
},
|
|
3025
|
+
{
|
|
3026
|
+
"fix": "Either pass `account.plans` OR set `variant=\"compact\"` to hide\nthe plan-picker section entirely.\n",
|
|
3027
|
+
"why": "`variant=full` requires `account.plans` so the plan-picker\nsection has rows to render. Without plans, the section renders\nits own empty-state and looks broken.\n",
|
|
3028
|
+
"wrong": "<billing-overview-ui variant=\"full\" account='{\"plan\":{...},\"status\":\"active\"}'></billing-overview-ui>\n"
|
|
3029
|
+
}
|
|
3030
|
+
],
|
|
3031
|
+
"category": "container",
|
|
3032
|
+
"composes": [
|
|
3033
|
+
"card-ui",
|
|
3034
|
+
"stat-ui",
|
|
3035
|
+
"tag-ui",
|
|
3036
|
+
"text-ui",
|
|
3037
|
+
"alert-ui",
|
|
3038
|
+
"plan-picker-ui",
|
|
3039
|
+
"payment-method-list-ui",
|
|
3040
|
+
"invoice-history-ui",
|
|
3041
|
+
"button-ui",
|
|
3042
|
+
"icon-ui"
|
|
3043
|
+
],
|
|
3044
|
+
"events": {
|
|
3045
|
+
"account-action": {
|
|
3046
|
+
"description": "Unified account-action event — normalises every actionable\nintent from descendant primitives into a single bubbling event.\nHandler can act on `detail.action` without subscribing to four\ndifferent child event names. Bubbles.\n",
|
|
3047
|
+
"detail": {
|
|
3048
|
+
"action": {
|
|
3049
|
+
"description": "One of \"change-plan\" | \"add-payment-method\" | \"pay-now\" |\n\"download-invoice\" | \"update-card\" | \"retry\" | \"select-plan\"\n| \"remove-payment-method\" | \"set-default-payment-method\" |\nor any consumer-defined value carried on a descendant\n[data-account-action] attribute.\n",
|
|
3050
|
+
"type": "string"
|
|
3051
|
+
},
|
|
3052
|
+
"payload": {
|
|
3053
|
+
"description": "Forwarded detail from the originating event (e.g. the\ninvoice record, the plan id, the dunning amount). Shape\nvaries by source.\n",
|
|
3054
|
+
"type": "object"
|
|
3055
|
+
},
|
|
3056
|
+
"source": {
|
|
3057
|
+
"description": "The originating primitive — \"plan-picker\" | \"payment-method-list\"\n| \"invoice-history\" | \"alert-dunning\" | \"header\" | \"custom\".\n",
|
|
3058
|
+
"type": "string"
|
|
3059
|
+
}
|
|
3060
|
+
}
|
|
3061
|
+
},
|
|
3062
|
+
"error": {
|
|
3063
|
+
"description": "Fired when a `data-stream-src` fetch fails. Bubbles.\n",
|
|
3064
|
+
"detail": {
|
|
3065
|
+
"reason": {
|
|
3066
|
+
"description": "One of `fetch-failed`.",
|
|
3067
|
+
"type": "string"
|
|
3068
|
+
}
|
|
3069
|
+
}
|
|
3070
|
+
},
|
|
3071
|
+
"load": {
|
|
3072
|
+
"description": "Fired when `data-stream-src` finishes a successful fetch and\n`account` is populated. Bubbles.\n",
|
|
3073
|
+
"detail": {
|
|
3074
|
+
"account": {
|
|
3075
|
+
"description": "The loaded account snapshot.",
|
|
3076
|
+
"type": "object"
|
|
3077
|
+
}
|
|
3078
|
+
}
|
|
3079
|
+
}
|
|
3080
|
+
},
|
|
3081
|
+
"examples": [
|
|
3082
|
+
{
|
|
3083
|
+
"description": "Active Pro plan with 4 saved cards + 3 invoices.",
|
|
3084
|
+
"a2ui": "[\n {\n \"id\": \"bo-pro\",\n \"component\": \"BillingOverview\",\n \"variant\": \"full\",\n \"currency\": \"USD\",\n \"account\": {\n \"plan\": {\n \"id\": \"p_pro\",\n \"name\": \"Pro\",\n \"price\": 48,\n \"cycle\": \"month\",\n \"currency\": \"USD\",\n \"status\": \"active\"\n },\n \"status\": \"active\",\n \"billingCycle\": \"month\",\n \"currentSpend\": 48,\n \"seats\": {\"used\": 4, \"total\": 10},\n \"nextInvoiceDate\": \"2026-06-01\",\n \"plans\": [],\n \"paymentMethods\": [],\n \"invoices\": []\n }\n }\n]\n",
|
|
3085
|
+
"name": "active-pro-account"
|
|
3086
|
+
},
|
|
3087
|
+
{
|
|
3088
|
+
"description": "Past-due account with dunning banner above plan section.",
|
|
3089
|
+
"a2ui": "[\n {\n \"id\": \"bo-past-due\",\n \"component\": \"BillingOverview\",\n \"variant\": \"full\",\n \"currency\": \"USD\",\n \"account\": {\n \"plan\": {\n \"id\": \"p_pro\",\n \"name\": \"Pro\",\n \"price\": 48,\n \"cycle\": \"month\",\n \"currency\": \"USD\",\n \"status\": \"past_due\"\n },\n \"status\": \"past_due\",\n \"billingCycle\": \"month\",\n \"currentSpend\": 48,\n \"seats\": {\"used\": 4, \"total\": 10},\n \"nextInvoiceDate\": \"2026-05-20\",\n \"dunning\": {\n \"amount\": 48,\n \"currency\": \"USD\",\n \"dueAt\": \"2026-05-20\",\n \"cardLast4\": \"4242\",\n \"reason\": \"declined\"\n },\n \"plans\": [],\n \"paymentMethods\": [],\n \"invoices\": []\n }\n }\n]\n",
|
|
3090
|
+
"name": "past-due-account"
|
|
3091
|
+
}
|
|
3092
|
+
],
|
|
3093
|
+
"keywords": [
|
|
3094
|
+
"billing",
|
|
3095
|
+
"overview",
|
|
3096
|
+
"dashboard",
|
|
3097
|
+
"account",
|
|
3098
|
+
"subscription",
|
|
3099
|
+
"plan",
|
|
3100
|
+
"invoice",
|
|
3101
|
+
"payment-method",
|
|
3102
|
+
"usage",
|
|
3103
|
+
"dunning",
|
|
3104
|
+
"past-due"
|
|
3105
|
+
],
|
|
3106
|
+
"name": "UIBillingOverview",
|
|
3107
|
+
"related": [
|
|
3108
|
+
"PlanPicker",
|
|
3109
|
+
"PaymentMethodList",
|
|
3110
|
+
"InvoiceHistory",
|
|
3111
|
+
"InvoiceDetail",
|
|
3112
|
+
"PaymentMethodForm",
|
|
3113
|
+
"Alert",
|
|
3114
|
+
"Stat"
|
|
3115
|
+
],
|
|
3116
|
+
"slots": {
|
|
3117
|
+
"after-invoice-history": {
|
|
3118
|
+
"description": "Optional content slotted below the invoice-history section\n(e.g. tax-document download row, billing-contact form).\n"
|
|
3119
|
+
},
|
|
3120
|
+
"before-plan-picker": {
|
|
3121
|
+
"description": "Optional content slotted above the plan-picker section (e.g. a\npromo banner, an annual-savings callout).\n"
|
|
3122
|
+
},
|
|
3123
|
+
"empty": {
|
|
3124
|
+
"description": "Custom empty-state content when there's no account snapshot\nAND no data-stream-src. Falls back to a default empty-state\nmessage.\n"
|
|
3125
|
+
},
|
|
3126
|
+
"header-actions": {
|
|
3127
|
+
"description": "Optional action row in the dashboard header (top-right). Used\nfor consumer-authored \"Contact sales\", \"Cancel subscription\",\netc. The composite NEVER stamps a default toolbar.\n"
|
|
3128
|
+
}
|
|
3129
|
+
},
|
|
3130
|
+
"states": [
|
|
3131
|
+
{
|
|
3132
|
+
"description": "Default — account rendered, ready for interaction.",
|
|
3133
|
+
"name": "idle"
|
|
3134
|
+
},
|
|
3135
|
+
{
|
|
3136
|
+
"description": "A `data-stream-src` fetch is in flight or [loading] is set.",
|
|
3137
|
+
"attribute": "loading",
|
|
3138
|
+
"name": "loading"
|
|
3139
|
+
},
|
|
3140
|
+
{
|
|
3141
|
+
"description": "No account snapshot + no data-stream-src.",
|
|
3142
|
+
"attribute": "empty",
|
|
3143
|
+
"name": "empty"
|
|
3144
|
+
},
|
|
3145
|
+
{
|
|
3146
|
+
"description": "Account is past-due (computed from `account.status === \"past_due\"`).\nStamps the dunning banner if `account.dunning` is present.\n",
|
|
3147
|
+
"attribute": "past-due",
|
|
3148
|
+
"name": "past-due"
|
|
3149
|
+
},
|
|
3150
|
+
{
|
|
3151
|
+
"description": "Account is trialing (computed from `account.status === \"trialing\"`).\n",
|
|
3152
|
+
"attribute": "trial",
|
|
3153
|
+
"name": "trial"
|
|
3154
|
+
},
|
|
3155
|
+
{
|
|
3156
|
+
"description": "Last `data-stream-src` fetch failed.",
|
|
3157
|
+
"attribute": "error",
|
|
3158
|
+
"name": "error"
|
|
3159
|
+
}
|
|
3160
|
+
],
|
|
3161
|
+
"status": "experimental",
|
|
3162
|
+
"synonyms": {
|
|
3163
|
+
"account": [
|
|
3164
|
+
"subscription",
|
|
3165
|
+
"membership"
|
|
3166
|
+
],
|
|
3167
|
+
"billing": [
|
|
3168
|
+
"subscription",
|
|
3169
|
+
"account-billing"
|
|
3170
|
+
],
|
|
3171
|
+
"overview": [
|
|
3172
|
+
"dashboard",
|
|
3173
|
+
"summary"
|
|
3174
|
+
]
|
|
3175
|
+
},
|
|
3176
|
+
"tag": "billing-overview-ui",
|
|
3177
|
+
"tokens": {
|
|
3178
|
+
"--billing-overview-bg": {
|
|
3179
|
+
"description": "Host page background. Defaults to transparent.",
|
|
3180
|
+
"default": "transparent"
|
|
3181
|
+
},
|
|
3182
|
+
"--billing-overview-gap": {
|
|
3183
|
+
"description": "Vertical gap between dashboard sections.",
|
|
3184
|
+
"default": "var(--a-space-5)"
|
|
3185
|
+
},
|
|
3186
|
+
"--billing-overview-header-gap": {
|
|
3187
|
+
"description": "Gap between the plan title block and the status badge cluster.",
|
|
3188
|
+
"default": "var(--a-space-3)"
|
|
3189
|
+
},
|
|
3190
|
+
"--billing-overview-kpi-columns": {
|
|
3191
|
+
"description": "Grid column template for the KPI strip. Falls back to a 3-column\nauto-fit when narrowed below 40rem (container query).\n",
|
|
3192
|
+
"default": "repeat(3, minmax(0, 1fr))"
|
|
3193
|
+
},
|
|
3194
|
+
"--billing-overview-kpi-gap": {
|
|
3195
|
+
"description": "Gap between KPI stat cards.",
|
|
3196
|
+
"default": "var(--a-space-3)"
|
|
3197
|
+
},
|
|
3198
|
+
"--billing-overview-meta-fg": {
|
|
3199
|
+
"description": "Foreground color for secondary metadata in the header.",
|
|
3200
|
+
"default": "var(--a-fg-muted)"
|
|
3201
|
+
},
|
|
3202
|
+
"--billing-overview-px": {
|
|
3203
|
+
"description": "Horizontal padding around dashboard content.",
|
|
3204
|
+
"default": "var(--a-space-5)"
|
|
3205
|
+
},
|
|
3206
|
+
"--billing-overview-py": {
|
|
3207
|
+
"description": "Vertical padding around dashboard content.",
|
|
3208
|
+
"default": "var(--a-space-5)"
|
|
3209
|
+
},
|
|
3210
|
+
"--billing-overview-section-heading-fg": {
|
|
3211
|
+
"description": "Foreground color for section heading labels.",
|
|
3212
|
+
"default": "var(--a-fg)"
|
|
3213
|
+
},
|
|
3214
|
+
"--billing-overview-section-heading-size": {
|
|
3215
|
+
"description": "Font size for section heading labels.",
|
|
3216
|
+
"default": "var(--a-text-base, 1rem)"
|
|
3217
|
+
},
|
|
3218
|
+
"--billing-overview-section-heading-weight": {
|
|
3219
|
+
"description": "Font weight for section heading labels.",
|
|
3220
|
+
"default": "var(--a-weight-semibold, 600)"
|
|
3221
|
+
},
|
|
3222
|
+
"--billing-overview-section-radius": {
|
|
3223
|
+
"description": "Section card corner radius.",
|
|
3224
|
+
"default": "var(--a-radius-lg)"
|
|
3225
|
+
}
|
|
3226
|
+
},
|
|
3227
|
+
"traits": [],
|
|
3228
|
+
"version": 1
|
|
3229
|
+
}
|
|
3230
|
+
},
|
|
2889
3231
|
"Block": {
|
|
2890
3232
|
"title": "Block",
|
|
2891
3233
|
"description": "Generic padded / margined content wrapper. Applies a configurable\npadding + margin scale via [padding] / [margin] attribute props,\nmapping to the canonical spacing tokens. Use as a lightweight\nspacing wrapper when <section-ui> would imply chrome the parent\ncontainer doesn't own. Not a layout primitive (no flex / grid) —\nfor layout use <col-ui> / <row-ui> / <stack-ui> / <grid-ui>.\n",
|
|
@@ -3378,6 +3720,16 @@
|
|
|
3378
3720
|
"type": "string",
|
|
3379
3721
|
"default": ""
|
|
3380
3722
|
},
|
|
3723
|
+
"rangeEnd": {
|
|
3724
|
+
"description": "End of a date range (ISO YYYY-MM-DD). See `rangeStart` for the full contract.",
|
|
3725
|
+
"type": "string",
|
|
3726
|
+
"default": ""
|
|
3727
|
+
},
|
|
3728
|
+
"rangeStart": {
|
|
3729
|
+
"description": "Start of a date range (ISO YYYY-MM-DD). When both rangeStart and rangeEnd are set + ordered, day cells strictly between the endpoints get `[data-in-range]` stamped for visual continuity. Used by `<date-range-picker-ui>` which pushes the same from/to onto both calendar panes. Endpoints themselves render via the `value` prop's `[data-selected]` state.",
|
|
3730
|
+
"type": "string",
|
|
3731
|
+
"default": ""
|
|
3732
|
+
},
|
|
3381
3733
|
"readonly": {
|
|
3382
3734
|
"description": "Blocks selection but allows month navigation.",
|
|
3383
3735
|
"type": "boolean",
|
|
@@ -4519,7 +4871,7 @@
|
|
|
4519
4871
|
],
|
|
4520
4872
|
"slots": {
|
|
4521
4873
|
"default": {
|
|
4522
|
-
"description": "Default — primary input child (typically <chat-input-ui
|
|
4874
|
+
"description": "Default — primary input child (typically <chat-input-ui>; <input-ui> also works — both emit a `submit` event on Enter without Shift)."
|
|
4523
4875
|
},
|
|
4524
4876
|
"attach": {
|
|
4525
4877
|
"description": "Future — attachment trigger button (paperclip icon to upload)."
|
|
@@ -4763,7 +5115,7 @@
|
|
|
4763
5115
|
"composes": [],
|
|
4764
5116
|
"events": {
|
|
4765
5117
|
"submit": {
|
|
4766
|
-
"description": "Fires when the user presses Enter (without Shift) in the textarea OR clicks the built-in send button. The composer suppresses submission while `[loading]` is set.",
|
|
5118
|
+
"description": "Fires when the user presses Enter (without Shift) in the textarea OR clicks the built-in send button. Unconditional — there is no [submit-on-enter] opt-in or opt-out attribute; Enter→submit is delegated from the inner <textarea-ui> which always emits a `submit` event on Enter without Shift. The composer suppresses submission while `[loading]` is set.",
|
|
4767
5119
|
"detail": {
|
|
4768
5120
|
"model": {
|
|
4769
5121
|
"description": "Currently selected model value (empty if no model picker).",
|
|
@@ -4988,7 +5340,7 @@
|
|
|
4988
5340
|
],
|
|
4989
5341
|
"slots": {
|
|
4990
5342
|
"default": {
|
|
4991
|
-
"description": "Bespoke children compose here in document order — typically <chat-thread> (with optional <chat-empty> inside) for the message surface, then <chat-composer> wrapping a <chat-input-ui
|
|
5343
|
+
"description": "Bespoke children compose here in document order — typically <chat-thread> (with optional <chat-empty> inside) for the message surface, then <chat-composer> wrapping a <chat-input-ui> for the input. Optional <chat-header>, <chat-sidebar slot=\"leading|trailing\">, <chat-status>."
|
|
4992
5344
|
}
|
|
4993
5345
|
},
|
|
4994
5346
|
"states": [
|
|
@@ -6954,9 +7306,9 @@
|
|
|
6954
7306
|
"version": 1
|
|
6955
7307
|
}
|
|
6956
7308
|
},
|
|
6957
|
-
"
|
|
6958
|
-
"title": "
|
|
6959
|
-
"description": "
|
|
7309
|
+
"DashboardLayout": {
|
|
7310
|
+
"title": "DashboardLayout",
|
|
7311
|
+
"description": "Module-tier dashboard-body composite. Crystallizes the recurring\n\"toolbar + KPI grid + chart area + table\" dashboard layout into a\nsingle primitive with four named regions (toolbar / kpis / charts /\ntable) plus an optional aside column. Each region is filled by\nconsumer-supplied <card-ui>s; the composite owns band sizing,\nresponsive breakpoints, and a [density] knob that propagates to\nevery descendant primitive via the parametric --a-density cascade.\n\nSits inside an <admin-page-body>; replaces the hand-rolled\n<col-ui gap=\"4\"> + nested <grid-ui> + <card-ui> chains every\nanalytics consumer reinvents today. Per ADR-0033 (Light-DOM\nsubstrate) — slot= attributes are decorative metadata; CSS rules\nmatch `:scope > [slot=\"X\"]` to position bands in DOM order.\n\nSpec: docs/specs/implementation-ready/SPEC-018-dashboard-layout.md.\n",
|
|
6960
7312
|
"type": "object",
|
|
6961
7313
|
"allOf": [
|
|
6962
7314
|
{
|
|
@@ -6967,64 +7319,316 @@
|
|
|
6967
7319
|
}
|
|
6968
7320
|
],
|
|
6969
7321
|
"properties": {
|
|
6970
|
-
"
|
|
6971
|
-
"description": "
|
|
6972
|
-
"type": "
|
|
6973
|
-
"
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
"
|
|
6981
|
-
"type": "boolean",
|
|
6982
|
-
"default": false
|
|
7322
|
+
"chart-split": {
|
|
7323
|
+
"description": "Chart-band column split. Empty string = single full-width chart;\n`2` = two equal columns; `2:1` / `3:2` / `3:1` = asymmetric\nratios. Collapses to single column at narrow widths (≤48em).\n",
|
|
7324
|
+
"type": "string",
|
|
7325
|
+
"enum": [
|
|
7326
|
+
"",
|
|
7327
|
+
"2",
|
|
7328
|
+
"2:1",
|
|
7329
|
+
"3:2",
|
|
7330
|
+
"3:1"
|
|
7331
|
+
],
|
|
7332
|
+
"default": ""
|
|
6983
7333
|
},
|
|
6984
7334
|
"component": {
|
|
6985
|
-
"const": "
|
|
6986
|
-
},
|
|
6987
|
-
"disabled": {
|
|
6988
|
-
"description": "Block all interaction. Trigger remains rendered but does not open the popover.",
|
|
6989
|
-
"type": "boolean",
|
|
6990
|
-
"default": false
|
|
7335
|
+
"const": "DashboardLayout"
|
|
6991
7336
|
},
|
|
6992
|
-
"
|
|
6993
|
-
"description": "
|
|
7337
|
+
"density": {
|
|
7338
|
+
"description": "Spacing scale — propagates --a-density to descendant primitives\nvia CSS custom-property cascade. Empty string inherits whatever\ndensity is in effect on an ancestor (the default — respects an\napp-level density theme). `compact` / `comfortable` / `spacious`\nexplicitly override.\n",
|
|
6994
7339
|
"type": "string",
|
|
6995
7340
|
"enum": [
|
|
6996
|
-
"
|
|
6997
|
-
"
|
|
6998
|
-
"
|
|
7341
|
+
"",
|
|
7342
|
+
"comfortable",
|
|
7343
|
+
"compact",
|
|
7344
|
+
"spacious"
|
|
6999
7345
|
],
|
|
7000
|
-
"default": "short"
|
|
7001
|
-
},
|
|
7002
|
-
"max": {
|
|
7003
|
-
"description": "Latest selectable ISO date (inclusive). Days after are disabled in both panes.",
|
|
7004
|
-
"type": "string",
|
|
7005
7346
|
"default": ""
|
|
7006
7347
|
},
|
|
7007
|
-
"
|
|
7008
|
-
"description": "
|
|
7348
|
+
"gap": {
|
|
7349
|
+
"description": "Override band-to-band vertical gap. Empty string = the\ndensity-modulated default (--a-space-4 at comfortable). Numeric\n`1`..`6` selects the corresponding --a-space-N step.\n",
|
|
7009
7350
|
"type": "string",
|
|
7010
7351
|
"default": ""
|
|
7011
7352
|
},
|
|
7012
|
-
"
|
|
7013
|
-
"description": "
|
|
7353
|
+
"kpi-columns": {
|
|
7354
|
+
"description": "Target column count for the KPI band at desktop width. Range 2-6;\nout-of-range values fall back to 4. Container-query collapse\nreduces this at narrower widths (≤48em → 2; ≤32em → 1).\n",
|
|
7014
7355
|
"type": "string",
|
|
7015
|
-
"
|
|
7016
|
-
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
|
|
7356
|
+
"enum": [
|
|
7357
|
+
"2",
|
|
7358
|
+
"3",
|
|
7359
|
+
"4",
|
|
7360
|
+
"5",
|
|
7361
|
+
"6"
|
|
7362
|
+
],
|
|
7363
|
+
"default": "4"
|
|
7021
7364
|
},
|
|
7022
|
-
"
|
|
7023
|
-
"description": "
|
|
7365
|
+
"loading": {
|
|
7366
|
+
"description": "Marks the composite as data-loading. Sets aria-busy=true on the\nhost and dims slotted children to 60% opacity with pointer-events\nsuppressed. Skeletons inside slotted cards continue to render\nnormally; the dim is on top of them.\n",
|
|
7024
7367
|
"type": "boolean",
|
|
7025
7368
|
"default": false
|
|
7026
|
-
}
|
|
7027
|
-
|
|
7369
|
+
}
|
|
7370
|
+
},
|
|
7371
|
+
"required": [
|
|
7372
|
+
"component"
|
|
7373
|
+
],
|
|
7374
|
+
"unevaluatedProperties": false,
|
|
7375
|
+
"x-adiaui": {
|
|
7376
|
+
"anti_patterns": [
|
|
7377
|
+
{
|
|
7378
|
+
"description": "Child without a [slot] attribute. Lands in the implicit default\nregion and breaks the band layout. Every direct child MUST\ndeclare its slot — toolbar / kpis / charts / table / aside.\n",
|
|
7379
|
+
"right": "<dashboard-layout-ui>\n <card-ui slot=\"kpis\">...</card-ui>\n</dashboard-layout-ui>\n",
|
|
7380
|
+
"rule": "Every direct child of dashboard-layout-ui declares its slot.\n",
|
|
7381
|
+
"wrong": "<dashboard-layout-ui>\n <card-ui><!-- no slot -->...</card-ui>\n</dashboard-layout-ui>\n"
|
|
7382
|
+
},
|
|
7383
|
+
{
|
|
7384
|
+
"description": "Nested DashboardLayout. Two density containers fight over the\n--a-density cascade. The inner one re-creates a 2-column layout\ninside a charts band, which is incoherent.\n",
|
|
7385
|
+
"right": "<tabs-ui>\n <tab-panel-ui><dashboard-layout-ui>...</dashboard-layout-ui></tab-panel-ui>\n <tab-panel-ui><dashboard-layout-ui>...</dashboard-layout-ui></tab-panel-ui>\n</tabs-ui>\n",
|
|
7386
|
+
"rule": "For nested dashboards, use sibling DashboardLayouts switched by\nTabs — not DashboardLayout inside DashboardLayout.\n",
|
|
7387
|
+
"wrong": "<dashboard-layout-ui>\n <dashboard-layout-ui slot=\"charts\">...</dashboard-layout-ui>\n</dashboard-layout-ui>\n"
|
|
7388
|
+
},
|
|
7389
|
+
{
|
|
7390
|
+
"description": "kpi-columns out of range. Eight cards in a row is too narrow\nto be legible at typical container widths; the container-query\ncollapse (≤48em → 2 cols, ≤32em → 1 col) won't help when N is\nalready that large at desktop.\n",
|
|
7391
|
+
"right": "<dashboard-layout-ui kpi-columns=\"4\">...</dashboard-layout-ui>\n",
|
|
7392
|
+
"rule": "kpi-columns ∈ {2,3,4,5,6}. Split into 2 rows of 4 by composing\n2 DashboardLayouts vertically if 8 cards are truly necessary.\n",
|
|
7393
|
+
"wrong": "<dashboard-layout-ui kpi-columns=\"8\">...</dashboard-layout-ui>\n"
|
|
7394
|
+
}
|
|
7395
|
+
],
|
|
7396
|
+
"category": "layout",
|
|
7397
|
+
"composes": [
|
|
7398
|
+
"card-ui",
|
|
7399
|
+
"grid-ui",
|
|
7400
|
+
"row-ui",
|
|
7401
|
+
"stat-ui",
|
|
7402
|
+
"chart-ui",
|
|
7403
|
+
"table-ui"
|
|
7404
|
+
],
|
|
7405
|
+
"events": {
|
|
7406
|
+
"density-change": {
|
|
7407
|
+
"description": "Fired when [density] changes (programmatic or via setDensity()).\nBubbles; detail.density carries the new value.\n",
|
|
7408
|
+
"detail": {
|
|
7409
|
+
"density": {
|
|
7410
|
+
"description": "The new density value (comfortable / compact / spacious).",
|
|
7411
|
+
"type": "string"
|
|
7412
|
+
}
|
|
7413
|
+
}
|
|
7414
|
+
},
|
|
7415
|
+
"region-empty": {
|
|
7416
|
+
"description": "Fired when a slot transitions from having content to being empty\n(consumer-driven removal of the last child for that slot).\nUseful for parent-level adjust-layout logic.\n",
|
|
7417
|
+
"detail": {
|
|
7418
|
+
"region": {
|
|
7419
|
+
"description": "The slot name that became empty (toolbar / kpis / charts / table / aside).",
|
|
7420
|
+
"type": "string"
|
|
7421
|
+
}
|
|
7422
|
+
}
|
|
7423
|
+
}
|
|
7424
|
+
},
|
|
7425
|
+
"examples": [
|
|
7426
|
+
{
|
|
7427
|
+
"description": "KPI-strip + 2:1 chart split + table band inside an admin page.\n",
|
|
7428
|
+
"a2ui": "[\n {\n \"id\": \"dash-1\",\n \"component\": \"DashboardLayout\",\n \"density\": \"\",\n \"kpiColumns\": \"4\",\n \"chartSplit\": \"2:1\",\n \"children\": [\"dash-toolbar\", \"dash-kpis\", \"dash-charts\", \"dash-table\"]\n },\n {\n \"id\": \"dash-toolbar\",\n \"component\": \"Row\",\n \"slot\": \"toolbar\"\n },\n {\n \"id\": \"dash-kpis\",\n \"component\": \"Group\",\n \"slot\": \"kpis\"\n },\n {\n \"id\": \"dash-charts\",\n \"component\": \"Group\",\n \"slot\": \"charts\"\n },\n {\n \"id\": \"dash-table\",\n \"component\": \"Card\",\n \"slot\": \"table\"\n }\n]\n",
|
|
7429
|
+
"name": "canonical-analytics-dashboard"
|
|
7430
|
+
},
|
|
7431
|
+
{
|
|
7432
|
+
"description": "Six-KPI dashboard at compact density (power-user view).\n",
|
|
7433
|
+
"a2ui": "[\n {\n \"id\": \"dash-2\",\n \"component\": \"DashboardLayout\",\n \"density\": \"compact\",\n \"kpiColumns\": \"6\"\n }\n]\n",
|
|
7434
|
+
"name": "compact-six-kpi"
|
|
7435
|
+
},
|
|
7436
|
+
{
|
|
7437
|
+
"description": "Dashboard with a sticky aside column carrying a live activity feed.\n",
|
|
7438
|
+
"a2ui": "[\n {\n \"id\": \"dash-3\",\n \"component\": \"DashboardLayout\",\n \"chartSplit\": \"2\",\n \"children\": [\"d3-aside\"]\n },\n {\n \"id\": \"d3-aside\",\n \"component\": \"Card\",\n \"slot\": \"aside\"\n }\n]\n",
|
|
7439
|
+
"name": "with-aside-feed"
|
|
7440
|
+
}
|
|
7441
|
+
],
|
|
7442
|
+
"keywords": [
|
|
7443
|
+
"dashboard",
|
|
7444
|
+
"dashboard-layout",
|
|
7445
|
+
"analytics",
|
|
7446
|
+
"kpi-grid",
|
|
7447
|
+
"chart-area",
|
|
7448
|
+
"dashboard-body",
|
|
7449
|
+
"admin-dashboard",
|
|
7450
|
+
"reporting",
|
|
7451
|
+
"metrics-page",
|
|
7452
|
+
"layout-container"
|
|
7453
|
+
],
|
|
7454
|
+
"name": "UIDashboardLayout",
|
|
7455
|
+
"related": [
|
|
7456
|
+
"AdminPageBody",
|
|
7457
|
+
"AdminPage",
|
|
7458
|
+
"Card",
|
|
7459
|
+
"Grid",
|
|
7460
|
+
"Stat",
|
|
7461
|
+
"Chart",
|
|
7462
|
+
"Table",
|
|
7463
|
+
"DateRangeSelector"
|
|
7464
|
+
],
|
|
7465
|
+
"slots": {
|
|
7466
|
+
"aside": {
|
|
7467
|
+
"description": "Optional right-side panel (e.g., live activity feed). When set,\npromotes the host to a 2-column grid with the aside as a sticky\nright column on desktop. Collapses when empty.\n"
|
|
7468
|
+
},
|
|
7469
|
+
"charts": {
|
|
7470
|
+
"description": "Chart band — wrapper containing 1-3 <card-ui> with <chart-ui>.\n[chart-split] drives the grid columns. Collapses when empty.\n"
|
|
7471
|
+
},
|
|
7472
|
+
"kpis": {
|
|
7473
|
+
"description": "KPI band — typically a wrapper element containing N <card-ui>\ninstances each with one <stat-ui>. The composite drives the\ngrid template via [kpi-columns]. Collapses when empty.\n"
|
|
7474
|
+
},
|
|
7475
|
+
"table": {
|
|
7476
|
+
"description": "Table band — typically a single <card-ui slot=\"table\"> containing\n<table-ui> and optional <pagination-ui> in the footer. Full-bleed\nacross the main column. Collapses when empty.\n"
|
|
7477
|
+
},
|
|
7478
|
+
"toolbar": {
|
|
7479
|
+
"description": "Top band — filter chips, segmented date range, global controls.\nTypically a single <row-ui> or <date-range-selector-ui> (SPEC-019).\nCollapses when empty (no row reserved).\n"
|
|
7480
|
+
}
|
|
7481
|
+
},
|
|
7482
|
+
"states": [
|
|
7483
|
+
{
|
|
7484
|
+
"description": "Default; all regions interactive.",
|
|
7485
|
+
"name": "idle"
|
|
7486
|
+
},
|
|
7487
|
+
{
|
|
7488
|
+
"description": "Data fetch in progress; aria-busy=true; content dimmed.",
|
|
7489
|
+
"attribute": "loading",
|
|
7490
|
+
"name": "loading"
|
|
7491
|
+
},
|
|
7492
|
+
{
|
|
7493
|
+
"description": "Compact-density variant; tighter band gaps + density cascade.",
|
|
7494
|
+
"attribute": "density",
|
|
7495
|
+
"name": "compact"
|
|
7496
|
+
},
|
|
7497
|
+
{
|
|
7498
|
+
"description": "Spacious-density variant; looser band gaps + density cascade.",
|
|
7499
|
+
"attribute": "density",
|
|
7500
|
+
"name": "spacious"
|
|
7501
|
+
}
|
|
7502
|
+
],
|
|
7503
|
+
"status": "experimental",
|
|
7504
|
+
"synonyms": {
|
|
7505
|
+
"charts": [
|
|
7506
|
+
"chart-area",
|
|
7507
|
+
"viz",
|
|
7508
|
+
"graphs"
|
|
7509
|
+
],
|
|
7510
|
+
"dashboard": [
|
|
7511
|
+
"analytics",
|
|
7512
|
+
"report",
|
|
7513
|
+
"overview",
|
|
7514
|
+
"metrics"
|
|
7515
|
+
],
|
|
7516
|
+
"kpi": [
|
|
7517
|
+
"metric",
|
|
7518
|
+
"stat",
|
|
7519
|
+
"measure"
|
|
7520
|
+
],
|
|
7521
|
+
"layout": [
|
|
7522
|
+
"container",
|
|
7523
|
+
"grid",
|
|
7524
|
+
"frame",
|
|
7525
|
+
"shell"
|
|
7526
|
+
],
|
|
7527
|
+
"tags": [
|
|
7528
|
+
"DashboardLayout",
|
|
7529
|
+
"Dashboard",
|
|
7530
|
+
"AnalyticsDashboard",
|
|
7531
|
+
"MetricsDashboard"
|
|
7532
|
+
]
|
|
7533
|
+
},
|
|
7534
|
+
"tag": "dashboard-layout-ui",
|
|
7535
|
+
"tokens": {
|
|
7536
|
+
"--dashboard-layout-aside-width": {
|
|
7537
|
+
"description": "Aside column width when [slot=\"aside\"] is present.",
|
|
7538
|
+
"default": "20em"
|
|
7539
|
+
},
|
|
7540
|
+
"--dashboard-layout-chart-gap": {
|
|
7541
|
+
"description": "Inter-card gap inside the chart band.",
|
|
7542
|
+
"default": "var(--a-space-4)"
|
|
7543
|
+
},
|
|
7544
|
+
"--dashboard-layout-gap": {
|
|
7545
|
+
"description": "Band-to-band vertical gap.",
|
|
7546
|
+
"default": "var(--a-space-4)"
|
|
7547
|
+
},
|
|
7548
|
+
"--dashboard-layout-kpi-gap": {
|
|
7549
|
+
"description": "Inter-card gap inside the KPI band.",
|
|
7550
|
+
"default": "var(--a-space-2)"
|
|
7551
|
+
},
|
|
7552
|
+
"--dashboard-layout-padding": {
|
|
7553
|
+
"description": "Outer padding around the composite.",
|
|
7554
|
+
"default": "0"
|
|
7555
|
+
}
|
|
7556
|
+
},
|
|
7557
|
+
"traits": [],
|
|
7558
|
+
"version": 1
|
|
7559
|
+
}
|
|
7560
|
+
},
|
|
7561
|
+
"DateRangePicker": {
|
|
7562
|
+
"title": "DateRangePicker",
|
|
7563
|
+
"description": "Compound form primitive for selecting a start + end date pair with optional named preset shortcuts (\"Today\", \"Last 7 days\", \"This month\", ...). Default presentation is a trigger button showing the formatted range; on activation a popover opens with two synchronized calendar panes + a preset side rail. Composes <calendar-picker-ui> twice; emits {from, to} ISO 8601 dates. Optional comparison-range mode emits a secondary range for analytics surfaces.",
|
|
7564
|
+
"type": "object",
|
|
7565
|
+
"allOf": [
|
|
7566
|
+
{
|
|
7567
|
+
"$ref": "#/$defs/ComponentCommon"
|
|
7568
|
+
},
|
|
7569
|
+
{
|
|
7570
|
+
"$ref": "#/$defs/CatalogComponentCommon"
|
|
7571
|
+
}
|
|
7572
|
+
],
|
|
7573
|
+
"properties": {
|
|
7574
|
+
"required": {
|
|
7575
|
+
"description": "Required for validation when inside a `<form>`.",
|
|
7576
|
+
"type": "boolean",
|
|
7577
|
+
"default": false
|
|
7578
|
+
},
|
|
7579
|
+
"compareValue": {
|
|
7580
|
+
"description": "Comparison range when `[comparison]` is set. Same `{from, to}` shape as `value`.",
|
|
7581
|
+
"$ref": "#/$defs/DynamicString"
|
|
7582
|
+
},
|
|
7583
|
+
"comparison": {
|
|
7584
|
+
"description": "Enable comparison-range mode. Renders a second preset cluster and emits a secondary range under `<name>-compare`.",
|
|
7585
|
+
"type": "boolean",
|
|
7586
|
+
"default": false
|
|
7587
|
+
},
|
|
7588
|
+
"component": {
|
|
7589
|
+
"const": "DateRangePicker"
|
|
7590
|
+
},
|
|
7591
|
+
"disabled": {
|
|
7592
|
+
"description": "Block all interaction. Trigger remains rendered but does not open the popover.",
|
|
7593
|
+
"type": "boolean",
|
|
7594
|
+
"default": false
|
|
7595
|
+
},
|
|
7596
|
+
"format": {
|
|
7597
|
+
"description": "Trigger button date format. `short`: `Jan 1, 2026`; `long`: `January 1, 2026`; `iso`: `2026-01-01`.",
|
|
7598
|
+
"type": "string",
|
|
7599
|
+
"enum": [
|
|
7600
|
+
"short",
|
|
7601
|
+
"long",
|
|
7602
|
+
"iso"
|
|
7603
|
+
],
|
|
7604
|
+
"default": "short"
|
|
7605
|
+
},
|
|
7606
|
+
"max": {
|
|
7607
|
+
"description": "Latest selectable ISO date (inclusive). Days after are disabled in both panes.",
|
|
7608
|
+
"type": "string",
|
|
7609
|
+
"default": ""
|
|
7610
|
+
},
|
|
7611
|
+
"min": {
|
|
7612
|
+
"description": "Earliest selectable ISO date (inclusive). Days before are disabled in both panes.",
|
|
7613
|
+
"type": "string",
|
|
7614
|
+
"default": ""
|
|
7615
|
+
},
|
|
7616
|
+
"name": {
|
|
7617
|
+
"description": "Form field name for form data submission. The selected range serializes as JSON `{\"from\":\"...\",\"to\":\"...\"}` under this key.",
|
|
7618
|
+
"type": "string",
|
|
7619
|
+
"default": ""
|
|
7620
|
+
},
|
|
7621
|
+
"noPresets": {
|
|
7622
|
+
"description": "Hide the preset side rail.",
|
|
7623
|
+
"type": "boolean",
|
|
7624
|
+
"default": false
|
|
7625
|
+
},
|
|
7626
|
+
"open": {
|
|
7627
|
+
"description": "Whether the popover is currently open.",
|
|
7628
|
+
"type": "boolean",
|
|
7629
|
+
"default": false
|
|
7630
|
+
},
|
|
7631
|
+
"placeholder": {
|
|
7028
7632
|
"description": "Text shown in the trigger when the value is empty.",
|
|
7029
7633
|
"type": "string",
|
|
7030
7634
|
"default": "Select range"
|
|
@@ -8724,6 +9328,11 @@
|
|
|
8724
9328
|
"type": "boolean",
|
|
8725
9329
|
"default": false
|
|
8726
9330
|
},
|
|
9331
|
+
"collapsible": {
|
|
9332
|
+
"description": "Reflected CSS-state marker — declares this sidebar's collapse\naffordance is exposed to authors (matching the <admin-sidebar>\nconvention). The .toggle() / .collapse() / .expand() public API\nis always callable; [collapsible] is the attribute consumers\nkey CSS rules off (e.g. showing a toggle button when present).\nSet on the canonical demos in editor-sidebar.examples.html.\n",
|
|
9333
|
+
"type": "boolean",
|
|
9334
|
+
"default": false
|
|
9335
|
+
},
|
|
8727
9336
|
"component": {
|
|
8728
9337
|
"const": "EditorSidebar"
|
|
8729
9338
|
},
|
|
@@ -10664,9 +11273,9 @@
|
|
|
10664
11273
|
"version": 1
|
|
10665
11274
|
}
|
|
10666
11275
|
},
|
|
10667
|
-
"
|
|
10668
|
-
"title": "
|
|
10669
|
-
"description": "
|
|
11276
|
+
"InlineMessage": {
|
|
11277
|
+
"title": "InlineMessage",
|
|
11278
|
+
"description": "In-flow message glyph + text used in form-field rows for validation\nfeedback, hint copy, and inline confirmations. Distinguished from\n<alert-ui> (banner / surface-bearing notice) by carrying no surface\nfill, no border, no padding box — severity is foreground color +\nicon only. Variants map to severity (info / success / warning /\ndanger). Nests inside <field-ui>, <col-ui>, <row-ui> without\nbreaking field rhythm. Non-interactive annotation only.\n",
|
|
10670
11279
|
"type": "object",
|
|
10671
11280
|
"allOf": [
|
|
10672
11281
|
{
|
|
@@ -10677,88 +11286,229 @@
|
|
|
10677
11286
|
}
|
|
10678
11287
|
],
|
|
10679
11288
|
"properties": {
|
|
10680
|
-
"type": {
|
|
10681
|
-
"description": "Input type. `password` wraps a native `<input>` for disc masking; `number` renders a contenteditable + stepper buttons (no native input). All other types use plain contenteditable.",
|
|
10682
|
-
"type": "string",
|
|
10683
|
-
"enum": [
|
|
10684
|
-
"text",
|
|
10685
|
-
"email",
|
|
10686
|
-
"password",
|
|
10687
|
-
"number",
|
|
10688
|
-
"tel",
|
|
10689
|
-
"url",
|
|
10690
|
-
"search",
|
|
10691
|
-
"date",
|
|
10692
|
-
"datetime-local",
|
|
10693
|
-
"time",
|
|
10694
|
-
"month",
|
|
10695
|
-
"week",
|
|
10696
|
-
"color"
|
|
10697
|
-
],
|
|
10698
|
-
"default": "text"
|
|
10699
|
-
},
|
|
10700
|
-
"required": {
|
|
10701
|
-
"description": "Marks the field as required for form validation. Sets aria-required.",
|
|
10702
|
-
"type": "boolean",
|
|
10703
|
-
"default": false
|
|
10704
|
-
},
|
|
10705
|
-
"autocomplete": {
|
|
10706
|
-
"description": "Browser autofill behavior per HTML autocomplete spec. Routed via setAttribute to the host element. Common values: off, on, cc-number, cc-exp, cc-csc, cc-name, email, username, current-password, new-password, one-time-code, given-name, family-name, street-address, postal-code.",
|
|
10707
|
-
"type": "string",
|
|
10708
|
-
"default": ""
|
|
10709
|
-
},
|
|
10710
11289
|
"component": {
|
|
10711
|
-
"const": "
|
|
10712
|
-
},
|
|
10713
|
-
"disabled": {
|
|
10714
|
-
"description": "Disables interaction, removes contenteditable, and dims the control",
|
|
10715
|
-
"type": "boolean",
|
|
10716
|
-
"default": false
|
|
11290
|
+
"const": "InlineMessage"
|
|
10717
11291
|
},
|
|
10718
|
-
"
|
|
10719
|
-
"description": "
|
|
10720
|
-
"
|
|
10721
|
-
"default": ""
|
|
11292
|
+
"icon": {
|
|
11293
|
+
"description": "Phosphor glyph override; each [variant] ships a sensible default (info / check-circle / warning / x-circle).",
|
|
11294
|
+
"$ref": "#/$defs/DynamicString"
|
|
10722
11295
|
},
|
|
10723
|
-
"
|
|
10724
|
-
"description": "
|
|
11296
|
+
"live": {
|
|
11297
|
+
"description": "Sets `aria-live` on the host for dynamic message updates. Empty = no live region (static annotation).",
|
|
10725
11298
|
"type": "string",
|
|
10726
11299
|
"enum": [
|
|
10727
|
-
"
|
|
10728
|
-
"
|
|
10729
|
-
"
|
|
10730
|
-
"tel",
|
|
10731
|
-
"search",
|
|
10732
|
-
"email",
|
|
10733
|
-
"url",
|
|
10734
|
-
"none"
|
|
11300
|
+
"",
|
|
11301
|
+
"polite",
|
|
11302
|
+
"assertive"
|
|
10735
11303
|
],
|
|
10736
|
-
"default": null
|
|
10737
|
-
},
|
|
10738
|
-
"label": {
|
|
10739
|
-
"description": "Inline label rendered as a leading caption inside the input chrome, between any prefix and the value. Wires aria-labelledby on the editable surface. For stacked label / hint / error compositions, wrap with field-ui.",
|
|
10740
|
-
"type": "string",
|
|
10741
|
-
"default": ""
|
|
10742
|
-
},
|
|
10743
|
-
"locale": {
|
|
10744
|
-
"description": "BCP-47 locale tag for `type=\"number\"`, e.g. `de-DE`, `fr-FR`, `en-IN`. When set, the input accepts both `.` AND the locale's decimal separator (e.g. `,` in de-DE), uses `Intl.NumberFormat` for display, and groups thousands on blur (e.g. en-US `1,234,567.89`, de-DE `1.234.567,89`). On focus, the input reverts to ungrouped form for easy editing. `.value` always stores the ungrouped, locale-decimal form so `Number(#toCanonical(v))` round-trips. Default empty = en-US-equivalent path (no behavior change).",
|
|
10745
|
-
"type": "string",
|
|
10746
11304
|
"default": ""
|
|
10747
11305
|
},
|
|
10748
|
-
"
|
|
10749
|
-
"description": "
|
|
10750
|
-
"
|
|
10751
|
-
"default": null
|
|
10752
|
-
},
|
|
10753
|
-
"maxlength": {
|
|
10754
|
-
"description": "Maximum character length for validation",
|
|
10755
|
-
"type": "number",
|
|
10756
|
-
"default": null
|
|
11306
|
+
"text": {
|
|
11307
|
+
"description": "Single-line message text. Default-slot content wins when present.",
|
|
11308
|
+
"$ref": "#/$defs/DynamicString"
|
|
10757
11309
|
},
|
|
10758
|
-
"
|
|
10759
|
-
"description": "
|
|
10760
|
-
"
|
|
10761
|
-
|
|
11310
|
+
"variant": {
|
|
11311
|
+
"description": "Semantic severity tone — drives icon + foreground color. Default carries no leading icon (pure hint copy).",
|
|
11312
|
+
"$ref": "#/$defs/DynamicString"
|
|
11313
|
+
}
|
|
11314
|
+
},
|
|
11315
|
+
"required": [
|
|
11316
|
+
"component"
|
|
11317
|
+
],
|
|
11318
|
+
"unevaluatedProperties": false,
|
|
11319
|
+
"x-adiaui": {
|
|
11320
|
+
"anti_patterns": [],
|
|
11321
|
+
"category": "feedback",
|
|
11322
|
+
"composes": [
|
|
11323
|
+
"icon-ui"
|
|
11324
|
+
],
|
|
11325
|
+
"events": {},
|
|
11326
|
+
"examples": [
|
|
11327
|
+
{
|
|
11328
|
+
"description": "Email field with a danger inline-message under the input.",
|
|
11329
|
+
"a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"Field\",\n \"label\": \"Email\",\n \"children\": [\n \"input\",\n \"msg\"\n ]\n },\n {\n \"id\": \"input\",\n \"component\": \"Input\",\n \"type\": \"email\"\n },\n {\n \"id\": \"msg\",\n \"component\": \"InlineMessage\",\n \"variant\": \"danger\",\n \"text\": \"Email address is required\"\n }\n]",
|
|
11330
|
+
"name": "field-validation"
|
|
11331
|
+
},
|
|
11332
|
+
{
|
|
11333
|
+
"description": "Password field with a muted hint (default variant, no icon).",
|
|
11334
|
+
"a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"Field\",\n \"label\": \"Password\",\n \"children\": [\n \"input\",\n \"hint\"\n ]\n },\n {\n \"id\": \"input\",\n \"component\": \"Input\",\n \"type\": \"password\"\n },\n {\n \"id\": \"hint\",\n \"component\": \"InlineMessage\",\n \"text\": \"At least 8 characters\"\n }\n]",
|
|
11335
|
+
"name": "password-hint"
|
|
11336
|
+
},
|
|
11337
|
+
{
|
|
11338
|
+
"description": "Username field with a polite live-region success confirmation.",
|
|
11339
|
+
"a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"Field\",\n \"label\": \"Username\",\n \"children\": [\n \"input\",\n \"msg\"\n ]\n },\n {\n \"id\": \"input\",\n \"component\": \"Input\"\n },\n {\n \"id\": \"msg\",\n \"component\": \"InlineMessage\",\n \"variant\": \"success\",\n \"live\": \"polite\",\n \"text\": \"Username is available\"\n }\n]",
|
|
11340
|
+
"name": "username-success"
|
|
11341
|
+
}
|
|
11342
|
+
],
|
|
11343
|
+
"keywords": [
|
|
11344
|
+
"inline",
|
|
11345
|
+
"message",
|
|
11346
|
+
"hint",
|
|
11347
|
+
"helper",
|
|
11348
|
+
"validation",
|
|
11349
|
+
"error",
|
|
11350
|
+
"field-error",
|
|
11351
|
+
"helper-text",
|
|
11352
|
+
"error-text",
|
|
11353
|
+
"form-feedback",
|
|
11354
|
+
"status",
|
|
11355
|
+
"notice"
|
|
11356
|
+
],
|
|
11357
|
+
"name": "UIInlineMessage",
|
|
11358
|
+
"related": [
|
|
11359
|
+
"alert",
|
|
11360
|
+
"field",
|
|
11361
|
+
"input",
|
|
11362
|
+
"text"
|
|
11363
|
+
],
|
|
11364
|
+
"slots": {
|
|
11365
|
+
"default": {
|
|
11366
|
+
"description": "Message body — text or inline DOM (e.g. <link-ui>, <kbd-ui>). Wins over the [text] attribute when present. Stays inline so the message reads as one annotation line under the field."
|
|
11367
|
+
},
|
|
11368
|
+
"leading": {
|
|
11369
|
+
"description": "Leading icon slot. Stamped automatically from [icon] or the variant's default glyph. Consumer-provided <icon-ui slot=\"leading\"> is preserved across [variant] changes (never overwritten)."
|
|
11370
|
+
}
|
|
11371
|
+
},
|
|
11372
|
+
"states": [
|
|
11373
|
+
{
|
|
11374
|
+
"description": "Default, ready for screen-reader pickup.",
|
|
11375
|
+
"name": "idle"
|
|
11376
|
+
}
|
|
11377
|
+
],
|
|
11378
|
+
"status": "stable",
|
|
11379
|
+
"synonyms": {
|
|
11380
|
+
"error": [
|
|
11381
|
+
"error",
|
|
11382
|
+
"alert",
|
|
11383
|
+
"validation"
|
|
11384
|
+
],
|
|
11385
|
+
"helper": [
|
|
11386
|
+
"hint",
|
|
11387
|
+
"help",
|
|
11388
|
+
"tooltip"
|
|
11389
|
+
],
|
|
11390
|
+
"hint": [
|
|
11391
|
+
"hint",
|
|
11392
|
+
"tooltip",
|
|
11393
|
+
"help"
|
|
11394
|
+
],
|
|
11395
|
+
"message": [
|
|
11396
|
+
"alert",
|
|
11397
|
+
"notification",
|
|
11398
|
+
"hint"
|
|
11399
|
+
],
|
|
11400
|
+
"notice": [
|
|
11401
|
+
"alert",
|
|
11402
|
+
"banner",
|
|
11403
|
+
"hint"
|
|
11404
|
+
],
|
|
11405
|
+
"validation": [
|
|
11406
|
+
"validation",
|
|
11407
|
+
"error",
|
|
11408
|
+
"alert"
|
|
11409
|
+
]
|
|
11410
|
+
},
|
|
11411
|
+
"tag": "inline-message-ui",
|
|
11412
|
+
"tokens": {},
|
|
11413
|
+
"traits": [],
|
|
11414
|
+
"version": 1
|
|
11415
|
+
}
|
|
11416
|
+
},
|
|
11417
|
+
"Input": {
|
|
11418
|
+
"title": "Input",
|
|
11419
|
+
"description": "Text input field with contenteditable surface. Supports prefix/suffix icons, label, form participation, and a `type=\"number\"` mode that renders [+]/[-] stepper buttons, numeric input filtering, and ARIA spinbutton semantics — no native `<input type=\"number\">` under the hood. Password type uses a native `<input>` (only path that still wraps native, for `-webkit-text-security` disc masking).",
|
|
11420
|
+
"type": "object",
|
|
11421
|
+
"allOf": [
|
|
11422
|
+
{
|
|
11423
|
+
"$ref": "#/$defs/ComponentCommon"
|
|
11424
|
+
},
|
|
11425
|
+
{
|
|
11426
|
+
"$ref": "#/$defs/CatalogComponentCommon"
|
|
11427
|
+
}
|
|
11428
|
+
],
|
|
11429
|
+
"properties": {
|
|
11430
|
+
"type": {
|
|
11431
|
+
"description": "Input type. `password` wraps a native `<input>` for disc masking; `number` renders a contenteditable + stepper buttons (no native input). All other types use plain contenteditable.",
|
|
11432
|
+
"type": "string",
|
|
11433
|
+
"enum": [
|
|
11434
|
+
"text",
|
|
11435
|
+
"email",
|
|
11436
|
+
"password",
|
|
11437
|
+
"number",
|
|
11438
|
+
"tel",
|
|
11439
|
+
"url",
|
|
11440
|
+
"search",
|
|
11441
|
+
"date",
|
|
11442
|
+
"datetime-local",
|
|
11443
|
+
"time",
|
|
11444
|
+
"month",
|
|
11445
|
+
"week",
|
|
11446
|
+
"color"
|
|
11447
|
+
],
|
|
11448
|
+
"default": "text"
|
|
11449
|
+
},
|
|
11450
|
+
"required": {
|
|
11451
|
+
"description": "Marks the field as required for form validation. Sets aria-required.",
|
|
11452
|
+
"type": "boolean",
|
|
11453
|
+
"default": false
|
|
11454
|
+
},
|
|
11455
|
+
"autocomplete": {
|
|
11456
|
+
"description": "Browser autofill behavior per HTML autocomplete spec. Routed via setAttribute to the host element. Common values: off, on, cc-number, cc-exp, cc-csc, cc-name, email, username, current-password, new-password, one-time-code, given-name, family-name, street-address, postal-code.",
|
|
11457
|
+
"type": "string",
|
|
11458
|
+
"default": ""
|
|
11459
|
+
},
|
|
11460
|
+
"component": {
|
|
11461
|
+
"const": "Input"
|
|
11462
|
+
},
|
|
11463
|
+
"disabled": {
|
|
11464
|
+
"description": "Disables interaction, removes contenteditable, and dims the control",
|
|
11465
|
+
"type": "boolean",
|
|
11466
|
+
"default": false
|
|
11467
|
+
},
|
|
11468
|
+
"error": {
|
|
11469
|
+
"description": "Validation error message. Set automatically by constraint validation or manually via setInvalid().",
|
|
11470
|
+
"type": "string",
|
|
11471
|
+
"default": ""
|
|
11472
|
+
},
|
|
11473
|
+
"inputmode": {
|
|
11474
|
+
"description": "Mobile keyboard hint per HTML inputmode spec. Routed via setAttribute to the host element. Values: text, decimal, numeric, tel, search, email, url.",
|
|
11475
|
+
"type": "string",
|
|
11476
|
+
"enum": [
|
|
11477
|
+
"text",
|
|
11478
|
+
"decimal",
|
|
11479
|
+
"numeric",
|
|
11480
|
+
"tel",
|
|
11481
|
+
"search",
|
|
11482
|
+
"email",
|
|
11483
|
+
"url",
|
|
11484
|
+
"none"
|
|
11485
|
+
],
|
|
11486
|
+
"default": null
|
|
11487
|
+
},
|
|
11488
|
+
"label": {
|
|
11489
|
+
"description": "Inline label rendered as a leading caption inside the input chrome, between any prefix and the value. Wires aria-labelledby on the editable surface. For stacked label / hint / error compositions, wrap with field-ui.",
|
|
11490
|
+
"type": "string",
|
|
11491
|
+
"default": ""
|
|
11492
|
+
},
|
|
11493
|
+
"locale": {
|
|
11494
|
+
"description": "BCP-47 locale tag for `type=\"number\"`, e.g. `de-DE`, `fr-FR`, `en-IN`. When set, the input accepts both `.` AND the locale's decimal separator (e.g. `,` in de-DE), uses `Intl.NumberFormat` for display, and groups thousands on blur (e.g. en-US `1,234,567.89`, de-DE `1.234.567,89`). On focus, the input reverts to ungrouped form for easy editing. `.value` always stores the ungrouped, locale-decimal form so `Number(#toCanonical(v))` round-trips. Default empty = en-US-equivalent path (no behavior change).",
|
|
11495
|
+
"type": "string",
|
|
11496
|
+
"default": ""
|
|
11497
|
+
},
|
|
11498
|
+
"max": {
|
|
11499
|
+
"description": "Maximum numeric value. Applies when `type=\"number\"`. Clamps + drives aria-valuemax + the [+] button's disabled state.",
|
|
11500
|
+
"type": "number",
|
|
11501
|
+
"default": null
|
|
11502
|
+
},
|
|
11503
|
+
"maxlength": {
|
|
11504
|
+
"description": "Maximum character length for validation",
|
|
11505
|
+
"type": "number",
|
|
11506
|
+
"default": null
|
|
11507
|
+
},
|
|
11508
|
+
"min": {
|
|
11509
|
+
"description": "Minimum numeric value. Applies when `type=\"number\"`. Clamps + drives aria-valuemin + the [-] button's disabled state.",
|
|
11510
|
+
"type": "number",
|
|
11511
|
+
"default": null
|
|
10762
11512
|
},
|
|
10763
11513
|
"minlength": {
|
|
10764
11514
|
"description": "Minimum character length for validation",
|
|
@@ -11358,9 +12108,9 @@
|
|
|
11358
12108
|
"version": 1
|
|
11359
12109
|
}
|
|
11360
12110
|
},
|
|
11361
|
-
"
|
|
11362
|
-
"title": "
|
|
11363
|
-
"description": "
|
|
12111
|
+
"IntegrationsPage": {
|
|
12112
|
+
"title": "IntegrationsPage",
|
|
12113
|
+
"description": "Module-tier Settings page composite — a searchable, category-grouped\ngrid of <integration-card-ui> tiles (SPEC-062). Owns the\n`integrations` array, the search-filter state, the category /\nstatus grouping, the responsive grid breakpoints, and the empty-state\ncopy. Card-level events (`connect` / `configure` / `disconnect` /\n`retry`) bubble up unchanged with `provider` in detail; the page also\nemits `search` (debounced) and a top-bar `filter-change` when the\nuser picks a status chip.\n\nLives in `packages/web-modules/settings/integrations-page/` per the\nthree-tier architecture — composes multiple primitives, holds layout\nresponsibility, consumed by the settings shell. Replaces the\nhand-rolled `settings/integrations` HTML template per consumer.\n\nSpec: docs/specs/implementation-ready/SPEC-063-integrations-page.md\n",
|
|
11364
12114
|
"type": "object",
|
|
11365
12115
|
"allOf": [
|
|
11366
12116
|
{
|
|
@@ -11372,91 +12122,950 @@
|
|
|
11372
12122
|
],
|
|
11373
12123
|
"properties": {
|
|
11374
12124
|
"component": {
|
|
11375
|
-
"const": "
|
|
12125
|
+
"const": "IntegrationsPage"
|
|
11376
12126
|
},
|
|
11377
|
-
"
|
|
11378
|
-
"description": "
|
|
12127
|
+
"group-by": {
|
|
12128
|
+
"description": "How to bucket cards into sections. `category` groups by the per-item\n`category` key; `status` groups by connection state; `none` renders\na single ungrouped grid.\n",
|
|
11379
12129
|
"type": "string",
|
|
11380
12130
|
"enum": [
|
|
11381
|
-
"
|
|
11382
|
-
"
|
|
12131
|
+
"category",
|
|
12132
|
+
"status",
|
|
12133
|
+
"none"
|
|
11383
12134
|
],
|
|
11384
|
-
"default": ""
|
|
12135
|
+
"default": "category"
|
|
12136
|
+
},
|
|
12137
|
+
"integrations": {
|
|
12138
|
+
"description": "Array of integration descriptors — each item conforms to the\nSPEC-062 <integration-card-ui> prop shape:\n`{ provider, name, logo?, description?, status, category?,\nerror-message? }`. Empty array renders the empty-state slot.\n",
|
|
12139
|
+
"$ref": "#/$defs/DynamicStringList"
|
|
12140
|
+
},
|
|
12141
|
+
"loading": {
|
|
12142
|
+
"description": "Renders a skeleton grid (6 tiles) instead of cards. Driven by the\nconsumer while the integrations payload is in flight.\n",
|
|
12143
|
+
"$ref": "#/$defs/DynamicBoolean"
|
|
12144
|
+
},
|
|
12145
|
+
"search-placeholder": {
|
|
12146
|
+
"description": "Placeholder copy for the built-in search input. Defaults to\n\"Search integrations\".\n",
|
|
12147
|
+
"type": "string",
|
|
12148
|
+
"default": "Search integrations"
|
|
12149
|
+
},
|
|
12150
|
+
"status-filter": {
|
|
12151
|
+
"description": "Optional status filter — restricts the visible cards to one status.\n`all` (default) shows everything; the rest restrict to that status\nbucket. Reflects so consumers can deep-link.\n",
|
|
12152
|
+
"$ref": "#/$defs/DynamicString"
|
|
11385
12153
|
}
|
|
11386
12154
|
},
|
|
11387
12155
|
"required": [
|
|
11388
|
-
"component"
|
|
12156
|
+
"component",
|
|
12157
|
+
"integrations"
|
|
11389
12158
|
],
|
|
11390
12159
|
"unevaluatedProperties": false,
|
|
11391
12160
|
"x-adiaui": {
|
|
11392
|
-
"anti_patterns": [
|
|
11393
|
-
"category": "display",
|
|
11394
|
-
"composes": [],
|
|
11395
|
-
"events": {},
|
|
11396
|
-
"examples": [
|
|
12161
|
+
"anti_patterns": [
|
|
11397
12162
|
{
|
|
11398
|
-
"
|
|
11399
|
-
"
|
|
11400
|
-
"name": "
|
|
11401
|
-
}
|
|
11402
|
-
],
|
|
11403
|
-
"keywords": [
|
|
11404
|
-
"kbd",
|
|
11405
|
-
"command",
|
|
11406
|
-
"shortcut",
|
|
11407
|
-
"hotkey",
|
|
11408
|
-
"keyboard",
|
|
11409
|
-
"keybinding"
|
|
11410
|
-
],
|
|
11411
|
-
"name": "UIKbd",
|
|
11412
|
-
"related": [
|
|
11413
|
-
"grid"
|
|
11414
|
-
],
|
|
11415
|
-
"slots": {
|
|
11416
|
-
"default": {
|
|
11417
|
-
"description": "Key label text"
|
|
11418
|
-
}
|
|
11419
|
-
},
|
|
11420
|
-
"states": [
|
|
12163
|
+
"fix": "{\"component\": \"IntegrationsPage\", \"integrations\": [\n {\"provider\": \"slack\", \"name\": \"Slack\", \"status\": \"available\"}\n]}\n",
|
|
12164
|
+
"why": "Slotted cards are ignored — the page generates cards from the\n`integrations` prop. The page renders empty.\n",
|
|
12165
|
+
"wrong": "{\"component\": \"IntegrationsPage\", \"children\": [\n {\"component\": \"IntegrationCard\", \"provider\": \"slack\", \"name\": \"Slack\"}\n]}\n"
|
|
12166
|
+
},
|
|
11421
12167
|
{
|
|
11422
|
-
"
|
|
11423
|
-
"
|
|
12168
|
+
"fix": "{\"component\": \"IntegrationsPage\", \"integrations\": [\n {\"provider\": \"slack\", \"name\": \"Slack\", \"status\": \"available\"}\n]}\n",
|
|
12169
|
+
"why": "Re-implements the page composite with primitives. Loses search,\ngrouping, and empty-state semantics.\n",
|
|
12170
|
+
"wrong": "{\"component\": \"Page\", \"children\": [\n {\"component\": \"Grid\", \"children\": [\n {\"component\": \"IntegrationCard\", \"provider\": \"slack\", \"name\": \"Slack\"}\n ]}\n]}\n"
|
|
11424
12171
|
}
|
|
11425
12172
|
],
|
|
11426
|
-
"
|
|
11427
|
-
"
|
|
11428
|
-
"
|
|
11429
|
-
|
|
11430
|
-
|
|
11431
|
-
|
|
11432
|
-
|
|
11433
|
-
|
|
11434
|
-
|
|
11435
|
-
|
|
11436
|
-
|
|
11437
|
-
"
|
|
11438
|
-
|
|
11439
|
-
|
|
11440
|
-
|
|
11441
|
-
|
|
11442
|
-
|
|
11443
|
-
|
|
11444
|
-
|
|
11445
|
-
|
|
11446
|
-
"
|
|
11447
|
-
"
|
|
11448
|
-
|
|
11449
|
-
|
|
11450
|
-
|
|
11451
|
-
|
|
11452
|
-
|
|
11453
|
-
|
|
11454
|
-
"
|
|
11455
|
-
"
|
|
11456
|
-
|
|
11457
|
-
|
|
11458
|
-
|
|
11459
|
-
|
|
12173
|
+
"category": "container",
|
|
12174
|
+
"composes": [
|
|
12175
|
+
"integration-card-ui",
|
|
12176
|
+
"grid-ui",
|
|
12177
|
+
"search-ui",
|
|
12178
|
+
"segmented-ui",
|
|
12179
|
+
"segment-ui",
|
|
12180
|
+
"text-ui"
|
|
12181
|
+
],
|
|
12182
|
+
"events": {
|
|
12183
|
+
"configure": {
|
|
12184
|
+
"description": "Bubbled from a child <integration-card-ui> while `status=\"connected\"`.",
|
|
12185
|
+
"detail": {
|
|
12186
|
+
"provider": {
|
|
12187
|
+
"description": "The provider key of the card that fired.",
|
|
12188
|
+
"type": "string"
|
|
12189
|
+
}
|
|
12190
|
+
}
|
|
12191
|
+
},
|
|
12192
|
+
"connect": {
|
|
12193
|
+
"description": "Bubbled from a child <integration-card-ui> when its primary button is pressed while `status=\"available\"`.",
|
|
12194
|
+
"detail": {
|
|
12195
|
+
"provider": {
|
|
12196
|
+
"description": "The provider key of the card that fired.",
|
|
12197
|
+
"type": "string"
|
|
12198
|
+
}
|
|
12199
|
+
}
|
|
12200
|
+
},
|
|
12201
|
+
"disconnect": {
|
|
12202
|
+
"description": "Bubbled from a child card's overflow menu disconnect item.",
|
|
12203
|
+
"detail": {
|
|
12204
|
+
"provider": {
|
|
12205
|
+
"description": "The provider key of the card that fired.",
|
|
12206
|
+
"type": "string"
|
|
12207
|
+
}
|
|
12208
|
+
}
|
|
12209
|
+
},
|
|
12210
|
+
"filter-change": {
|
|
12211
|
+
"description": "User clicked a status filter chip in the top bar.",
|
|
12212
|
+
"detail": {
|
|
12213
|
+
"status": {
|
|
12214
|
+
"description": "The newly-selected status filter (`all` resets).",
|
|
12215
|
+
"type": "string"
|
|
12216
|
+
}
|
|
12217
|
+
}
|
|
12218
|
+
},
|
|
12219
|
+
"retry": {
|
|
12220
|
+
"description": "Bubbled from a child <integration-card-ui> while `status=\"error\"`.",
|
|
12221
|
+
"detail": {
|
|
12222
|
+
"provider": {
|
|
12223
|
+
"description": "The provider key of the card that fired.",
|
|
12224
|
+
"type": "string"
|
|
12225
|
+
}
|
|
12226
|
+
}
|
|
12227
|
+
},
|
|
12228
|
+
"search": {
|
|
12229
|
+
"description": "Debounced search input change.",
|
|
12230
|
+
"detail": {
|
|
12231
|
+
"query": {
|
|
12232
|
+
"description": "The current search query (lower-cased, trimmed).",
|
|
12233
|
+
"type": "string"
|
|
12234
|
+
}
|
|
12235
|
+
}
|
|
12236
|
+
}
|
|
12237
|
+
},
|
|
12238
|
+
"examples": [
|
|
12239
|
+
{
|
|
12240
|
+
"description": "Full integrations page grouped by category (default).",
|
|
12241
|
+
"a2ui": "[\n {\n \"id\": \"page\",\n \"component\": \"IntegrationsPage\",\n \"group-by\": \"category\",\n \"integrations\": [\n {\"provider\": \"slack\", \"name\": \"Slack\", \"logo\": \"/integrations/slack.svg\",\n \"description\": \"Notifications and replies in channels.\",\n \"status\": \"connected\", \"category\": \"Communication\"},\n {\"provider\": \"github\", \"name\": \"GitHub\", \"logo\": \"/integrations/github.svg\",\n \"description\": \"Sync issues and pull requests.\",\n \"status\": \"available\", \"category\": \"Developer Tools\"},\n {\"provider\": \"stripe\", \"name\": \"Stripe\", \"logo\": \"/integrations/stripe.svg\",\n \"description\": \"Charge customers and reconcile invoices.\",\n \"status\": \"error\", \"category\": \"Payments\",\n \"error-message\": \"Token expired — re-authenticate.\"}\n ]\n }\n]\n",
|
|
12242
|
+
"name": "category-grouped"
|
|
12243
|
+
},
|
|
12244
|
+
{
|
|
12245
|
+
"description": "Loading state — 6 skeleton tiles, no cards.",
|
|
12246
|
+
"a2ui": "[{\"id\": \"page\", \"component\": \"IntegrationsPage\", \"loading\": true}]\n",
|
|
12247
|
+
"name": "loading-skeleton"
|
|
12248
|
+
},
|
|
12249
|
+
{
|
|
12250
|
+
"description": "Empty state — no integrations available.",
|
|
12251
|
+
"a2ui": "[{\"id\": \"page\", \"component\": \"IntegrationsPage\", \"integrations\": []}]\n",
|
|
12252
|
+
"name": "empty-data"
|
|
12253
|
+
}
|
|
12254
|
+
],
|
|
12255
|
+
"keywords": [
|
|
12256
|
+
"integrations",
|
|
12257
|
+
"integration",
|
|
12258
|
+
"settings",
|
|
12259
|
+
"settings-page",
|
|
12260
|
+
"connections",
|
|
12261
|
+
"third-party",
|
|
12262
|
+
"oauth",
|
|
12263
|
+
"providers",
|
|
12264
|
+
"app-directory",
|
|
12265
|
+
"marketplace"
|
|
12266
|
+
],
|
|
12267
|
+
"name": "UIIntegrationsPage",
|
|
12268
|
+
"related": [
|
|
12269
|
+
"IntegrationCard",
|
|
12270
|
+
"Grid",
|
|
12271
|
+
"Search",
|
|
12272
|
+
"Segmented",
|
|
12273
|
+
"Page"
|
|
12274
|
+
],
|
|
12275
|
+
"slots": {
|
|
12276
|
+
"empty": {
|
|
12277
|
+
"description": "Optional override for the empty-state copy. When supplied, replaces\nthe built-in \"No integrations match\" / \"No integrations available\"\nmessages.\n"
|
|
12278
|
+
},
|
|
12279
|
+
"header": {
|
|
12280
|
+
"description": "Optional page header (kicker / title / subtitle). Overrides the\ndefault rendering — when supplied the composite stamps no\nbuilt-in heading.\n"
|
|
12281
|
+
}
|
|
12282
|
+
},
|
|
12283
|
+
"states": [
|
|
12284
|
+
{
|
|
12285
|
+
"description": "Default; renders all groups matching the current filter.",
|
|
12286
|
+
"name": "idle"
|
|
12287
|
+
},
|
|
12288
|
+
{
|
|
12289
|
+
"description": "Skeleton grid; cards hidden.",
|
|
12290
|
+
"attribute": "loading",
|
|
12291
|
+
"name": "loading"
|
|
12292
|
+
},
|
|
12293
|
+
{
|
|
12294
|
+
"description": "Search query yields zero cards.",
|
|
12295
|
+
"attribute": "data-empty-search",
|
|
12296
|
+
"name": "empty-search"
|
|
12297
|
+
},
|
|
12298
|
+
{
|
|
12299
|
+
"description": "`integrations` array is empty.",
|
|
12300
|
+
"attribute": "data-empty-data",
|
|
12301
|
+
"name": "empty-data"
|
|
12302
|
+
}
|
|
12303
|
+
],
|
|
12304
|
+
"status": "stable",
|
|
12305
|
+
"synonyms": {
|
|
12306
|
+
"integrations": [
|
|
12307
|
+
"integration",
|
|
12308
|
+
"connections",
|
|
12309
|
+
"apps",
|
|
12310
|
+
"providers"
|
|
12311
|
+
],
|
|
12312
|
+
"marketplace": [
|
|
12313
|
+
"integrations",
|
|
12314
|
+
"app-directory",
|
|
12315
|
+
"apps"
|
|
12316
|
+
],
|
|
12317
|
+
"oauth": [
|
|
12318
|
+
"integration",
|
|
12319
|
+
"connection",
|
|
12320
|
+
"auth"
|
|
12321
|
+
],
|
|
12322
|
+
"settings": [
|
|
12323
|
+
"settings",
|
|
12324
|
+
"account",
|
|
12325
|
+
"admin"
|
|
12326
|
+
]
|
|
12327
|
+
},
|
|
12328
|
+
"tag": "integrations-page-ui",
|
|
12329
|
+
"tokens": {
|
|
12330
|
+
"--integrations-page-bg": {
|
|
12331
|
+
"description": "Page background. Defaults to `var(--a-bg)`.",
|
|
12332
|
+
"default": "var(--a-bg)"
|
|
12333
|
+
},
|
|
12334
|
+
"--integrations-page-card-gap": {
|
|
12335
|
+
"description": "Gap inside the grid between cards.",
|
|
12336
|
+
"default": "var(--a-space-4)"
|
|
12337
|
+
},
|
|
12338
|
+
"--integrations-page-fg": {
|
|
12339
|
+
"description": "Primary foreground. Defaults to `var(--a-fg)`.",
|
|
12340
|
+
"default": "var(--a-fg)"
|
|
12341
|
+
},
|
|
12342
|
+
"--integrations-page-fg-muted": {
|
|
12343
|
+
"description": "Secondary foreground for empty-state copy + section meta.",
|
|
12344
|
+
"default": "var(--a-fg-muted)"
|
|
12345
|
+
},
|
|
12346
|
+
"--integrations-page-gap": {
|
|
12347
|
+
"description": "Vertical gap between toolbar / sections / empty-state.",
|
|
12348
|
+
"default": "var(--a-space-5)"
|
|
12349
|
+
},
|
|
12350
|
+
"--integrations-page-grid-min": {
|
|
12351
|
+
"description": "Minimum card width for the auto-fill grid track.",
|
|
12352
|
+
"default": "var(--a-space-12)"
|
|
12353
|
+
},
|
|
12354
|
+
"--integrations-page-px": {
|
|
12355
|
+
"description": "Horizontal padding around the page.",
|
|
12356
|
+
"default": "var(--a-space-5)"
|
|
12357
|
+
},
|
|
12358
|
+
"--integrations-page-py": {
|
|
12359
|
+
"description": "Vertical padding around the page.",
|
|
12360
|
+
"default": "var(--a-space-5)"
|
|
12361
|
+
},
|
|
12362
|
+
"--integrations-page-section-gap": {
|
|
12363
|
+
"description": "Vertical gap between sibling category sections.",
|
|
12364
|
+
"default": "var(--a-space-6)"
|
|
12365
|
+
},
|
|
12366
|
+
"--integrations-page-section-heading-fg": {
|
|
12367
|
+
"description": "Section heading color.",
|
|
12368
|
+
"default": "var(--a-fg-strong)"
|
|
12369
|
+
},
|
|
12370
|
+
"--integrations-page-section-heading-size": {
|
|
12371
|
+
"description": "Section heading font size.",
|
|
12372
|
+
"default": "var(--a-ui-sm)"
|
|
12373
|
+
},
|
|
12374
|
+
"--integrations-page-section-heading-weight": {
|
|
12375
|
+
"description": "Section heading font weight.",
|
|
12376
|
+
"default": "var(--a-weight-medium)"
|
|
12377
|
+
}
|
|
12378
|
+
},
|
|
12379
|
+
"traits": [],
|
|
12380
|
+
"version": 1
|
|
12381
|
+
}
|
|
12382
|
+
},
|
|
12383
|
+
"InvoiceDetail": {
|
|
12384
|
+
"title": "InvoiceDetail",
|
|
12385
|
+
"description": "Module-tier page composite that renders a single invoice — header\n(number + status badge + dates), line-items table, totals block,\ncustomer + remit-to blocks, and a slot-driven action toolbar.\nThe canonical invoice layout shared by billing-enabled products\nso totals math, status-badge color mapping, and action-toolbar\norder do not drift across surfaces.\n\nData-driven via the `invoice` property OR a `data-stream-src`\nendpoint. The composite stamps a six-region skeleton once on\nfirst connect — header · meta · parties · lines · totals ·\nfooter — then mutates per-region nodes via id-keyed in-place\ndiff on every property change. The status badge color maps\nfrom `invoice.status` (paid → success, past-due → warning,\nvoid → muted, open/draft → default). Action buttons are\nconsumer-slotted into `header-actions` per spec OD-002 (always\nslot, never stamp a default toolbar).\n\nPrint-friendly: an internal `@media print` branch hides the\naction toolbar + zeroes the page padding. The composite is a\ndisplay surface — extends UIElement, not UIFormElement.\n\nSpec: docs/specs/implementation-ready/SPEC-007-invoice-detail-page.md.\n",
|
|
12386
|
+
"type": "object",
|
|
12387
|
+
"allOf": [
|
|
12388
|
+
{
|
|
12389
|
+
"$ref": "#/$defs/ComponentCommon"
|
|
12390
|
+
},
|
|
12391
|
+
{
|
|
12392
|
+
"$ref": "#/$defs/CatalogComponentCommon"
|
|
12393
|
+
}
|
|
12394
|
+
],
|
|
12395
|
+
"properties": {
|
|
12396
|
+
"component": {
|
|
12397
|
+
"const": "InvoiceDetail"
|
|
12398
|
+
},
|
|
12399
|
+
"currency": {
|
|
12400
|
+
"description": "ISO 4217 currency code for amount formatting via\nIntl.NumberFormat. Overridable per-record via invoice.currency.\n",
|
|
12401
|
+
"type": "string",
|
|
12402
|
+
"default": "USD"
|
|
12403
|
+
},
|
|
12404
|
+
"data-stream-src": {
|
|
12405
|
+
"description": "Optional endpoint returning the invoice record (universal\ndata-stream-* trait). On successful load, `invoice` is\nreplaced and a `load` event fires; on failure an `error`\nevent fires.\n",
|
|
12406
|
+
"type": "string",
|
|
12407
|
+
"default": ""
|
|
12408
|
+
},
|
|
12409
|
+
"density": {
|
|
12410
|
+
"description": "Line-items table row density. `compact` for tightly-packed\ninvoices with many line items; `standard` for typical invoices.\nForwarded to the embedded <table-ui density>.\n",
|
|
12411
|
+
"type": "string",
|
|
12412
|
+
"enum": [
|
|
12413
|
+
"compact",
|
|
12414
|
+
"standard"
|
|
12415
|
+
],
|
|
12416
|
+
"default": "standard"
|
|
12417
|
+
},
|
|
12418
|
+
"invoice": {
|
|
12419
|
+
"description": "The invoice record. Source of truth for the rendered page.\nShape: {number, status, issuedAt, dueAt, customer:{name,email},\nremitTo?:{name,address?}, lines:[{description,qty,unitAmount,\namount}], subtotal, tax, discount?, total, currency,\nnotes?:string}. Null + no data-stream-src renders the empty\nstate.\n",
|
|
12420
|
+
"type": "object",
|
|
12421
|
+
"default": null
|
|
12422
|
+
},
|
|
12423
|
+
"loading": {
|
|
12424
|
+
"description": "Renders skeleton placeholders for header + line-items + totals\nwhile a data-stream-src fetch is in flight. Sets aria-busy\non the host. Data updates suppressed while [loading] is set.\n",
|
|
12425
|
+
"$ref": "#/$defs/DynamicBoolean"
|
|
12426
|
+
},
|
|
12427
|
+
"locale": {
|
|
12428
|
+
"description": "Locale for Intl.NumberFormat (amounts) and Intl.DateTimeFormat\n(issued/due). Defaults to document.documentElement.lang (or\n\"en-US\" when absent).\n",
|
|
12429
|
+
"type": "string",
|
|
12430
|
+
"default": ""
|
|
12431
|
+
},
|
|
12432
|
+
"printable": {
|
|
12433
|
+
"description": "Includes the @media print branch — hides the action toolbar\nand zeroes page padding so the printed output is invoice-only.\nSet [printable] to false on screens where the invoice is\nembedded inside a larger surface and printing should not be\na first-class action.\n",
|
|
12434
|
+
"type": "boolean",
|
|
12435
|
+
"default": true
|
|
12436
|
+
},
|
|
12437
|
+
"status": {
|
|
12438
|
+
"description": "Mirrors invoice.status. Drives the status badge `variant`\nmapping (paid → success, past-due → warning, void → muted,\nopen/draft → default). When set independently of `invoice`,\nthe host status reflection wins for CSS — useful when the\nhost wraps an invoice without a status field.\n",
|
|
12439
|
+
"$ref": "#/$defs/DynamicString"
|
|
12440
|
+
}
|
|
12441
|
+
},
|
|
12442
|
+
"required": [
|
|
12443
|
+
"component",
|
|
12444
|
+
"invoice"
|
|
12445
|
+
],
|
|
12446
|
+
"unevaluatedProperties": false,
|
|
12447
|
+
"x-adiaui": {
|
|
12448
|
+
"anti_patterns": [
|
|
12449
|
+
{
|
|
12450
|
+
"fix": "{\"component\": \"InvoiceDetail\", \"invoice\":\n {\"lines\": [...], \"subtotal\": 24, \"total\": 24.5, \"currency\": \"USD\"}}\n",
|
|
12451
|
+
"why": "Line items belong on `invoice.lines`, not the host. Without\nthe wrapping `invoice` object, totals + currency are unwired\nand the composite renders the empty state.\n",
|
|
12452
|
+
"wrong": "{\"component\": \"InvoiceDetail\", \"lines\": [...]}\n"
|
|
12453
|
+
},
|
|
12454
|
+
{
|
|
12455
|
+
"fix": "Open the invoice via <a href=\"/invoices/INV-001234\"> route\nnavigation; render the InvoiceDetail composite on that route.\n",
|
|
12456
|
+
"why": "Invoices are routes, not modals. Modal traps focus + clips\non long content; the composite is designed for full-page\nlayout.\n",
|
|
12457
|
+
"wrong": "{\"component\": \"Modal\", \"children\":\n [{\"component\": \"InvoiceDetail\", \"invoice\": {...}}]}\n"
|
|
12458
|
+
},
|
|
12459
|
+
{
|
|
12460
|
+
"fix": "<invoice-detail-ui status=\"paid\"></invoice-detail-ui>\n",
|
|
12461
|
+
"why": "`settled` is not in the status enum. Unknown statuses fall\nback to the default badge variant; the consumer surface\nloses the semantic color mapping.\n",
|
|
12462
|
+
"wrong": "<invoice-detail-ui status=\"settled\"></invoice-detail-ui>\n"
|
|
12463
|
+
}
|
|
12464
|
+
],
|
|
12465
|
+
"category": "container",
|
|
12466
|
+
"composes": [
|
|
12467
|
+
"card-ui",
|
|
12468
|
+
"table-ui",
|
|
12469
|
+
"stat-ui",
|
|
12470
|
+
"tag-ui",
|
|
12471
|
+
"button-ui",
|
|
12472
|
+
"text-ui",
|
|
12473
|
+
"icon-ui",
|
|
12474
|
+
"empty-state-ui"
|
|
12475
|
+
],
|
|
12476
|
+
"events": {
|
|
12477
|
+
"error": {
|
|
12478
|
+
"description": "Fired when a data-stream-src fetch fails OR when the host is\nasked to print but window.print is unavailable. Bubbles.\n",
|
|
12479
|
+
"detail": {
|
|
12480
|
+
"reason": {
|
|
12481
|
+
"description": "One of `fetch-failed`, `print-unavailable`.",
|
|
12482
|
+
"type": "string"
|
|
12483
|
+
}
|
|
12484
|
+
}
|
|
12485
|
+
},
|
|
12486
|
+
"invoice-action": {
|
|
12487
|
+
"description": "Fired when a header-action button carrying\n[data-invoice-action] is activated. Consumers wire this to\ndownload / send / pay / void flows. Bubbles.\n",
|
|
12488
|
+
"detail": {
|
|
12489
|
+
"action": {
|
|
12490
|
+
"description": "The data-invoice-action value (download, send, pay, etc.).",
|
|
12491
|
+
"type": "string"
|
|
12492
|
+
},
|
|
12493
|
+
"invoiceNumber": {
|
|
12494
|
+
"description": "invoice.number at the time of activation.",
|
|
12495
|
+
"type": "string"
|
|
12496
|
+
}
|
|
12497
|
+
}
|
|
12498
|
+
},
|
|
12499
|
+
"line-item-click": {
|
|
12500
|
+
"description": "Fired when a line-item row is clicked. Bubbles.\n",
|
|
12501
|
+
"detail": {
|
|
12502
|
+
"index": {
|
|
12503
|
+
"description": "0-based row index within invoice.lines.",
|
|
12504
|
+
"type": "integer"
|
|
12505
|
+
},
|
|
12506
|
+
"lineItem": {
|
|
12507
|
+
"description": "The clicked invoice.lines[index] record.",
|
|
12508
|
+
"type": "object"
|
|
12509
|
+
}
|
|
12510
|
+
}
|
|
12511
|
+
},
|
|
12512
|
+
"load": {
|
|
12513
|
+
"description": "Fired when a data-stream-src fetch resolves and the invoice\nrecord is populated. Bubbles.\n",
|
|
12514
|
+
"detail": {
|
|
12515
|
+
"invoiceNumber": {
|
|
12516
|
+
"description": "The loaded invoice.number.",
|
|
12517
|
+
"type": "string"
|
|
12518
|
+
}
|
|
12519
|
+
}
|
|
12520
|
+
}
|
|
12521
|
+
},
|
|
12522
|
+
"examples": [
|
|
12523
|
+
{
|
|
12524
|
+
"description": "A paid invoice with two line items + slotted actions.",
|
|
12525
|
+
"a2ui": "[\n {\n \"id\": \"inv-paid\",\n \"component\": \"InvoiceDetail\",\n \"status\": \"paid\",\n \"currency\": \"USD\",\n \"invoice\": {\n \"number\": \"INV-001234\",\n \"status\": \"paid\",\n \"issuedAt\": \"2026-05-01\",\n \"dueAt\": \"2026-05-15\",\n \"customer\": {\"name\": \"Acme Co.\", \"email\": \"billing@acme.test\"},\n \"lines\": [\n {\"description\": \"Pro plan — May\", \"qty\": 1, \"unitAmount\": 24.00, \"amount\": 24.00},\n {\"description\": \"Add-on — Audit log retention\", \"qty\": 1, \"unitAmount\": 0.50, \"amount\": 0.50}\n ],\n \"subtotal\": 24.50,\n \"tax\": 0,\n \"total\": 24.50,\n \"currency\": \"USD\"\n },\n \"children\": [\"btn-download\"]\n },\n {\"id\": \"btn-download\", \"component\": \"Button\",\n \"text\": \"Download\", \"slot\": \"header-actions\"}\n]\n",
|
|
12526
|
+
"name": "paid-invoice"
|
|
12527
|
+
},
|
|
12528
|
+
{
|
|
12529
|
+
"description": "Open invoice awaiting payment + Pay CTA.",
|
|
12530
|
+
"a2ui": "[\n {\n \"id\": \"inv-open\",\n \"component\": \"InvoiceDetail\",\n \"status\": \"open\",\n \"currency\": \"USD\",\n \"invoice\": {\n \"number\": \"INV-001235\",\n \"status\": \"open\",\n \"issuedAt\": \"2026-05-10\",\n \"dueAt\": \"2026-05-24\",\n \"customer\": {\"name\": \"Globex Corp.\", \"email\": \"ap@globex.test\"},\n \"lines\": [\n {\"description\": \"Team seats × 5\", \"qty\": 5, \"unitAmount\": 10.00, \"amount\": 50.00}\n ],\n \"subtotal\": 50.00,\n \"tax\": 5.00,\n \"total\": 55.00,\n \"currency\": \"USD\"\n },\n \"children\": [\"btn-pay-open\"]\n },\n {\"id\": \"btn-pay-open\", \"component\": \"Button\",\n \"text\": \"Pay $55\", \"variant\": \"primary\",\n \"slot\": \"header-actions\"}\n]\n",
|
|
12531
|
+
"name": "open-invoice"
|
|
12532
|
+
}
|
|
12533
|
+
],
|
|
12534
|
+
"keywords": [
|
|
12535
|
+
"invoice",
|
|
12536
|
+
"invoice-detail",
|
|
12537
|
+
"billing",
|
|
12538
|
+
"receipt",
|
|
12539
|
+
"bill",
|
|
12540
|
+
"statement",
|
|
12541
|
+
"payment",
|
|
12542
|
+
"line-items",
|
|
12543
|
+
"charges",
|
|
12544
|
+
"totals",
|
|
12545
|
+
"paid",
|
|
12546
|
+
"past-due",
|
|
12547
|
+
"void"
|
|
12548
|
+
],
|
|
12549
|
+
"name": "UIInvoiceDetail",
|
|
12550
|
+
"related": [
|
|
12551
|
+
"Card",
|
|
12552
|
+
"Table",
|
|
12553
|
+
"Stat",
|
|
12554
|
+
"Tag",
|
|
12555
|
+
"Button",
|
|
12556
|
+
"EmptyState",
|
|
12557
|
+
"PlanPicker"
|
|
12558
|
+
],
|
|
12559
|
+
"slots": {
|
|
12560
|
+
"customer-block": {
|
|
12561
|
+
"description": "Override the default customer block. When unset, the composite\nrenders a default block from invoice.customer.\n"
|
|
12562
|
+
},
|
|
12563
|
+
"footer": {
|
|
12564
|
+
"description": "Optional content below the totals — payment instructions,\nterms, fine print.\n"
|
|
12565
|
+
},
|
|
12566
|
+
"header-actions": {
|
|
12567
|
+
"description": "Action toolbar slotted into the top-right of the invoice\nheader — Download, Send, Pay, etc. Consumer-owned per\nSPEC-007 OD-002 (the composite NEVER stamps a default\ntoolbar; action sets vary too much across products).\nButtons carrying [data-invoice-action] dispatch the host's\n`invoice-action` event on activation.\n"
|
|
12568
|
+
},
|
|
12569
|
+
"remit-to-block": {
|
|
12570
|
+
"description": "Override the default remit-to block. When unset, the composite\nrenders a default block from invoice.remitTo if present.\n"
|
|
12571
|
+
}
|
|
12572
|
+
},
|
|
12573
|
+
"states": [
|
|
12574
|
+
{
|
|
12575
|
+
"description": "Default — invoice rendered, ready for interaction.",
|
|
12576
|
+
"name": "idle"
|
|
12577
|
+
},
|
|
12578
|
+
{
|
|
12579
|
+
"description": "A data-stream-src fetch is in flight.",
|
|
12580
|
+
"attribute": "loading",
|
|
12581
|
+
"name": "loading"
|
|
12582
|
+
},
|
|
12583
|
+
{
|
|
12584
|
+
"description": "No invoice + no data-stream-src.",
|
|
12585
|
+
"attribute": "empty",
|
|
12586
|
+
"name": "empty"
|
|
12587
|
+
},
|
|
12588
|
+
{
|
|
12589
|
+
"description": "Last data-stream-src fetch failed.",
|
|
12590
|
+
"attribute": "error",
|
|
12591
|
+
"name": "error"
|
|
12592
|
+
}
|
|
12593
|
+
],
|
|
12594
|
+
"status": "experimental",
|
|
12595
|
+
"synonyms": {
|
|
12596
|
+
"invoice": [
|
|
12597
|
+
"bill",
|
|
12598
|
+
"receipt",
|
|
12599
|
+
"statement"
|
|
12600
|
+
],
|
|
12601
|
+
"line-items": [
|
|
12602
|
+
"charges",
|
|
12603
|
+
"entries"
|
|
12604
|
+
],
|
|
12605
|
+
"payment": [
|
|
12606
|
+
"charge",
|
|
12607
|
+
"billing"
|
|
12608
|
+
]
|
|
12609
|
+
},
|
|
12610
|
+
"tag": "invoice-detail-ui",
|
|
12611
|
+
"tokens": {
|
|
12612
|
+
"--invoice-detail-amount-fg": {
|
|
12613
|
+
"description": "Color for monetary amounts in the totals stack.",
|
|
12614
|
+
"default": "var(--a-fg)"
|
|
12615
|
+
},
|
|
12616
|
+
"--invoice-detail-bg": {
|
|
12617
|
+
"description": "Host page background. Defaults to transparent.",
|
|
12618
|
+
"default": "transparent"
|
|
12619
|
+
},
|
|
12620
|
+
"--invoice-detail-line-amount-align": {
|
|
12621
|
+
"description": "Text-align for the rightmost amount column in the lines table.\n`end` for typical right-aligned numerics.\n",
|
|
12622
|
+
"default": "end"
|
|
12623
|
+
},
|
|
12624
|
+
"--invoice-detail-meta-fg": {
|
|
12625
|
+
"description": "Color for the secondary header metadata (issued / due).",
|
|
12626
|
+
"default": "var(--a-fg-muted)"
|
|
12627
|
+
},
|
|
12628
|
+
"--invoice-detail-page-padding": {
|
|
12629
|
+
"description": "Inset around the invoice content area.",
|
|
12630
|
+
"default": "var(--a-space-5)"
|
|
12631
|
+
},
|
|
12632
|
+
"--invoice-detail-section-gap": {
|
|
12633
|
+
"description": "Vertical gap between header, parties, lines, totals.",
|
|
12634
|
+
"default": "var(--a-space-5)"
|
|
12635
|
+
},
|
|
12636
|
+
"--invoice-detail-status-badge-radius": {
|
|
12637
|
+
"description": "Status badge corner radius.",
|
|
12638
|
+
"default": "var(--a-radius-md)"
|
|
12639
|
+
},
|
|
12640
|
+
"--invoice-detail-total-size": {
|
|
12641
|
+
"description": "Font size for the grand total line.",
|
|
12642
|
+
"default": "var(--a-text-2xl, 1.5rem)"
|
|
12643
|
+
},
|
|
12644
|
+
"--invoice-detail-total-weight": {
|
|
12645
|
+
"description": "Font weight for the grand total line.",
|
|
12646
|
+
"default": "var(--a-weight-bold, 700)"
|
|
12647
|
+
},
|
|
12648
|
+
"--invoice-detail-totals-width": {
|
|
12649
|
+
"description": "Width of the right-aligned totals stack. Clamps to 100% on\nnarrow viewports.\n",
|
|
12650
|
+
"default": "min(360px, 100%)"
|
|
12651
|
+
}
|
|
12652
|
+
},
|
|
12653
|
+
"traits": [],
|
|
12654
|
+
"version": 1
|
|
12655
|
+
}
|
|
12656
|
+
},
|
|
12657
|
+
"InvoiceHistory": {
|
|
12658
|
+
"title": "InvoiceHistory",
|
|
12659
|
+
"description": "Canonical billing-list composite — a pre-configured <table-ui> with\ninvoice-shaped columns (number, issued, due, amount, status, actions),\nstatus-badge cell renderer (paid/open/past-due/void/draft → semantic\nbadge variant), currency cell renderer, optional search + filter\nchips via <table-toolbar-ui>, and a row-click that navigates to the\ninvoice detail page.\n\nWraps <table-ui> with billing-shaped columns + cell renderers + a\nCSV-export toolbar. Consumer passes invoices[]; the composite owns\ncolumn shape, status-to-badge mapping, currency formatting, date\nformatting, and navigation. Sibling to SPEC-007 (invoice detail).\n\nEach invoice record: {id, number, status, issuedAt, dueAt, amount,\ncurrency}. status MUST be one of \"draft\" | \"open\" | \"paid\" |\n\"past-due\" | \"void\"; unknown values fall back to a neutral badge.\n\nSpec: docs/specs/implementation-ready/SPEC-008-invoice-history-table.md.\n",
|
|
12660
|
+
"type": "object",
|
|
12661
|
+
"allOf": [
|
|
12662
|
+
{
|
|
12663
|
+
"$ref": "#/$defs/ComponentCommon"
|
|
12664
|
+
},
|
|
12665
|
+
{
|
|
12666
|
+
"$ref": "#/$defs/CatalogComponentCommon"
|
|
12667
|
+
}
|
|
12668
|
+
],
|
|
12669
|
+
"properties": {
|
|
12670
|
+
"component": {
|
|
12671
|
+
"const": "InvoiceHistory"
|
|
12672
|
+
},
|
|
12673
|
+
"currency": {
|
|
12674
|
+
"description": "Default ISO 4217 currency code for amount formatting. Overridable\nper-row via invoices[].currency.\n",
|
|
12675
|
+
"type": "string",
|
|
12676
|
+
"default": "USD"
|
|
12677
|
+
},
|
|
12678
|
+
"data-stream-src": {
|
|
12679
|
+
"description": "Optional endpoint returning the `invoices` array (universal\ndata-stream-* trait). On successful load, `invoices` is replaced\nand a `load` event fires; on failure an `error` event fires.\n",
|
|
12680
|
+
"type": "string",
|
|
12681
|
+
"default": ""
|
|
12682
|
+
},
|
|
12683
|
+
"density": {
|
|
12684
|
+
"description": "Row density, forwarded to <table-ui>. `compact` for dense lists,\n`standard` for default rows, `comfortable` for spacious rows.\n",
|
|
12685
|
+
"type": "string",
|
|
12686
|
+
"enum": [
|
|
12687
|
+
"compact",
|
|
12688
|
+
"standard",
|
|
12689
|
+
"comfortable"
|
|
12690
|
+
],
|
|
12691
|
+
"default": "standard"
|
|
12692
|
+
},
|
|
12693
|
+
"exportable": {
|
|
12694
|
+
"description": "When set, the default toolbar carries an \"Export CSV\" button.\nConsumers overriding the toolbar via slot=\"toolbar\" can omit\nthis and stamp their own export affordance.\n",
|
|
12695
|
+
"type": "boolean",
|
|
12696
|
+
"default": true
|
|
12697
|
+
},
|
|
12698
|
+
"filter": {
|
|
12699
|
+
"description": "Active status filter — narrows visible rows to a single status\nbucket. Empty string = show all. Mirrors the toolbar chip-group\nselection state.\n",
|
|
12700
|
+
"$ref": "#/$defs/DynamicString"
|
|
12701
|
+
},
|
|
12702
|
+
"hrefPattern": {
|
|
12703
|
+
"description": "URL template for row-click navigation. The literal `{number}` is\nreplaced with the invoice's number on click. Defaults to\n`/invoices/{number}`.\n",
|
|
12704
|
+
"type": "string",
|
|
12705
|
+
"default": "/invoices/{number}"
|
|
12706
|
+
},
|
|
12707
|
+
"invoices": {
|
|
12708
|
+
"description": "Array of invoice records. Source of truth for the rendered rows.\nShape per record: {id, number, status, issuedAt, dueAt, amount,\ncurrency?}. status must be one of \"draft\" | \"open\" | \"paid\" |\n\"past-due\" | \"void\". Empty array renders the empty-state.\n",
|
|
12709
|
+
"$ref": "#/$defs/DynamicStringList"
|
|
12710
|
+
},
|
|
12711
|
+
"loading": {
|
|
12712
|
+
"description": "Forwarded to <table-ui> — renders skeleton rows instead of data\nwhile a fetch is in flight.\n",
|
|
12713
|
+
"$ref": "#/$defs/DynamicBoolean"
|
|
12714
|
+
},
|
|
12715
|
+
"locale": {
|
|
12716
|
+
"description": "Locale for Intl.NumberFormat (amount) and Intl.DateTimeFormat\n(issuedAt / dueAt). Defaults to document.documentElement.lang\n(or \"en-US\" when absent).\n",
|
|
12717
|
+
"type": "string",
|
|
12718
|
+
"default": ""
|
|
12719
|
+
},
|
|
12720
|
+
"paginate": {
|
|
12721
|
+
"description": "Rows per page, forwarded to <table-ui>. 0 = show all rows.\n",
|
|
12722
|
+
"type": "number",
|
|
12723
|
+
"default": 25
|
|
12724
|
+
},
|
|
12725
|
+
"selectable": {
|
|
12726
|
+
"description": "When set, enables row selection via a leading checkbox column on\nthe underlying <table-ui> (bulk-action surface).\n",
|
|
12727
|
+
"type": "boolean",
|
|
12728
|
+
"default": false
|
|
12729
|
+
}
|
|
12730
|
+
},
|
|
12731
|
+
"required": [
|
|
12732
|
+
"component",
|
|
12733
|
+
"invoices"
|
|
12734
|
+
],
|
|
12735
|
+
"unevaluatedProperties": false,
|
|
12736
|
+
"x-adiaui": {
|
|
12737
|
+
"anti_patterns": [
|
|
12738
|
+
{
|
|
12739
|
+
"fix": "<invoice-history-ui .invoices=\"${rows}\"></invoice-history-ui>\n",
|
|
12740
|
+
"why": "Hand-rolled billing list. Reinvents the canonical composite,\ndrifts on status-badge mapping, currency formatting, and\ndate format.\n",
|
|
12741
|
+
"wrong": "<table-ui sortable>\n <col-def key=\"number\" label=\"Invoice\"></col-def>\n <col-def key=\"status\" label=\"Status\"></col-def>\n</table-ui>\n"
|
|
12742
|
+
},
|
|
12743
|
+
{
|
|
12744
|
+
"fix": "<invoice-history-ui .invoices=\"${rows}\"></invoice-history-ui>\n",
|
|
12745
|
+
"why": "Columns are owned by the composite. Custom columns belong on a\ndifferent <table-ui> composition.\n",
|
|
12746
|
+
"wrong": "<invoice-history-ui .columns=\"${customColumns}\"\n .invoices=\"${rows}\"></invoice-history-ui>\n"
|
|
12747
|
+
}
|
|
12748
|
+
],
|
|
12749
|
+
"category": "display",
|
|
12750
|
+
"composes": [
|
|
12751
|
+
"table-ui",
|
|
12752
|
+
"table-toolbar-ui",
|
|
12753
|
+
"badge-ui",
|
|
12754
|
+
"button-ui",
|
|
12755
|
+
"empty-state-ui",
|
|
12756
|
+
"pagination-ui"
|
|
12757
|
+
],
|
|
12758
|
+
"events": {
|
|
12759
|
+
"error": {
|
|
12760
|
+
"description": "Fired when a `data-stream-src` fetch fails. Bubbles.\n",
|
|
12761
|
+
"detail": {
|
|
12762
|
+
"reason": {
|
|
12763
|
+
"description": "One of `fetch-failed`.",
|
|
12764
|
+
"type": "string"
|
|
12765
|
+
}
|
|
12766
|
+
}
|
|
12767
|
+
},
|
|
12768
|
+
"invoice-export": {
|
|
12769
|
+
"description": "Fired when the default \"Export CSV\" toolbar button is pressed.\nDetail carries the generated blob; consumers may preventDefault\nto suppress the default download. Bubbles.\n",
|
|
12770
|
+
"detail": {
|
|
12771
|
+
"blob": {
|
|
12772
|
+
"description": "The generated text/csv Blob.",
|
|
12773
|
+
"type": "object"
|
|
12774
|
+
},
|
|
12775
|
+
"rowCount": {
|
|
12776
|
+
"description": "Number of rows in the export.",
|
|
12777
|
+
"type": "integer"
|
|
12778
|
+
}
|
|
12779
|
+
}
|
|
12780
|
+
},
|
|
12781
|
+
"invoice-filter-change": {
|
|
12782
|
+
"description": "Fired when the status filter changes via the toolbar chip group.\nBubbles.\n",
|
|
12783
|
+
"detail": {
|
|
12784
|
+
"filter": {
|
|
12785
|
+
"description": "New status filter value (empty string = all).",
|
|
12786
|
+
"type": "string",
|
|
12787
|
+
"enum": [
|
|
12788
|
+
"",
|
|
12789
|
+
"draft",
|
|
12790
|
+
"open",
|
|
12791
|
+
"paid",
|
|
12792
|
+
"past-due",
|
|
12793
|
+
"void"
|
|
12794
|
+
]
|
|
12795
|
+
},
|
|
12796
|
+
"previous": {
|
|
12797
|
+
"description": "Previous filter value.",
|
|
12798
|
+
"type": "string"
|
|
12799
|
+
}
|
|
12800
|
+
}
|
|
12801
|
+
},
|
|
12802
|
+
"invoice-row-click": {
|
|
12803
|
+
"description": "Fired when an invoice row is activated (mouse click or keyboard\nEnter / Space). Listener can preventDefault() to suppress the\ndefault `window.location.assign(href)` navigation. Bubbles.\n",
|
|
12804
|
+
"detail": {
|
|
12805
|
+
"href": {
|
|
12806
|
+
"description": "Resolved navigation URL.",
|
|
12807
|
+
"type": "string"
|
|
12808
|
+
},
|
|
12809
|
+
"invoice": {
|
|
12810
|
+
"description": "The invoice record under the clicked row.",
|
|
12811
|
+
"type": "object"
|
|
12812
|
+
}
|
|
12813
|
+
}
|
|
12814
|
+
},
|
|
12815
|
+
"invoice-selection-change": {
|
|
12816
|
+
"description": "Fired when row selection changes (only when `selectable` is set).\nBubbles.\n",
|
|
12817
|
+
"detail": {
|
|
12818
|
+
"selected": {
|
|
12819
|
+
"description": "Array of selected invoice records.",
|
|
12820
|
+
"type": "array"
|
|
12821
|
+
}
|
|
12822
|
+
}
|
|
12823
|
+
},
|
|
12824
|
+
"load": {
|
|
12825
|
+
"description": "Fired when `data-stream-src` finishes a successful fetch and\n`invoices` is populated. Bubbles.\n",
|
|
12826
|
+
"detail": {
|
|
12827
|
+
"count": {
|
|
12828
|
+
"description": "Number of invoices loaded.",
|
|
12829
|
+
"type": "integer"
|
|
12830
|
+
}
|
|
12831
|
+
}
|
|
12832
|
+
}
|
|
12833
|
+
},
|
|
12834
|
+
"examples": [
|
|
12835
|
+
{
|
|
12836
|
+
"description": "6-column billing list with status badges, currency formatting, and pagination.",
|
|
12837
|
+
"a2ui": "[\n {\n \"id\": \"inv-hist-1\",\n \"component\": \"InvoiceHistory\",\n \"currency\": \"USD\",\n \"paginate\": 25,\n \"invoices\": [\n {\"id\":\"i1\",\"number\":\"INV-001234\",\"status\":\"paid\",\"issuedAt\":\"2026-05-01\",\"dueAt\":\"2026-05-15\",\"amount\":24.50},\n {\"id\":\"i2\",\"number\":\"INV-001235\",\"status\":\"open\",\"issuedAt\":\"2026-05-08\",\"dueAt\":\"2026-05-22\",\"amount\":24.50},\n {\"id\":\"i3\",\"number\":\"INV-001236\",\"status\":\"past-due\",\"issuedAt\":\"2026-04-15\",\"dueAt\":\"2026-04-29\",\"amount\":24.50}\n ]\n }\n]\n",
|
|
12838
|
+
"name": "canonical"
|
|
12839
|
+
},
|
|
12840
|
+
{
|
|
12841
|
+
"description": "Server-streamed invoices via data-stream-src.",
|
|
12842
|
+
"a2ui": "[\n {\n \"id\": \"inv-hist-stream\",\n \"component\": \"InvoiceHistory\",\n \"data-stream-src\": \"/api/invoices\",\n \"currency\": \"USD\",\n \"paginate\": 50\n }\n]\n",
|
|
12843
|
+
"name": "streamed"
|
|
12844
|
+
}
|
|
12845
|
+
],
|
|
12846
|
+
"keywords": [
|
|
12847
|
+
"invoice",
|
|
12848
|
+
"invoices",
|
|
12849
|
+
"billing",
|
|
12850
|
+
"invoice-history",
|
|
12851
|
+
"invoice-list",
|
|
12852
|
+
"payments-history",
|
|
12853
|
+
"receipt",
|
|
12854
|
+
"receipts",
|
|
12855
|
+
"statement",
|
|
12856
|
+
"statements",
|
|
12857
|
+
"subscription",
|
|
12858
|
+
"charges",
|
|
12859
|
+
"past-due",
|
|
12860
|
+
"paid",
|
|
12861
|
+
"billing-list",
|
|
12862
|
+
"billing-table",
|
|
12863
|
+
"download-invoice",
|
|
12864
|
+
"export-invoices"
|
|
12865
|
+
],
|
|
12866
|
+
"name": "InvoiceHistory",
|
|
12867
|
+
"related": [
|
|
12868
|
+
"Table",
|
|
12869
|
+
"TableToolbar",
|
|
12870
|
+
"Badge",
|
|
12871
|
+
"Button",
|
|
12872
|
+
"EmptyState",
|
|
12873
|
+
"Pagination"
|
|
12874
|
+
],
|
|
12875
|
+
"slots": {
|
|
12876
|
+
"empty": {
|
|
12877
|
+
"description": "Custom empty-state content when `invoices` is empty. Falls back\nto a default <empty-state-ui icon=\"receipt\"> when omitted.\n"
|
|
12878
|
+
},
|
|
12879
|
+
"toolbar": {
|
|
12880
|
+
"description": "Optional pre-table action toolbar — overrides the default\n<table-toolbar-ui> + export button stamp. Use when the host\nsurface needs custom actions (e.g. \"New invoice\", \"Reconcile\").\n"
|
|
12881
|
+
}
|
|
12882
|
+
},
|
|
12883
|
+
"states": [
|
|
12884
|
+
{
|
|
12885
|
+
"description": "Default — rows rendered, ready for interaction.",
|
|
12886
|
+
"name": "idle"
|
|
12887
|
+
},
|
|
12888
|
+
{
|
|
12889
|
+
"description": "A `data-stream-src` fetch is in flight.",
|
|
12890
|
+
"attribute": "loading",
|
|
12891
|
+
"name": "loading"
|
|
12892
|
+
},
|
|
12893
|
+
{
|
|
12894
|
+
"description": "No invoices to render (computed from invoices.length).",
|
|
12895
|
+
"attribute": "empty",
|
|
12896
|
+
"name": "empty"
|
|
12897
|
+
},
|
|
12898
|
+
{
|
|
12899
|
+
"description": "Last `data-stream-src` fetch failed.",
|
|
12900
|
+
"attribute": "error",
|
|
12901
|
+
"name": "error"
|
|
12902
|
+
}
|
|
12903
|
+
],
|
|
12904
|
+
"status": "experimental",
|
|
12905
|
+
"synonyms": {
|
|
12906
|
+
"billing": [
|
|
12907
|
+
"invoice",
|
|
12908
|
+
"payment",
|
|
12909
|
+
"subscription"
|
|
12910
|
+
],
|
|
12911
|
+
"history": [
|
|
12912
|
+
"log",
|
|
12913
|
+
"audit",
|
|
12914
|
+
"record",
|
|
12915
|
+
"timeline"
|
|
12916
|
+
],
|
|
12917
|
+
"invoice": [
|
|
12918
|
+
"bill",
|
|
12919
|
+
"statement",
|
|
12920
|
+
"receipt"
|
|
12921
|
+
],
|
|
12922
|
+
"receipts": [
|
|
12923
|
+
"invoices",
|
|
12924
|
+
"billing"
|
|
12925
|
+
],
|
|
12926
|
+
"statement": [
|
|
12927
|
+
"invoice",
|
|
12928
|
+
"bill"
|
|
12929
|
+
]
|
|
12930
|
+
},
|
|
12931
|
+
"tag": "invoice-history-ui",
|
|
12932
|
+
"tokens": {
|
|
12933
|
+
"--invoice-history-amount-fg": {
|
|
12934
|
+
"description": "Amount cell foreground.",
|
|
12935
|
+
"default": "var(--a-fg-strong, var(--a-fg))"
|
|
12936
|
+
},
|
|
12937
|
+
"--invoice-history-amount-font": {
|
|
12938
|
+
"description": "Font family for tabular amounts; defaults to the mono stack.",
|
|
12939
|
+
"default": "var(--a-font-mono)"
|
|
12940
|
+
},
|
|
12941
|
+
"--invoice-history-bg": {
|
|
12942
|
+
"description": "Host background. Defaults to transparent.",
|
|
12943
|
+
"default": "transparent"
|
|
12944
|
+
},
|
|
12945
|
+
"--invoice-history-date-fg": {
|
|
12946
|
+
"description": "Secondary metadata (issued / due dates) foreground.",
|
|
12947
|
+
"default": "var(--a-fg-muted)"
|
|
12948
|
+
},
|
|
12949
|
+
"--invoice-history-filter-gap": {
|
|
12950
|
+
"description": "Gap between status-filter chips.",
|
|
12951
|
+
"default": "var(--a-space-2)"
|
|
12952
|
+
},
|
|
12953
|
+
"--invoice-history-gap": {
|
|
12954
|
+
"description": "Vertical gap between toolbar / table / pagination regions.",
|
|
12955
|
+
"default": "var(--a-space-3)"
|
|
12956
|
+
},
|
|
12957
|
+
"--invoice-history-row-min-height": {
|
|
12958
|
+
"description": "Forwarded as `--table-row-h` to <table-ui>; row minimum height.",
|
|
12959
|
+
"default": "var(--table-row-h, 3rem)"
|
|
12960
|
+
},
|
|
12961
|
+
"--invoice-history-toolbar-gap": {
|
|
12962
|
+
"description": "Gap between toolbar clusters (title · filter chips · export).",
|
|
12963
|
+
"default": "var(--a-space-3)"
|
|
12964
|
+
}
|
|
12965
|
+
},
|
|
12966
|
+
"traits": [],
|
|
12967
|
+
"version": 1
|
|
12968
|
+
}
|
|
12969
|
+
},
|
|
12970
|
+
"Kbd": {
|
|
12971
|
+
"title": "Kbd",
|
|
12972
|
+
"description": "Keyboard key cap. Purely decorative, content from innerHTML — typically a single key or short chord like \"⌘K\" or \"Ctrl+Shift+P\". Use inline in menu items, tooltips, command hints, and shortcut documentation.",
|
|
12973
|
+
"type": "object",
|
|
12974
|
+
"allOf": [
|
|
12975
|
+
{
|
|
12976
|
+
"$ref": "#/$defs/ComponentCommon"
|
|
12977
|
+
},
|
|
12978
|
+
{
|
|
12979
|
+
"$ref": "#/$defs/CatalogComponentCommon"
|
|
12980
|
+
}
|
|
12981
|
+
],
|
|
12982
|
+
"properties": {
|
|
12983
|
+
"component": {
|
|
12984
|
+
"const": "Kbd"
|
|
12985
|
+
},
|
|
12986
|
+
"size": {
|
|
12987
|
+
"description": "Sizing scale (compact tier — sm / md only).",
|
|
12988
|
+
"type": "string",
|
|
12989
|
+
"enum": [
|
|
12990
|
+
"sm",
|
|
12991
|
+
"md"
|
|
12992
|
+
],
|
|
12993
|
+
"default": ""
|
|
12994
|
+
}
|
|
12995
|
+
},
|
|
12996
|
+
"required": [
|
|
12997
|
+
"component"
|
|
12998
|
+
],
|
|
12999
|
+
"unevaluatedProperties": false,
|
|
13000
|
+
"x-adiaui": {
|
|
13001
|
+
"anti_patterns": [],
|
|
13002
|
+
"category": "display",
|
|
13003
|
+
"composes": [],
|
|
13004
|
+
"events": {},
|
|
13005
|
+
"examples": [
|
|
13006
|
+
{
|
|
13007
|
+
"description": "Card displaying a grid of keyboard shortcut rows with key badges and descriptions.",
|
|
13008
|
+
"a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"Card\",\n \"children\": [\n \"hdr\",\n \"sec\"\n ]\n },\n {\n \"id\": \"hdr\",\n \"component\": \"Header\",\n \"children\": [\n \"title\"\n ]\n },\n {\n \"id\": \"title\",\n \"component\": \"Text\",\n \"slot\": \"heading\",\n \"textContent\": \"Keyboard Shortcuts\"\n },\n {\n \"id\": \"sec\",\n \"component\": \"Section\",\n \"children\": [\n \"grid\"\n ]\n },\n {\n \"id\": \"grid\",\n \"component\": \"Grid\",\n \"columns\": 1,\n \"gap\": \"2\",\n \"children\": [\n \"r1\",\n \"r2\",\n \"r3\",\n \"r4\",\n \"r5\",\n \"r6\"\n ]\n },\n {\n \"id\": \"r1\",\n \"component\": \"Row\",\n \"children\": [\n \"k1\",\n \"d1\"\n ]\n },\n {\n \"id\": \"k1\",\n \"component\": \"Kbd\",\n \"text\": \"Ctrl+K\"\n },\n {\n \"id\": \"d1\",\n \"component\": \"Text\",\n \"textContent\": \"Open command palette\"\n },\n {\n \"id\": \"r2\",\n \"component\": \"Row\",\n \"children\": [\n \"k2\",\n \"d2\"\n ]\n },\n {\n \"id\": \"k2\",\n \"component\": \"Kbd\",\n \"text\": \"Ctrl+S\"\n },\n {\n \"id\": \"d2\",\n \"component\": \"Text\",\n \"textContent\": \"Save current file\"\n },\n {\n \"id\": \"r3\",\n \"component\": \"Row\",\n \"children\": [\n \"k3\",\n \"d3\"\n ]\n },\n {\n \"id\": \"k3\",\n \"component\": \"Kbd\",\n \"text\": \"Ctrl+Z\"\n },\n {\n \"id\": \"d3\",\n \"component\": \"Text\",\n \"textContent\": \"Undo last action\"\n },\n {\n \"id\": \"r4\",\n \"component\": \"Row\",\n \"children\": [\n \"k4\",\n \"d4\"\n ]\n },\n {\n \"id\": \"k4\",\n \"component\": \"Kbd\",\n \"text\": \"Ctrl+Shift+P\"\n },\n {\n \"id\": \"d4\",\n \"component\": \"Text\",\n \"textContent\": \"Toggle preview\"\n },\n {\n \"id\": \"r5\",\n \"component\": \"Row\",\n \"children\": [\n \"k5\",\n \"d5\"\n ]\n },\n {\n \"id\": \"k5\",\n \"component\": \"Kbd\",\n \"text\": \"Ctrl+N\"\n },\n {\n \"id\": \"d5\",\n \"component\": \"Text\",\n \"textContent\": \"Create new document\"\n },\n {\n \"id\": \"r6\",\n \"component\": \"Row\",\n \"children\": [\n \"k6\",\n \"d6\"\n ]\n },\n {\n \"id\": \"k6\",\n \"component\": \"Kbd\",\n \"text\": \"Esc\"\n },\n {\n \"id\": \"d6\",\n \"component\": \"Text\",\n \"textContent\": \"Close dialog\"\n }\n]",
|
|
13009
|
+
"name": "kbd-shortcuts"
|
|
13010
|
+
}
|
|
13011
|
+
],
|
|
13012
|
+
"keywords": [
|
|
13013
|
+
"kbd",
|
|
13014
|
+
"command",
|
|
13015
|
+
"shortcut",
|
|
13016
|
+
"hotkey",
|
|
13017
|
+
"keyboard",
|
|
13018
|
+
"keybinding"
|
|
13019
|
+
],
|
|
13020
|
+
"name": "UIKbd",
|
|
13021
|
+
"related": [
|
|
13022
|
+
"grid"
|
|
13023
|
+
],
|
|
13024
|
+
"slots": {
|
|
13025
|
+
"default": {
|
|
13026
|
+
"description": "Key label text"
|
|
13027
|
+
}
|
|
13028
|
+
},
|
|
13029
|
+
"states": [
|
|
13030
|
+
{
|
|
13031
|
+
"description": "Default, ready for interaction.",
|
|
13032
|
+
"name": "idle"
|
|
13033
|
+
}
|
|
13034
|
+
],
|
|
13035
|
+
"status": "stable",
|
|
13036
|
+
"synonyms": {
|
|
13037
|
+
"command": [
|
|
13038
|
+
"command",
|
|
13039
|
+
"palette",
|
|
13040
|
+
"kbd",
|
|
13041
|
+
"shortcut"
|
|
13042
|
+
],
|
|
13043
|
+
"hotkey": [
|
|
13044
|
+
"kbd",
|
|
13045
|
+
"shortcut",
|
|
13046
|
+
"command"
|
|
13047
|
+
],
|
|
13048
|
+
"keybinding": [
|
|
13049
|
+
"kbd",
|
|
13050
|
+
"shortcut",
|
|
13051
|
+
"command"
|
|
13052
|
+
],
|
|
13053
|
+
"keyboard": [
|
|
13054
|
+
"kbd",
|
|
13055
|
+
"shortcut",
|
|
13056
|
+
"command"
|
|
13057
|
+
],
|
|
13058
|
+
"shortcut": [
|
|
13059
|
+
"kbd",
|
|
13060
|
+
"shortcut",
|
|
13061
|
+
"command"
|
|
13062
|
+
],
|
|
13063
|
+
"tags": [
|
|
13064
|
+
"Keyboard"
|
|
13065
|
+
]
|
|
13066
|
+
},
|
|
13067
|
+
"tag": "kbd-ui",
|
|
13068
|
+
"tokens": {},
|
|
11460
13069
|
"traits": [],
|
|
11461
13070
|
"version": 1
|
|
11462
13071
|
}
|
|
@@ -12111,6 +13720,180 @@
|
|
|
12111
13720
|
"version": 1
|
|
12112
13721
|
}
|
|
12113
13722
|
},
|
|
13723
|
+
"LoadingOverlay": {
|
|
13724
|
+
"title": "LoadingOverlay",
|
|
13725
|
+
"description": "Container-scoped busy overlay. Covers a positioned parent region with a centered spinner (auto-stamped) or slotted indicator (skeleton-ui, progress-ui, custom) while async work is in flight. Wires aria-busy onto the parent on connect; applies a [delay] grace window to avoid flash on fast loads. For viewport-scoped / route loaders use a dedicated route-loader pattern; for submit-button busy use <button-ui loading>.",
|
|
13726
|
+
"type": "object",
|
|
13727
|
+
"allOf": [
|
|
13728
|
+
{
|
|
13729
|
+
"$ref": "#/$defs/ComponentCommon"
|
|
13730
|
+
},
|
|
13731
|
+
{
|
|
13732
|
+
"$ref": "#/$defs/CatalogComponentCommon"
|
|
13733
|
+
}
|
|
13734
|
+
],
|
|
13735
|
+
"properties": {
|
|
13736
|
+
"active": {
|
|
13737
|
+
"description": "When set, overlay is visible and the parent container is marked aria-busy. Toggle from consumer code; default hidden.",
|
|
13738
|
+
"$ref": "#/$defs/DynamicBoolean"
|
|
13739
|
+
},
|
|
13740
|
+
"component": {
|
|
13741
|
+
"const": "LoadingOverlay"
|
|
13742
|
+
},
|
|
13743
|
+
"delay": {
|
|
13744
|
+
"description": "Suppress the overlay until this many ms elapse. Prevents flash on fast loads. Default 200ms.",
|
|
13745
|
+
"$ref": "#/$defs/DynamicNumber"
|
|
13746
|
+
},
|
|
13747
|
+
"label": {
|
|
13748
|
+
"description": "Accessible operation name used by the host aria-label and forwarded to the auto-stamped spinner.",
|
|
13749
|
+
"$ref": "#/$defs/DynamicString"
|
|
13750
|
+
},
|
|
13751
|
+
"variant": {
|
|
13752
|
+
"description": "Backdrop treatment — default (muted scrim), transparent (no backdrop fill — useful with full-area skeleton indicators), blur (light scrim with backdrop-filter blur).",
|
|
13753
|
+
"$ref": "#/$defs/DynamicString"
|
|
13754
|
+
}
|
|
13755
|
+
},
|
|
13756
|
+
"required": [
|
|
13757
|
+
"component"
|
|
13758
|
+
],
|
|
13759
|
+
"unevaluatedProperties": false,
|
|
13760
|
+
"x-adiaui": {
|
|
13761
|
+
"anti_patterns": [
|
|
13762
|
+
{
|
|
13763
|
+
"fix": "{\"component\": \"Card\", \"children\": [\n {\"component\": \"LoadingOverlay\", \"active\": true},\n {\"component\": \"Table\", \"data-stream-src\": \"...\"}\n]}\n",
|
|
13764
|
+
"why": "LoadingOverlay is container-scoped. Attaching it directly to Page\ncovers the entire viewport but lacks the route-loader's wiring\n(skeleton routing, route-level animation). Use the route loader.\n",
|
|
13765
|
+
"wrong": "{\"component\": \"Page\", \"children\": [\n {\"component\": \"LoadingOverlay\", \"active\": true}\n]}\n"
|
|
13766
|
+
},
|
|
13767
|
+
{
|
|
13768
|
+
"fix": "{\"component\": \"Modal\", \"open\": true, \"loading\": true}\n",
|
|
13769
|
+
"why": "Modal owns its own busy state and focus trap; nesting a\nLoadingOverlay introduces two competing inert toggles.\n",
|
|
13770
|
+
"wrong": "{\"component\": \"Modal\", \"open\": true, \"children\": [\n {\"component\": \"LoadingOverlay\", \"active\": true}\n]}\n"
|
|
13771
|
+
},
|
|
13772
|
+
{
|
|
13773
|
+
"fix": "{\"component\": \"Form\", \"children\": [\n {\"component\": \"Button\", \"text\": \"Submitting\", \"type\": \"submit\", \"loading\": true, \"disabled\": true}\n]}\n",
|
|
13774
|
+
"why": "A form-submit affordance belongs on the button itself, not as an\noverlay over the entire form region. Use Button[loading].\n",
|
|
13775
|
+
"wrong": "{\"component\": \"Form\", \"children\": [\n {\"component\": \"Button\", \"text\": \"Submit\", \"type\": \"submit\"},\n {\"component\": \"LoadingOverlay\", \"active\": true}\n]}\n"
|
|
13776
|
+
}
|
|
13777
|
+
],
|
|
13778
|
+
"category": "feedback",
|
|
13779
|
+
"composes": [],
|
|
13780
|
+
"events": {},
|
|
13781
|
+
"examples": [
|
|
13782
|
+
{
|
|
13783
|
+
"description": "Card containing a table that loads on mount; the overlay covers the card's body while data streams.",
|
|
13784
|
+
"a2ui": "[\n {\n \"id\": \"card\",\n \"component\": \"Card\",\n \"children\": [\"sec\"]\n },\n {\n \"id\": \"sec\",\n \"component\": \"Section\",\n \"children\": [\"overlay\", \"table\"]\n },\n {\n \"id\": \"overlay\",\n \"component\": \"LoadingOverlay\",\n \"active\": true,\n \"label\": \"Loading orders…\"\n },\n {\n \"id\": \"table\",\n \"component\": \"Table\",\n \"data-stream-src\": \"/api/orders\"\n }\n]",
|
|
13785
|
+
"name": "card-with-loading-table"
|
|
13786
|
+
},
|
|
13787
|
+
{
|
|
13788
|
+
"description": "Skeleton-shaped placeholder overlay using the transparent variant — slot a stack of <Skeleton> rows.",
|
|
13789
|
+
"a2ui": "[\n {\n \"id\": \"ov\",\n \"component\": \"LoadingOverlay\",\n \"active\": true,\n \"variant\": \"transparent\",\n \"label\": \"Loading content…\",\n \"children\": [\"sk-stack\"]\n },\n {\n \"id\": \"sk-stack\",\n \"component\": \"Column\",\n \"gap\": \"2\",\n \"children\": [\"sk1\", \"sk2\", \"sk3\"]\n },\n {\n \"id\": \"sk1\",\n \"component\": \"Skeleton\",\n \"width\": \"100%\",\n \"height\": \"1rem\"\n },\n {\n \"id\": \"sk2\",\n \"component\": \"Skeleton\",\n \"width\": \"80%\",\n \"height\": \"1rem\"\n },\n {\n \"id\": \"sk3\",\n \"component\": \"Skeleton\",\n \"width\": \"60%\",\n \"height\": \"1rem\"\n }\n]",
|
|
13790
|
+
"name": "skeleton-overlay"
|
|
13791
|
+
},
|
|
13792
|
+
{
|
|
13793
|
+
"description": "Overlay with the default 200ms grace window. If the underlying load resolves in less than 200ms, the overlay never paints.",
|
|
13794
|
+
"a2ui": "[\n {\n \"id\": \"ov\",\n \"component\": \"LoadingOverlay\",\n \"active\": true,\n \"delay\": 200,\n \"label\": \"Loading\"\n }\n]",
|
|
13795
|
+
"name": "fast-load-no-flash"
|
|
13796
|
+
}
|
|
13797
|
+
],
|
|
13798
|
+
"keywords": [
|
|
13799
|
+
"loading",
|
|
13800
|
+
"overlay",
|
|
13801
|
+
"busy",
|
|
13802
|
+
"spinner",
|
|
13803
|
+
"skeleton",
|
|
13804
|
+
"placeholder",
|
|
13805
|
+
"feedback",
|
|
13806
|
+
"progress",
|
|
13807
|
+
"indicator",
|
|
13808
|
+
"wait"
|
|
13809
|
+
],
|
|
13810
|
+
"name": "UILoadingOverlay",
|
|
13811
|
+
"related": [
|
|
13812
|
+
"Spinner",
|
|
13813
|
+
"Skeleton",
|
|
13814
|
+
"Progress",
|
|
13815
|
+
"Card",
|
|
13816
|
+
"Table",
|
|
13817
|
+
"Modal"
|
|
13818
|
+
],
|
|
13819
|
+
"slots": {
|
|
13820
|
+
"default": {
|
|
13821
|
+
"description": "Busy indicator content — <spinner-ui>, <skeleton-ui>, <progress-ui>, or custom. If empty, a centered <spinner-ui size=\"lg\"> is auto-stamped."
|
|
13822
|
+
}
|
|
13823
|
+
},
|
|
13824
|
+
"states": [
|
|
13825
|
+
{
|
|
13826
|
+
"description": "Default, hidden. Parent interactive.",
|
|
13827
|
+
"name": "idle"
|
|
13828
|
+
},
|
|
13829
|
+
{
|
|
13830
|
+
"description": "Overlay visible; parent has aria-busy=\"true\".",
|
|
13831
|
+
"attribute": "active",
|
|
13832
|
+
"name": "active"
|
|
13833
|
+
}
|
|
13834
|
+
],
|
|
13835
|
+
"status": "stable",
|
|
13836
|
+
"synonyms": {
|
|
13837
|
+
"busy": [
|
|
13838
|
+
"loading",
|
|
13839
|
+
"overlay",
|
|
13840
|
+
"busy",
|
|
13841
|
+
"spinner"
|
|
13842
|
+
],
|
|
13843
|
+
"loader": [
|
|
13844
|
+
"loading",
|
|
13845
|
+
"overlay",
|
|
13846
|
+
"spinner"
|
|
13847
|
+
],
|
|
13848
|
+
"loading": [
|
|
13849
|
+
"loading",
|
|
13850
|
+
"overlay",
|
|
13851
|
+
"busy",
|
|
13852
|
+
"spinner",
|
|
13853
|
+
"skeleton"
|
|
13854
|
+
],
|
|
13855
|
+
"overlay": [
|
|
13856
|
+
"loading",
|
|
13857
|
+
"overlay",
|
|
13858
|
+
"busy"
|
|
13859
|
+
],
|
|
13860
|
+
"spinner": [
|
|
13861
|
+
"loading",
|
|
13862
|
+
"overlay",
|
|
13863
|
+
"spinner"
|
|
13864
|
+
]
|
|
13865
|
+
},
|
|
13866
|
+
"tag": "loading-overlay-ui",
|
|
13867
|
+
"tokens": {
|
|
13868
|
+
"--loading-overlay-bg": {
|
|
13869
|
+
"description": "Backdrop fill color. Default uses the generic neutral scrim token.",
|
|
13870
|
+
"default": "var(--a-scrim-default)"
|
|
13871
|
+
},
|
|
13872
|
+
"--loading-overlay-duration": {
|
|
13873
|
+
"description": "Fade in / fade out duration.",
|
|
13874
|
+
"default": "var(--a-duration)"
|
|
13875
|
+
},
|
|
13876
|
+
"--loading-overlay-easing": {
|
|
13877
|
+
"description": "Fade easing curve.",
|
|
13878
|
+
"default": "var(--a-easing-out)"
|
|
13879
|
+
},
|
|
13880
|
+
"--loading-overlay-gap": {
|
|
13881
|
+
"description": "Vertical gap between the indicator and any sibling content (e.g. label, skeleton stack).",
|
|
13882
|
+
"default": "var(--a-space-3)"
|
|
13883
|
+
},
|
|
13884
|
+
"--loading-overlay-radius": {
|
|
13885
|
+
"description": "Backdrop corner radius. Matches the parent surface by default.",
|
|
13886
|
+
"default": "var(--a-radius-md)"
|
|
13887
|
+
},
|
|
13888
|
+
"--loading-overlay-z": {
|
|
13889
|
+
"description": "Stacking order. Sits above sibling content, below modal-ui (which uses ::backdrop on top-layer dialog).",
|
|
13890
|
+
"default": "50"
|
|
13891
|
+
}
|
|
13892
|
+
},
|
|
13893
|
+
"traits": [],
|
|
13894
|
+
"version": 1
|
|
13895
|
+
}
|
|
13896
|
+
},
|
|
12114
13897
|
"Menu": {
|
|
12115
13898
|
"title": "Menu",
|
|
12116
13899
|
"description": "Dropdown action menu with roving focus and keyboard navigation. Uses Popover API.",
|
|
@@ -12202,6 +13985,9 @@
|
|
|
12202
13985
|
"slots": {
|
|
12203
13986
|
"default": {
|
|
12204
13987
|
"description": "Menu items with role=\"menuitem\" and optional <hr> dividers"
|
|
13988
|
+
},
|
|
13989
|
+
"trigger": {
|
|
13990
|
+
"description": "Required. Focusable element that opens the menu when activated. Exactly one child must have slot=\"trigger\" — typically <button-ui>, but any focusable element works. Without it the menu cannot open via keyboard or pointer. Lives in light DOM; the items are hoisted to a top-layer popover on open."
|
|
12205
13991
|
}
|
|
12206
13992
|
},
|
|
12207
13993
|
"states": [
|
|
@@ -13103,13 +14889,256 @@
|
|
|
13103
14889
|
"bezier-wire"
|
|
13104
14890
|
]
|
|
13105
14891
|
},
|
|
13106
|
-
"tag": "noodles-ui",
|
|
14892
|
+
"tag": "noodles-ui",
|
|
14893
|
+
"tokens": {
|
|
14894
|
+
"--noodles-duration": {
|
|
14895
|
+
"description": "Transition duration for noodle animations"
|
|
14896
|
+
},
|
|
14897
|
+
"--noodles-easing": {
|
|
14898
|
+
"description": "Easing function for noodle animations"
|
|
14899
|
+
}
|
|
14900
|
+
},
|
|
14901
|
+
"traits": [],
|
|
14902
|
+
"version": 1
|
|
14903
|
+
}
|
|
14904
|
+
},
|
|
14905
|
+
"NotificationPreferences": {
|
|
14906
|
+
"title": "NotificationPreferences",
|
|
14907
|
+
"description": "Page-level Settings composite: a matrix of notification types (rows)\n× delivery channels (columns: in-app, email, SMS) with a binary\n<check-ui> in each cell and an optional <switch-ui> column-header\nmaster toggle for bulk-flipping a channel across every row.\n\nForm-bearing — the composite extends UIFormElement and serializes its\ncurrent preferences shape as JSON on `value`. Per first-principle #2\n(\"save is the consumer's job\"), the composite does NOT mutate the\npassed-in `preferences` array; it emits a typed `change` event per\ncell toggle and a `bulk-toggle` event per column-header switch, and\nexposes the staged JSON via the form value so a host <form> submit\ncarries it through ElementInternals.\n\nChannels are columns; types are rows (the smaller-set / larger-set\ninvariant — channels are 3-5 in the wild, types are 10-50). Layout\nrenders as a semantic ARIA grid (`role=\"table\"`/`row`/`cell`/\n`rowheader`/`columnheader`) — NOT native `<table>` (per the HTML\nparser strip rule, table-content tags would foster-parent out of a\ncustom-element subtree).\n\nSpec: docs/specs/implementation-ready/SPEC-064-notification-preferences.md.\n",
|
|
14908
|
+
"type": "object",
|
|
14909
|
+
"allOf": [
|
|
14910
|
+
{
|
|
14911
|
+
"$ref": "#/$defs/ComponentCommon"
|
|
14912
|
+
},
|
|
14913
|
+
{
|
|
14914
|
+
"$ref": "#/$defs/CatalogComponentCommon"
|
|
14915
|
+
}
|
|
14916
|
+
],
|
|
14917
|
+
"properties": {
|
|
14918
|
+
"channelEnabled": {
|
|
14919
|
+
"description": "Map of channel-key → master-toggle boolean for the column-header\n<switch-ui>. When omitted, master toggles default to `true` for\nevery channel. Independent of cell values — toggling the master\noff does NOT auto-update the cells; the host receives a\n`bulk-toggle` event and updates `preferences` itself.\n",
|
|
14920
|
+
"type": "object",
|
|
14921
|
+
"default": {}
|
|
14922
|
+
},
|
|
14923
|
+
"channels": {
|
|
14924
|
+
"description": "Column definitions — one record per delivery channel. Each\ncarries a stable `key`, a `label` (the column header), and an\noptional `icon` name (Phosphor — defaults to no icon when\nabsent). Example: [{key:\"in-app\", label:\"In-app\", icon:\"chat-circle\"},\n{key:\"email\", label:\"Email\", icon:\"envelope\"}]. Empty array\nrenders nothing (the matrix needs at least one column).\n",
|
|
14925
|
+
"$ref": "#/$defs/DynamicStringList"
|
|
14926
|
+
},
|
|
14927
|
+
"component": {
|
|
14928
|
+
"const": "NotificationPreferences"
|
|
14929
|
+
},
|
|
14930
|
+
"disabled": {
|
|
14931
|
+
"description": "All cells + master toggles become non-interactive.",
|
|
14932
|
+
"type": "boolean",
|
|
14933
|
+
"default": false
|
|
14934
|
+
},
|
|
14935
|
+
"group-by": {
|
|
14936
|
+
"description": "Row-grouping mode. `none` (default) renders all rows in one\nblock. `group` renders one section per unique `preferences[].group`\nvalue with a header row above each section.\n",
|
|
14937
|
+
"type": "string",
|
|
14938
|
+
"enum": [
|
|
14939
|
+
"none",
|
|
14940
|
+
"group"
|
|
14941
|
+
],
|
|
14942
|
+
"default": "none"
|
|
14943
|
+
},
|
|
14944
|
+
"loading": {
|
|
14945
|
+
"description": "Renders a skeleton matrix overlay. Cells become non-interactive\nand dim while loading.\n",
|
|
14946
|
+
"type": "boolean",
|
|
14947
|
+
"default": false
|
|
14948
|
+
},
|
|
14949
|
+
"preferences": {
|
|
14950
|
+
"description": "Matrix data — one row per notification type. Each record carries\na stable `key`, a `label`, optional `description` (rendered under\nthe label), optional `group` (when `group-by=\"group\"`), and a\n`channels` map keyed by channel key with boolean values.\nExample: {key:\"mentions\", label:\"Mentions\", channels:{\"in-app\":true,\nemail:false, sms:false}}. Empty array renders the empty state.\n",
|
|
14951
|
+
"$ref": "#/$defs/DynamicStringList"
|
|
14952
|
+
}
|
|
14953
|
+
},
|
|
14954
|
+
"required": [
|
|
14955
|
+
"component",
|
|
14956
|
+
"preferences",
|
|
14957
|
+
"channels"
|
|
14958
|
+
],
|
|
14959
|
+
"unevaluatedProperties": false,
|
|
14960
|
+
"x-adiaui": {
|
|
14961
|
+
"anti_patterns": [
|
|
14962
|
+
{
|
|
14963
|
+
"fix": "<notification-preferences-ui id=\"prefs\"></notification-preferences-ui>\n<script>\n document.querySelector('#prefs').channels = [\n {key:'email', label:'Email'}\n ];\n document.querySelector('#prefs').preferences = [\n {key:'mentions', label:'Mentions', channels:{email:true}},\n {key:'replies', label:'Replies', channels:{email:false}}\n ];\n</script>\n",
|
|
14964
|
+
"why": "Cells are generated from the `preferences` matrix. Slotted\nswitches are ignored and the host renders empty.\n",
|
|
14965
|
+
"wrong": "<notification-preferences-ui>\n <switch-ui label=\"Email mentions\"></switch-ui>\n <switch-ui label=\"Email replies\"></switch-ui>\n</notification-preferences-ui>\n"
|
|
14966
|
+
},
|
|
14967
|
+
{
|
|
14968
|
+
"fix": "<notification-preferences-ui id=\"prefs\"></notification-preferences-ui>\n<script>/* set channels + preferences here */</script>\n",
|
|
14969
|
+
"why": "Re-implements the matrix in raw HTML — loses the typed\n`change` / `bulk-toggle` event contract, the column-master\nswitch, the group-by support, and the consistent token-driven\nvisual treatment. Worse, table-content tags inside a custom\nelement subtree are foster-parented out of the DOM by the HTML\nparser — they silently vanish.\n",
|
|
14970
|
+
"wrong": "<table>\n <thead><tr><th></th><th>Email</th></tr></thead>\n <tbody>\n <tr><th>Mentions</th><td><check-ui></check-ui></td></tr>\n </tbody>\n</table>\n"
|
|
14971
|
+
}
|
|
14972
|
+
],
|
|
14973
|
+
"category": "container",
|
|
14974
|
+
"composes": [
|
|
14975
|
+
"check-ui",
|
|
14976
|
+
"switch-ui",
|
|
14977
|
+
"icon-ui",
|
|
14978
|
+
"text-ui",
|
|
14979
|
+
"empty-state-ui"
|
|
14980
|
+
],
|
|
14981
|
+
"events": {
|
|
14982
|
+
"bulk-toggle": {
|
|
14983
|
+
"description": "Fired when the user toggles a column-header <switch-ui>.\nBubbles. Mirrors `change` shape but for the column master —\nhost applies the bulk change to its own `preferences` data.\n",
|
|
14984
|
+
"detail": {
|
|
14985
|
+
"channel": {
|
|
14986
|
+
"description": "The `key` of the channel column whose master flipped.",
|
|
14987
|
+
"type": "string"
|
|
14988
|
+
},
|
|
14989
|
+
"enabled": {
|
|
14990
|
+
"description": "The new desired master state.",
|
|
14991
|
+
"type": "boolean"
|
|
14992
|
+
}
|
|
14993
|
+
}
|
|
14994
|
+
},
|
|
14995
|
+
"change": {
|
|
14996
|
+
"description": "Fired when the user toggles a cell <check-ui>. Bubbles. The\ncomposite emits this with the previous state — the host must\napply the new state to its own data and re-pass `preferences`\nfor the cell to visually update.\n",
|
|
14997
|
+
"detail": {
|
|
14998
|
+
"channel": {
|
|
14999
|
+
"description": "The `key` of the channel column whose cell flipped.",
|
|
15000
|
+
"type": "string"
|
|
15001
|
+
},
|
|
15002
|
+
"enabled": {
|
|
15003
|
+
"description": "The new desired state (true = opted in).",
|
|
15004
|
+
"type": "boolean"
|
|
15005
|
+
},
|
|
15006
|
+
"row": {
|
|
15007
|
+
"description": "The `key` of the notification type whose cell flipped.",
|
|
15008
|
+
"type": "string"
|
|
15009
|
+
}
|
|
15010
|
+
}
|
|
15011
|
+
}
|
|
15012
|
+
},
|
|
15013
|
+
"examples": [
|
|
15014
|
+
{
|
|
15015
|
+
"description": "Three channels (in-app / email / SMS) × four notification types.",
|
|
15016
|
+
"a2ui": "[\n {\n \"id\": \"np-default\",\n \"component\": \"NotificationPreferences\",\n \"name\": \"notifications\",\n \"channels\": [\n {\"key\": \"in-app\", \"label\": \"In-app\", \"icon\": \"chat-circle\"},\n {\"key\": \"email\", \"label\": \"Email\", \"icon\": \"envelope\"},\n {\"key\": \"sms\", \"label\": \"SMS\", \"icon\": \"device-mobile\"}\n ],\n \"preferences\": [\n {\"key\": \"mentions\", \"label\": \"Mentions\",\n \"channels\": {\"in-app\": true, \"email\": true, \"sms\": false}},\n {\"key\": \"comments\", \"label\": \"Comments\",\n \"channels\": {\"in-app\": true, \"email\": false, \"sms\": false}},\n {\"key\": \"releases\", \"label\": \"Releases\",\n \"channels\": {\"in-app\": false,\"email\": true, \"sms\": false}},\n {\"key\": \"security\", \"label\": \"Security alerts\",\n \"channels\": {\"in-app\": true, \"email\": true, \"sms\": true}}\n ]\n }\n]\n",
|
|
15017
|
+
"name": "default"
|
|
15018
|
+
},
|
|
15019
|
+
{
|
|
15020
|
+
"description": "Same matrix grouped by category via group-by=\"group\".",
|
|
15021
|
+
"a2ui": "[\n {\n \"id\": \"np-grouped\",\n \"component\": \"NotificationPreferences\",\n \"name\": \"notifications\",\n \"groupBy\": \"group\",\n \"channels\": [\n {\"key\": \"in-app\", \"label\": \"In-app\"},\n {\"key\": \"email\", \"label\": \"Email\"}\n ],\n \"preferences\": [\n {\"key\": \"mentions\", \"label\": \"Mentions\", \"group\": \"Activity\",\n \"channels\": {\"in-app\": true, \"email\": true}},\n {\"key\": \"comments\", \"label\": \"Comments\", \"group\": \"Activity\",\n \"channels\": {\"in-app\": true, \"email\": false}},\n {\"key\": \"digest\", \"label\": \"Weekly digest\", \"group\": \"Summaries\",\n \"channels\": {\"in-app\": false, \"email\": true}}\n ]\n }\n]\n",
|
|
15022
|
+
"name": "grouped"
|
|
15023
|
+
}
|
|
15024
|
+
],
|
|
15025
|
+
"keywords": [
|
|
15026
|
+
"notification-preferences",
|
|
15027
|
+
"notifications",
|
|
15028
|
+
"preferences",
|
|
15029
|
+
"opt-in",
|
|
15030
|
+
"opt-out",
|
|
15031
|
+
"alerts",
|
|
15032
|
+
"channels",
|
|
15033
|
+
"in-app",
|
|
15034
|
+
"email",
|
|
15035
|
+
"sms",
|
|
15036
|
+
"subscriptions",
|
|
15037
|
+
"notification-settings"
|
|
15038
|
+
],
|
|
15039
|
+
"name": "UINotificationPreferences",
|
|
15040
|
+
"related": [
|
|
15041
|
+
"Check",
|
|
15042
|
+
"Switch",
|
|
15043
|
+
"Table",
|
|
15044
|
+
"EmptyState",
|
|
15045
|
+
"Icon",
|
|
15046
|
+
"Text"
|
|
15047
|
+
],
|
|
15048
|
+
"slots": {
|
|
15049
|
+
"empty": {
|
|
15050
|
+
"description": "Custom empty-state copy shown when `preferences` is empty. Falls\nback to a default <empty-state-ui> when not provided.\n"
|
|
15051
|
+
},
|
|
15052
|
+
"footer": {
|
|
15053
|
+
"description": "Optional content below the matrix — e.g. a global Save Changes\nbutton row or fine-print disclaimer. Falls back to nothing.\n"
|
|
15054
|
+
},
|
|
15055
|
+
"header": {
|
|
15056
|
+
"description": "Optional content above the matrix — e.g. a page title, intro\ncopy, or per-page save row. Falls back to nothing when empty.\n"
|
|
15057
|
+
}
|
|
15058
|
+
},
|
|
15059
|
+
"states": [
|
|
15060
|
+
{
|
|
15061
|
+
"description": "Default — matrix rendered, ready for interaction.",
|
|
15062
|
+
"name": "idle"
|
|
15063
|
+
},
|
|
15064
|
+
{
|
|
15065
|
+
"description": "Skeleton overlay while data loads.",
|
|
15066
|
+
"attribute": "loading",
|
|
15067
|
+
"name": "loading"
|
|
15068
|
+
},
|
|
15069
|
+
{
|
|
15070
|
+
"description": "All toggles non-interactive.",
|
|
15071
|
+
"attribute": "disabled",
|
|
15072
|
+
"name": "disabled"
|
|
15073
|
+
},
|
|
15074
|
+
{
|
|
15075
|
+
"description": "No notification types configured.",
|
|
15076
|
+
"attribute": "empty",
|
|
15077
|
+
"name": "empty"
|
|
15078
|
+
}
|
|
15079
|
+
],
|
|
15080
|
+
"status": "stable",
|
|
15081
|
+
"synonyms": {
|
|
15082
|
+
"channels": [
|
|
15083
|
+
"delivery",
|
|
15084
|
+
"destinations"
|
|
15085
|
+
],
|
|
15086
|
+
"notifications": [
|
|
15087
|
+
"alerts",
|
|
15088
|
+
"messages",
|
|
15089
|
+
"updates"
|
|
15090
|
+
],
|
|
15091
|
+
"preferences": [
|
|
15092
|
+
"settings",
|
|
15093
|
+
"opt-ins",
|
|
15094
|
+
"subscriptions"
|
|
15095
|
+
]
|
|
15096
|
+
},
|
|
15097
|
+
"tag": "notification-preferences-ui",
|
|
13107
15098
|
"tokens": {
|
|
13108
|
-
"--
|
|
13109
|
-
"description": "
|
|
15099
|
+
"--notification-preferences-bg": {
|
|
15100
|
+
"description": "Host background.",
|
|
15101
|
+
"default": "var(--a-bg)"
|
|
13110
15102
|
},
|
|
13111
|
-
"--
|
|
13112
|
-
"description": "
|
|
15103
|
+
"--notification-preferences-border": {
|
|
15104
|
+
"description": "Row separator color.",
|
|
15105
|
+
"default": "var(--a-border-subtle)"
|
|
15106
|
+
},
|
|
15107
|
+
"--notification-preferences-channel-width": {
|
|
15108
|
+
"description": "Minimum column width for each channel cell.",
|
|
15109
|
+
"default": "var(--a-space-9)"
|
|
15110
|
+
},
|
|
15111
|
+
"--notification-preferences-group-fg": {
|
|
15112
|
+
"description": "Group-heading label color.",
|
|
15113
|
+
"default": "var(--a-fg-muted)"
|
|
15114
|
+
},
|
|
15115
|
+
"--notification-preferences-px": {
|
|
15116
|
+
"description": "Host horizontal padding.",
|
|
15117
|
+
"default": "var(--a-space-5)"
|
|
15118
|
+
},
|
|
15119
|
+
"--notification-preferences-py": {
|
|
15120
|
+
"description": "Host vertical padding.",
|
|
15121
|
+
"default": "var(--a-space-5)"
|
|
15122
|
+
},
|
|
15123
|
+
"--notification-preferences-radius": {
|
|
15124
|
+
"description": "Outer matrix container radius.",
|
|
15125
|
+
"default": "var(--a-radius-md)"
|
|
15126
|
+
},
|
|
15127
|
+
"--notification-preferences-row-bg": {
|
|
15128
|
+
"description": "Even-row zebra background.",
|
|
15129
|
+
"default": "var(--a-bg-muted)"
|
|
15130
|
+
},
|
|
15131
|
+
"--notification-preferences-row-label-min": {
|
|
15132
|
+
"description": "Minimum row-label column width.",
|
|
15133
|
+
"default": "12rem"
|
|
15134
|
+
},
|
|
15135
|
+
"--notification-preferences-row-px": {
|
|
15136
|
+
"description": "Per-cell horizontal padding.",
|
|
15137
|
+
"default": "var(--a-space-3)"
|
|
15138
|
+
},
|
|
15139
|
+
"--notification-preferences-row-py": {
|
|
15140
|
+
"description": "Per-row vertical padding.",
|
|
15141
|
+
"default": "var(--a-space-3)"
|
|
13113
15142
|
}
|
|
13114
15143
|
},
|
|
13115
15144
|
"traits": [],
|
|
@@ -13917,85 +15946,499 @@
|
|
|
13917
15946
|
],
|
|
13918
15947
|
"unevaluatedProperties": false,
|
|
13919
15948
|
"x-adiaui": {
|
|
13920
|
-
"anti_patterns": [],
|
|
13921
|
-
"category": "navigation",
|
|
13922
|
-
"composes": [],
|
|
15949
|
+
"anti_patterns": [],
|
|
15950
|
+
"category": "navigation",
|
|
15951
|
+
"composes": [],
|
|
15952
|
+
"events": {
|
|
15953
|
+
"page-change": {
|
|
15954
|
+
"description": "Fired when a page button is clicked. detail contains { page }.",
|
|
15955
|
+
"detail": {
|
|
15956
|
+
"page": {
|
|
15957
|
+
"description": "New page number.",
|
|
15958
|
+
"type": "number"
|
|
15959
|
+
}
|
|
15960
|
+
}
|
|
15961
|
+
}
|
|
15962
|
+
},
|
|
15963
|
+
"examples": [
|
|
15964
|
+
{
|
|
15965
|
+
"description": "Card with header containing title and search input, table component, and pagination footer.",
|
|
15966
|
+
"a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"Card\",\n \"size\": \"lg\",\n \"children\": [\n \"hdr\",\n \"sec\",\n \"ftr\"\n ]\n },\n {\n \"id\": \"hdr\",\n \"component\": \"Header\",\n \"children\": [\n \"title-row\"\n ]\n },\n {\n \"id\": \"title-row\",\n \"component\": \"Row\",\n \"children\": [\n \"title\",\n \"search\"\n ],\n \"gap\": \"4\"\n },\n {\n \"id\": \"title\",\n \"component\": \"Text\",\n \"slot\": \"heading\",\n \"textContent\": \"Data Table\",\n \"variant\": \"section\"\n },\n {\n \"id\": \"search\",\n \"component\": \"Input\",\n \"placeholder\": \"Search...\",\n \"type\": \"search\",\n \"name\": \"search\"\n },\n {\n \"id\": \"sec\",\n \"component\": \"Section\",\n \"children\": [\n \"tbl\"\n ]\n },\n {\n \"id\": \"tbl\",\n \"component\": \"Table\",\n \"sortable\": true\n },\n {\n \"id\": \"ftr\",\n \"component\": \"Footer\",\n \"children\": [\n \"pager\"\n ]\n },\n {\n \"id\": \"pager\",\n \"component\": \"Pagination\",\n \"total\": 10,\n \"page\": 1\n }\n]",
|
|
15967
|
+
"name": "data-table-view"
|
|
15968
|
+
},
|
|
15969
|
+
{
|
|
15970
|
+
"description": "Row with centered pagination component for navigating paged content.",
|
|
15971
|
+
"a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"Row\",\n \"justify\": \"center\",\n \"children\": [\n \"pager\"\n ]\n },\n {\n \"id\": \"pager\",\n \"component\": \"Pagination\",\n \"total\": 10,\n \"page\": 1\n }\n]",
|
|
15972
|
+
"name": "pagination-nav"
|
|
15973
|
+
}
|
|
15974
|
+
],
|
|
15975
|
+
"keywords": [
|
|
15976
|
+
"pagination",
|
|
15977
|
+
"navigation",
|
|
15978
|
+
"back",
|
|
15979
|
+
"paginate",
|
|
15980
|
+
"paging"
|
|
15981
|
+
],
|
|
15982
|
+
"name": "UIPagination",
|
|
15983
|
+
"related": [
|
|
15984
|
+
"input",
|
|
15985
|
+
"table"
|
|
15986
|
+
],
|
|
15987
|
+
"slots": {},
|
|
15988
|
+
"states": [
|
|
15989
|
+
{
|
|
15990
|
+
"description": "Default, ready for interaction.",
|
|
15991
|
+
"name": "idle"
|
|
15992
|
+
}
|
|
15993
|
+
],
|
|
15994
|
+
"status": "stable",
|
|
15995
|
+
"synonyms": {
|
|
15996
|
+
"back": [
|
|
15997
|
+
"breadcrumb",
|
|
15998
|
+
"nav",
|
|
15999
|
+
"pagination"
|
|
16000
|
+
],
|
|
16001
|
+
"navigation": [
|
|
16002
|
+
"nav",
|
|
16003
|
+
"sidebar",
|
|
16004
|
+
"breadcrumb",
|
|
16005
|
+
"tabs",
|
|
16006
|
+
"menu",
|
|
16007
|
+
"pagination"
|
|
16008
|
+
],
|
|
16009
|
+
"paginate": [
|
|
16010
|
+
"pagination",
|
|
16011
|
+
"nav",
|
|
16012
|
+
"table"
|
|
16013
|
+
],
|
|
16014
|
+
"paging": [
|
|
16015
|
+
"pagination",
|
|
16016
|
+
"nav"
|
|
16017
|
+
]
|
|
16018
|
+
},
|
|
16019
|
+
"tag": "pagination-ui",
|
|
16020
|
+
"tokens": {},
|
|
16021
|
+
"traits": [],
|
|
16022
|
+
"version": 1
|
|
16023
|
+
}
|
|
16024
|
+
},
|
|
16025
|
+
"Pane": {
|
|
16026
|
+
"title": "Pane",
|
|
16027
|
+
"description": "Collapsible, resizable content panel — drag-resize handle on the\ninner edge when [side=\"leading\"] / [side=\"trailing\"], [resizable]\nopt-in. Used standalone for resizable two-pane layouts, or wrapped\nby <editor-sidebar> / <admin-sidebar> which DELEGATE drag to the\ninner pane-ui rather than reimplementing it. See pane.yaml's\na2ui.rules for the full composition contract.\n",
|
|
16028
|
+
"type": "object",
|
|
16029
|
+
"allOf": [
|
|
16030
|
+
{
|
|
16031
|
+
"$ref": "#/$defs/ComponentCommon"
|
|
16032
|
+
},
|
|
16033
|
+
{
|
|
16034
|
+
"$ref": "#/$defs/CatalogComponentCommon"
|
|
16035
|
+
}
|
|
16036
|
+
],
|
|
16037
|
+
"properties": {
|
|
16038
|
+
"collapsed": {
|
|
16039
|
+
"description": "Component property: collapsed.",
|
|
16040
|
+
"type": "boolean",
|
|
16041
|
+
"default": false
|
|
16042
|
+
},
|
|
16043
|
+
"component": {
|
|
16044
|
+
"const": "Pane"
|
|
16045
|
+
},
|
|
16046
|
+
"maxWidth": {
|
|
16047
|
+
"description": "Component property: maxWidth.",
|
|
16048
|
+
"type": "number",
|
|
16049
|
+
"default": 9999
|
|
16050
|
+
},
|
|
16051
|
+
"minWidth": {
|
|
16052
|
+
"description": "Component property: minWidth.",
|
|
16053
|
+
"type": "number",
|
|
16054
|
+
"default": 200
|
|
16055
|
+
},
|
|
16056
|
+
"resizable": {
|
|
16057
|
+
"description": "Component property: resizable.",
|
|
16058
|
+
"type": "boolean",
|
|
16059
|
+
"default": false
|
|
16060
|
+
},
|
|
16061
|
+
"side": {
|
|
16062
|
+
"description": "Opts a pane into horizontal-sibling chrome: suppresses the default\nfour-sided border and moves the resize grabber to the inner edge\n(right edge for `leading`, left edge for `trailing`). Also flips the\nresize-drag direction so `trailing` panes grow when dragged leftward.\nUnset keeps the pane-intrinsic chrome (full border, right-edge\ngrabber when resizable).\n",
|
|
16063
|
+
"type": "string",
|
|
16064
|
+
"enum": [
|
|
16065
|
+
"",
|
|
16066
|
+
"leading",
|
|
16067
|
+
"trailing"
|
|
16068
|
+
],
|
|
16069
|
+
"default": ""
|
|
16070
|
+
}
|
|
16071
|
+
},
|
|
16072
|
+
"required": [
|
|
16073
|
+
"component"
|
|
16074
|
+
],
|
|
16075
|
+
"unevaluatedProperties": false,
|
|
16076
|
+
"x-adiaui": {
|
|
16077
|
+
"anti_patterns": [],
|
|
16078
|
+
"category": "layout",
|
|
16079
|
+
"composes": [
|
|
16080
|
+
"icon-ui"
|
|
16081
|
+
],
|
|
16082
|
+
"events": {
|
|
16083
|
+
"toggle": {
|
|
16084
|
+
"description": "Fired when the pane's collapsed state flips (via button press, keyboard, or programmatic toggle()). Bubbles."
|
|
16085
|
+
}
|
|
16086
|
+
},
|
|
16087
|
+
"examples": [
|
|
16088
|
+
{
|
|
16089
|
+
"description": "Split pane with TextArea for editing markdown on the left and a preview card on the right.",
|
|
16090
|
+
"a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"Row\",\n \"children\": [\n \"left\",\n \"right\"\n ]\n },\n {\n \"id\": \"left\",\n \"component\": \"Pane\",\n \"resizable\": true,\n \"width\": \"50%\",\n \"children\": [\n \"editor-card\"\n ]\n },\n {\n \"id\": \"editor-card\",\n \"component\": \"Card\",\n \"children\": [\n \"ed-hdr\",\n \"ed-sec\"\n ]\n },\n {\n \"id\": \"ed-hdr\",\n \"component\": \"Header\",\n \"children\": [\n \"ed-title\"\n ]\n },\n {\n \"id\": \"ed-title\",\n \"component\": \"Text\",\n \"slot\": \"heading\",\n \"textContent\": \"Editor\"\n },\n {\n \"id\": \"ed-sec\",\n \"component\": \"Section\",\n \"children\": [\n \"textarea\"\n ]\n },\n {\n \"id\": \"textarea\",\n \"component\": \"TextArea\",\n \"placeholder\": \"Write your markdown here...\",\n \"rows\": 20\n },\n {\n \"id\": \"right\",\n \"component\": \"Pane\",\n \"resizable\": true,\n \"width\": \"50%\",\n \"children\": [\n \"preview-card\"\n ]\n },\n {\n \"id\": \"preview-card\",\n \"component\": \"Card\",\n \"children\": [\n \"pv-hdr\",\n \"pv-sec\"\n ]\n },\n {\n \"id\": \"pv-hdr\",\n \"component\": \"Header\",\n \"children\": [\n \"pv-title\"\n ]\n },\n {\n \"id\": \"pv-title\",\n \"component\": \"Text\",\n \"slot\": \"heading\",\n \"textContent\": \"Preview\"\n },\n {\n \"id\": \"pv-sec\",\n \"component\": \"Section\",\n \"children\": [\n \"preview-text\"\n ]\n },\n {\n \"id\": \"preview-text\",\n \"component\": \"Text\",\n \"variant\": \"body\",\n \"textContent\": \"Rendered markdown will appear here...\"\n }\n]",
|
|
16091
|
+
"name": "markdown-editor"
|
|
16092
|
+
},
|
|
16093
|
+
{
|
|
16094
|
+
"description": "Row with two resizable Pane components for left/right panel layout.",
|
|
16095
|
+
"a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"Row\",\n \"children\": [\n \"left\",\n \"right\"\n ]\n },\n {\n \"id\": \"left\",\n \"component\": \"Pane\",\n \"resizable\": true,\n \"width\": \"50%\",\n \"children\": [\n \"ltxt\"\n ]\n },\n {\n \"id\": \"ltxt\",\n \"component\": \"Text\",\n \"variant\": \"body\",\n \"textContent\": \"Left panel content\"\n },\n {\n \"id\": \"right\",\n \"component\": \"Pane\",\n \"resizable\": true,\n \"width\": \"50%\",\n \"children\": [\n \"rtxt\"\n ]\n },\n {\n \"id\": \"rtxt\",\n \"component\": \"Text\",\n \"variant\": \"body\",\n \"textContent\": \"Right panel content\"\n }\n]",
|
|
16096
|
+
"name": "split-pane"
|
|
16097
|
+
}
|
|
16098
|
+
],
|
|
16099
|
+
"keywords": [
|
|
16100
|
+
"pane"
|
|
16101
|
+
],
|
|
16102
|
+
"name": "UIPane",
|
|
16103
|
+
"related": [
|
|
16104
|
+
"text-area"
|
|
16105
|
+
],
|
|
16106
|
+
"slots": {
|
|
16107
|
+
"header": {
|
|
16108
|
+
"description": "Auto-created header element with label text and toggle arrow"
|
|
16109
|
+
}
|
|
16110
|
+
},
|
|
16111
|
+
"states": [
|
|
16112
|
+
{
|
|
16113
|
+
"description": "Default, ready for interaction.",
|
|
16114
|
+
"name": "idle"
|
|
16115
|
+
}
|
|
16116
|
+
],
|
|
16117
|
+
"status": "stable",
|
|
16118
|
+
"synonyms": {
|
|
16119
|
+
"tags": [
|
|
16120
|
+
"split-pane",
|
|
16121
|
+
"side-panel",
|
|
16122
|
+
"resizable-panel",
|
|
16123
|
+
"detail-pane",
|
|
16124
|
+
"list-pane",
|
|
16125
|
+
"context-pane",
|
|
16126
|
+
"Panel",
|
|
16127
|
+
"Pane"
|
|
16128
|
+
]
|
|
16129
|
+
},
|
|
16130
|
+
"tag": "pane-ui",
|
|
16131
|
+
"tokens": {},
|
|
16132
|
+
"traits": [],
|
|
16133
|
+
"version": 1
|
|
16134
|
+
}
|
|
16135
|
+
},
|
|
16136
|
+
"PaymentMethodForm": {
|
|
16137
|
+
"title": "PaymentMethodForm",
|
|
16138
|
+
"description": "Form-participating composite for capturing a payment method —\ncard number, expiry, CVC, name on card, billing address (optional),\nand country. The form chrome + structured validation + a single\nnormalized emit event; it does NOT integrate with Stripe Elements\nor a tokenization SDK directly (consumer responsibility).\n\nEach sub-field is a <field-ui> wrapper around an <input-ui> (or\n<select-ui> for country). Card number is Luhn-validated; expiry is\nparsed as MM/YY with month + year bounds; CVC is 3-4 digits.\nBrand detection (visa / mastercard / amex / discover) runs against\na small regex map and surfaces via the `change` event detail.\n\nForm value is a JSON-encoded payload of normalized field values\nserialized through ElementInternals under [name] (default\n\"paymentMethod\"). On submit, the host fires\n`submit-payment-method` with a flat detail\n`{ token, last4, brand, expMonth, expYear, name, country }`.\n`token` is a synthetic local-mode token (sha-like opaque string);\nconsumers integrating with a real processor handle tokenization\nin their own submit listener using `last4` / `brand` / etc.\n\nSpec: docs/specs/implementation-ready/SPEC-009-payment-method-form.md.\n",
|
|
16139
|
+
"type": "object",
|
|
16140
|
+
"allOf": [
|
|
16141
|
+
{
|
|
16142
|
+
"$ref": "#/$defs/ComponentCommon"
|
|
16143
|
+
},
|
|
16144
|
+
{
|
|
16145
|
+
"$ref": "#/$defs/CatalogComponentCommon"
|
|
16146
|
+
}
|
|
16147
|
+
],
|
|
16148
|
+
"properties": {
|
|
16149
|
+
"required": {
|
|
16150
|
+
"description": "Form-validation gate. When set, an empty composite fails\ncheckValidity() with \"Payment method required.\".\n",
|
|
16151
|
+
"type": "boolean",
|
|
16152
|
+
"default": false
|
|
16153
|
+
},
|
|
16154
|
+
"autofocus": {
|
|
16155
|
+
"description": "When set, the first sub-field (Name on card) receives focus on\nfirst connect. Convention parity with native form elements.\n",
|
|
16156
|
+
"type": "boolean",
|
|
16157
|
+
"default": false
|
|
16158
|
+
},
|
|
16159
|
+
"component": {
|
|
16160
|
+
"const": "PaymentMethodForm"
|
|
16161
|
+
},
|
|
16162
|
+
"countries": {
|
|
16163
|
+
"description": "Allowed billing countries, ISO 3166-1 alpha-2 codes. Drives\nthe <select-ui> dropdown's options. Empty array uses a\ndefault short list (US, CA, GB, DE, FR, AU).\n",
|
|
16164
|
+
"$ref": "#/$defs/DynamicStringList"
|
|
16165
|
+
},
|
|
16166
|
+
"default-country": {
|
|
16167
|
+
"description": "Default selected country (ISO 3166-1 alpha-2). Falls back to\nthe first entry in `countries` (or \"US\" when empty).\n",
|
|
16168
|
+
"type": "string",
|
|
16169
|
+
"default": "US"
|
|
16170
|
+
},
|
|
16171
|
+
"disabled": {
|
|
16172
|
+
"description": "Forwarded to every sub-control. Pointer-events:none on the\ncomposite host as a belt-and-suspenders.\n",
|
|
16173
|
+
"$ref": "#/$defs/DynamicBoolean"
|
|
16174
|
+
},
|
|
16175
|
+
"error": {
|
|
16176
|
+
"description": "Externally-set error message (e.g. server-rejected card). When\nnon-empty, the composite renders an <alert-ui variant=\"danger\">\nat the top of the form and sets aria-invalid=true on the host.\n",
|
|
16177
|
+
"$ref": "#/$defs/DynamicString"
|
|
16178
|
+
},
|
|
16179
|
+
"name": {
|
|
16180
|
+
"description": "Form field name. The composite's serialized form value lives\nunder this key in any wrapping <form>. Defaults to\n\"paymentMethod\".\n",
|
|
16181
|
+
"type": "string",
|
|
16182
|
+
"default": "paymentMethod"
|
|
16183
|
+
},
|
|
16184
|
+
"prefill": {
|
|
16185
|
+
"description": "JSON-encoded prefill payload `{last4, brand, expMonth, expYear,\nname, country}`. When set, the summary row renders with the\nsaved-card chrome and the rest of the form is hidden behind an\n\"Edit card\" button. Useful for \"update saved payment method\"\nflows.\n",
|
|
16186
|
+
"type": "string",
|
|
16187
|
+
"default": ""
|
|
16188
|
+
},
|
|
16189
|
+
"require-billing-address": {
|
|
16190
|
+
"description": "When set, renders the billing-address sub-fields (address line\n1, optional line 2, postal code). When unset, only postal code\n+ country are collected for the address-verification check.\n",
|
|
16191
|
+
"type": "boolean",
|
|
16192
|
+
"default": false
|
|
16193
|
+
},
|
|
16194
|
+
"value": {
|
|
16195
|
+
"description": "Resolved payment-method token. Read-only externally — the\ncomposite writes it after a successful tokenize() call. Setting\nthis to a non-empty string is treated as \"prefilled from a\nsaved payment method\" and renders the form in\nread-only-summary mode (last4 + brand + expiry shown).\n",
|
|
16196
|
+
"$ref": "#/$defs/DynamicString"
|
|
16197
|
+
}
|
|
16198
|
+
},
|
|
16199
|
+
"required": [
|
|
16200
|
+
"component"
|
|
16201
|
+
],
|
|
16202
|
+
"unevaluatedProperties": false,
|
|
16203
|
+
"x-adiaui": {
|
|
16204
|
+
"anti_patterns": [
|
|
16205
|
+
{
|
|
16206
|
+
"fix": "<payment-method-form-ui name=\"paymentMethod\" required></payment-method-form-ui>\n",
|
|
16207
|
+
"why": "Raw card digits in `value`. The composite's value is the\ntokenized output, never the input. Raw digits leak through\nreflection back to the attribute and end up in DOM snapshots /\nbrowser history / analytics.\n",
|
|
16208
|
+
"wrong": "<payment-method-form-ui value=\"4242 4242 4242 4242\"></payment-method-form-ui>\n"
|
|
16209
|
+
},
|
|
16210
|
+
{
|
|
16211
|
+
"fix": "<payment-method-form-ui aria-label=\"Card details\"></payment-method-form-ui>\n",
|
|
16212
|
+
"why": "PaymentMethodForm IS itself a labeled field group; nesting in\nField duplicates the label and breaks the internal grid\nlayout. Field's auto-id stamping confuses the composite's\nfirst-focusable lookup.\n",
|
|
16213
|
+
"wrong": "<field-ui label=\"Card details\">\n <payment-method-form-ui></payment-method-form-ui>\n</field-ui>\n"
|
|
16214
|
+
},
|
|
16215
|
+
{
|
|
16216
|
+
"fix": "<form>\n <payment-method-form-ui id=\"pm\"></payment-method-form-ui>\n <button-ui type=\"submit\" text=\"Save\"></button-ui>\n</form>\n<script>\n form.addEventListener('submit', async (e) => {\n e.preventDefault();\n const detail = await pm.tokenize();\n // Hand `detail.last4` / `detail.brand` to your processor SDK\n // to mint a real token; POST the resulting token to /charge.\n });\n</script>\n",
|
|
16217
|
+
"why": "Posting the form's serialized token directly to /charge skips\ntokenization — the synthetic local-mode token is opaque but\nNOT a real payment token. A real processor must mint the\ntoken before the charge call.\n",
|
|
16218
|
+
"wrong": "<form>\n <payment-method-form-ui></payment-method-form-ui>\n <button-ui type=\"submit\" text=\"Save\"></button-ui>\n</form>\n<script>\n form.addEventListener('submit', (e) => fetch('/charge', { body: new FormData(form) }));\n</script>\n"
|
|
16219
|
+
}
|
|
16220
|
+
],
|
|
16221
|
+
"category": "input",
|
|
16222
|
+
"composes": [
|
|
16223
|
+
"field-ui",
|
|
16224
|
+
"input-ui",
|
|
16225
|
+
"select-ui",
|
|
16226
|
+
"alert-ui",
|
|
16227
|
+
"icon-ui",
|
|
16228
|
+
"button-ui"
|
|
16229
|
+
],
|
|
13923
16230
|
"events": {
|
|
13924
|
-
"
|
|
13925
|
-
"description": "Fired
|
|
16231
|
+
"change": {
|
|
16232
|
+
"description": "Fired on every sub-field input. Detail carries a snapshot of\nthe current form validity + detected card brand. Bubbles.\n",
|
|
13926
16233
|
"detail": {
|
|
13927
|
-
"
|
|
13928
|
-
"description": "
|
|
13929
|
-
"type": "
|
|
16234
|
+
"brand": {
|
|
16235
|
+
"description": "Detected brand (`visa` / `mastercard` / `amex` / `discover` / `unknown`).",
|
|
16236
|
+
"type": "string"
|
|
16237
|
+
},
|
|
16238
|
+
"valid": {
|
|
16239
|
+
"description": "Whether the form currently passes all constraints.",
|
|
16240
|
+
"type": "boolean"
|
|
16241
|
+
}
|
|
16242
|
+
}
|
|
16243
|
+
},
|
|
16244
|
+
"payment-method-error": {
|
|
16245
|
+
"description": "Fired when tokenize() fails — either constraint validation\nsurfaced one or more field errors, or a Luhn / expiry / CVC\ncheck failed. Bubbles.\n",
|
|
16246
|
+
"detail": {
|
|
16247
|
+
"code": {
|
|
16248
|
+
"description": "Error code — one of `validation-failed`, `card-invalid`, `expired`, `cvc-invalid`.",
|
|
16249
|
+
"type": "string"
|
|
16250
|
+
},
|
|
16251
|
+
"field": {
|
|
16252
|
+
"description": "Field name that surfaced the error (`cardNumber` / `expiry` / `cvc` / `name` / `postalCode` / `country` / null).",
|
|
16253
|
+
"type": "string"
|
|
16254
|
+
},
|
|
16255
|
+
"message": {
|
|
16256
|
+
"description": "Human-readable error message.",
|
|
16257
|
+
"type": "string"
|
|
16258
|
+
}
|
|
16259
|
+
}
|
|
16260
|
+
},
|
|
16261
|
+
"submit-payment-method": {
|
|
16262
|
+
"description": "Fired when tokenize() resolves — either via an outer <form>\nsubmission or an explicit tokenize() call. Detail carries the\nnormalized payload that downstream code POSTs to the billing\nservice. Bubbles.\n",
|
|
16263
|
+
"detail": {
|
|
16264
|
+
"brand": {
|
|
16265
|
+
"description": "Detected brand — `visa`, `mastercard`, `amex`, `discover`, or `unknown`.",
|
|
16266
|
+
"type": "string"
|
|
16267
|
+
},
|
|
16268
|
+
"country": {
|
|
16269
|
+
"description": "ISO 3166-1 alpha-2 billing country.",
|
|
16270
|
+
"type": "string"
|
|
16271
|
+
},
|
|
16272
|
+
"expMonth": {
|
|
16273
|
+
"description": "Expiry month (1-12).",
|
|
16274
|
+
"type": "integer"
|
|
16275
|
+
},
|
|
16276
|
+
"expYear": {
|
|
16277
|
+
"description": "Expiry year (4-digit).",
|
|
16278
|
+
"type": "integer"
|
|
16279
|
+
},
|
|
16280
|
+
"last4": {
|
|
16281
|
+
"description": "Last 4 digits of the card number.",
|
|
16282
|
+
"type": "string"
|
|
16283
|
+
},
|
|
16284
|
+
"name": {
|
|
16285
|
+
"description": "Name on card.",
|
|
16286
|
+
"type": "string"
|
|
16287
|
+
},
|
|
16288
|
+
"token": {
|
|
16289
|
+
"description": "Synthetic local-mode token (sha-like opaque string).",
|
|
16290
|
+
"type": "string"
|
|
13930
16291
|
}
|
|
13931
16292
|
}
|
|
13932
16293
|
}
|
|
13933
16294
|
},
|
|
13934
16295
|
"examples": [
|
|
13935
16296
|
{
|
|
13936
|
-
"description": "
|
|
13937
|
-
"a2ui": "[\n {\n \"id\": \"
|
|
13938
|
-
"name": "
|
|
16297
|
+
"description": "Empty form, all sub-fields visible, required.",
|
|
16298
|
+
"a2ui": "[\n {\n \"id\": \"pm-1\",\n \"component\": \"PaymentMethodForm\",\n \"name\": \"paymentMethod\",\n \"required\": true\n }\n]\n",
|
|
16299
|
+
"name": "default"
|
|
13939
16300
|
},
|
|
13940
16301
|
{
|
|
13941
|
-
"description": "
|
|
13942
|
-
"a2ui": "[\n {\n \"id\": \"
|
|
13943
|
-
"name": "
|
|
16302
|
+
"description": "Edit-saved-card flow — summary row renders with the saved\ncard; \"Edit card\" CTA reveals the full form.\n",
|
|
16303
|
+
"a2ui": "[\n {\n \"id\": \"pm-2\",\n \"component\": \"PaymentMethodForm\",\n \"name\": \"paymentMethod\",\n \"prefill\": \"{\\\"last4\\\":\\\"4242\\\",\\\"brand\\\":\\\"visa\\\",\\\"expMonth\\\":12,\\\"expYear\\\":2027,\\\"name\\\":\\\"Pat Doe\\\",\\\"country\\\":\\\"US\\\"}\"\n }\n]\n",
|
|
16304
|
+
"name": "prefilled-saved-card"
|
|
16305
|
+
},
|
|
16306
|
+
{
|
|
16307
|
+
"description": "Full form including billing address lines + postal + country.\n",
|
|
16308
|
+
"a2ui": "[\n {\n \"id\": \"pm-3\",\n \"component\": \"PaymentMethodForm\",\n \"name\": \"paymentMethod\",\n \"requireBillingAddress\": true,\n \"countries\": [\"US\", \"CA\", \"GB\", \"DE\"]\n }\n]\n",
|
|
16309
|
+
"name": "with-billing-address"
|
|
13944
16310
|
}
|
|
13945
16311
|
],
|
|
13946
16312
|
"keywords": [
|
|
13947
|
-
"
|
|
13948
|
-
"
|
|
13949
|
-
"
|
|
13950
|
-
"
|
|
13951
|
-
"
|
|
13952
|
-
|
|
13953
|
-
|
|
16313
|
+
"payment-method",
|
|
16314
|
+
"card",
|
|
16315
|
+
"billing",
|
|
16316
|
+
"checkout",
|
|
16317
|
+
"card-capture",
|
|
16318
|
+
"payment",
|
|
16319
|
+
"credit-card",
|
|
16320
|
+
"debit-card",
|
|
16321
|
+
"save-payment-method",
|
|
16322
|
+
"update-payment-method",
|
|
16323
|
+
"add-card"
|
|
16324
|
+
],
|
|
16325
|
+
"name": "UIPaymentMethodForm",
|
|
13954
16326
|
"related": [
|
|
13955
|
-
"
|
|
13956
|
-
"
|
|
16327
|
+
"Form",
|
|
16328
|
+
"Field",
|
|
16329
|
+
"Input",
|
|
16330
|
+
"Select",
|
|
16331
|
+
"Alert",
|
|
16332
|
+
"PlanPicker",
|
|
16333
|
+
"Button"
|
|
13957
16334
|
],
|
|
13958
|
-
"slots": {
|
|
16335
|
+
"slots": {
|
|
16336
|
+
"legal": {
|
|
16337
|
+
"description": "Optional content rendered below the form fields — typically a\nterms-of-storage acknowledgement string with link(s).\n"
|
|
16338
|
+
}
|
|
16339
|
+
},
|
|
13959
16340
|
"states": [
|
|
13960
16341
|
{
|
|
13961
|
-
"description": "Default
|
|
16342
|
+
"description": "Default; ready for input.",
|
|
13962
16343
|
"name": "idle"
|
|
16344
|
+
},
|
|
16345
|
+
{
|
|
16346
|
+
"description": "tokenize() in flight.",
|
|
16347
|
+
"attribute": "tokenizing",
|
|
16348
|
+
"name": "tokenizing"
|
|
16349
|
+
},
|
|
16350
|
+
{
|
|
16351
|
+
"description": "A field-level or host-level error is present.",
|
|
16352
|
+
"attribute": "error",
|
|
16353
|
+
"name": "error"
|
|
16354
|
+
},
|
|
16355
|
+
{
|
|
16356
|
+
"description": "A saved payment method is displayed; form is hidden.",
|
|
16357
|
+
"attribute": "prefilled",
|
|
16358
|
+
"name": "prefilled"
|
|
16359
|
+
},
|
|
16360
|
+
{
|
|
16361
|
+
"description": "All sub-fields non-interactive.",
|
|
16362
|
+
"attribute": "disabled",
|
|
16363
|
+
"name": "disabled"
|
|
13963
16364
|
}
|
|
13964
16365
|
],
|
|
13965
|
-
"status": "
|
|
16366
|
+
"status": "experimental",
|
|
13966
16367
|
"synonyms": {
|
|
13967
|
-
"
|
|
13968
|
-
"
|
|
13969
|
-
"
|
|
13970
|
-
"
|
|
13971
|
-
],
|
|
13972
|
-
"navigation": [
|
|
13973
|
-
"nav",
|
|
13974
|
-
"sidebar",
|
|
13975
|
-
"breadcrumb",
|
|
13976
|
-
"tabs",
|
|
13977
|
-
"menu",
|
|
13978
|
-
"pagination"
|
|
16368
|
+
"billing": [
|
|
16369
|
+
"billing-info",
|
|
16370
|
+
"payment-method",
|
|
16371
|
+
"card"
|
|
13979
16372
|
],
|
|
13980
|
-
"
|
|
13981
|
-
"
|
|
13982
|
-
"
|
|
13983
|
-
"
|
|
16373
|
+
"card": [
|
|
16374
|
+
"payment-card",
|
|
16375
|
+
"credit-card",
|
|
16376
|
+
"debit-card"
|
|
13984
16377
|
],
|
|
13985
|
-
"
|
|
13986
|
-
"
|
|
13987
|
-
"
|
|
16378
|
+
"payment-method": [
|
|
16379
|
+
"card",
|
|
16380
|
+
"card-on-file",
|
|
16381
|
+
"billing"
|
|
13988
16382
|
]
|
|
13989
16383
|
},
|
|
13990
|
-
"tag": "
|
|
13991
|
-
"tokens": {
|
|
16384
|
+
"tag": "payment-method-form-ui",
|
|
16385
|
+
"tokens": {
|
|
16386
|
+
"--payment-method-form-alert-mb": {
|
|
16387
|
+
"description": "Margin-block-end on the host-level error alert.",
|
|
16388
|
+
"default": "var(--a-space-3)"
|
|
16389
|
+
},
|
|
16390
|
+
"--payment-method-form-brand-icon-size": {
|
|
16391
|
+
"description": "Inline brand-badge icon size in the card-number suffix.",
|
|
16392
|
+
"default": "1.25em"
|
|
16393
|
+
},
|
|
16394
|
+
"--payment-method-form-disabled-opacity": {
|
|
16395
|
+
"description": "Opacity applied to the host when [disabled].",
|
|
16396
|
+
"default": "var(--a-opacity-disabled, 0.5)"
|
|
16397
|
+
},
|
|
16398
|
+
"--payment-method-form-gap": {
|
|
16399
|
+
"description": "Gap between rows of the form grid.",
|
|
16400
|
+
"default": "var(--a-space-3)"
|
|
16401
|
+
},
|
|
16402
|
+
"--payment-method-form-grid-template": {
|
|
16403
|
+
"description": "Grid-template-areas for the field layout. Defaults to a\n4-row template — name spans both columns, card number spans\nboth, expiry + cvc share row 3, country + postal share row 4.\nAddress rows append when `require-billing-address` is set.\n",
|
|
16404
|
+
"default": "\"name name\" \"card card\" \"expiry cvc\" \"country postal\""
|
|
16405
|
+
},
|
|
16406
|
+
"--payment-method-form-legal-fg": {
|
|
16407
|
+
"description": "Foreground color of the slotted legal copy.",
|
|
16408
|
+
"default": "var(--a-fg-muted)"
|
|
16409
|
+
},
|
|
16410
|
+
"--payment-method-form-legal-size": {
|
|
16411
|
+
"description": "Font size of the slotted legal copy.",
|
|
16412
|
+
"default": "var(--a-text-xs, 0.75rem)"
|
|
16413
|
+
},
|
|
16414
|
+
"--payment-method-form-summary-bg": {
|
|
16415
|
+
"description": "Background of the saved-card summary row.",
|
|
16416
|
+
"default": "var(--a-bg-muted)"
|
|
16417
|
+
},
|
|
16418
|
+
"--payment-method-form-summary-border": {
|
|
16419
|
+
"description": "Border on the saved-card summary row.",
|
|
16420
|
+
"default": "1px solid var(--a-border)"
|
|
16421
|
+
},
|
|
16422
|
+
"--payment-method-form-summary-px": {
|
|
16423
|
+
"description": "Horizontal padding inside the saved-card summary row.",
|
|
16424
|
+
"default": "var(--a-space-4)"
|
|
16425
|
+
},
|
|
16426
|
+
"--payment-method-form-summary-py": {
|
|
16427
|
+
"description": "Vertical padding inside the saved-card summary row.",
|
|
16428
|
+
"default": "var(--a-space-3)"
|
|
16429
|
+
},
|
|
16430
|
+
"--payment-method-form-summary-radius": {
|
|
16431
|
+
"description": "Corner radius on the saved-card summary row.",
|
|
16432
|
+
"default": "var(--a-radius-md)"
|
|
16433
|
+
}
|
|
16434
|
+
},
|
|
13992
16435
|
"traits": [],
|
|
13993
16436
|
"version": 1
|
|
13994
16437
|
}
|
|
13995
16438
|
},
|
|
13996
|
-
"
|
|
13997
|
-
"title": "
|
|
13998
|
-
"description": "
|
|
16439
|
+
"PaymentMethodList": {
|
|
16440
|
+
"title": "PaymentMethodList",
|
|
16441
|
+
"description": "Compound billing primitive that renders the user's saved payment\nmethods (cards, bank accounts, wallets) as a vertical list with one\nrow designated as the default. Each row shows a brand mark, the\nlast-4 / account identifier, an optional expiry, and per-row actions\n(set-default / edit / remove). A trailing \"Add payment method\" CTA\nemits `add` so consumers can route the consumer flow.\n\nDefault is a strict 1-of-N radiogroup — exactly one row carries the\ndefault state when the list is non-empty. The primitive does NOT\nmutate the data source; all changes flow as events (`change`,\n`add`, `remove`, `select`) and the consumer applies the side\neffect against their billing API.\n\nSpec: docs/specs/implementation-ready/SPEC-010-payment-method-list.md.\n",
|
|
13999
16442
|
"type": "object",
|
|
14000
16443
|
"allOf": [
|
|
14001
16444
|
{
|
|
@@ -14006,38 +16449,46 @@
|
|
|
14006
16449
|
}
|
|
14007
16450
|
],
|
|
14008
16451
|
"properties": {
|
|
14009
|
-
"
|
|
14010
|
-
"description": "
|
|
16452
|
+
"add-icon": {
|
|
16453
|
+
"description": "Phosphor icon name for the add CTA.",
|
|
16454
|
+
"type": "string",
|
|
16455
|
+
"default": "plus"
|
|
16456
|
+
},
|
|
16457
|
+
"add-label": {
|
|
16458
|
+
"description": "Label for the trailing add CTA.",
|
|
16459
|
+
"type": "string",
|
|
16460
|
+
"default": "Add payment method"
|
|
16461
|
+
},
|
|
16462
|
+
"component": {
|
|
16463
|
+
"const": "PaymentMethodList"
|
|
16464
|
+
},
|
|
16465
|
+
"disabled": {
|
|
16466
|
+
"description": "Block all interaction; rows remain visible.",
|
|
14011
16467
|
"type": "boolean",
|
|
14012
16468
|
"default": false
|
|
14013
16469
|
},
|
|
14014
|
-
"
|
|
14015
|
-
"
|
|
16470
|
+
"methods": {
|
|
16471
|
+
"description": "Array of saved payment-method records. Source of truth for the\nrendered rows. Shape per record:\n{id, brand, last4?, expiry?, holder?, type, default?, status?}.\nEmpty array renders the empty-state.\n",
|
|
16472
|
+
"$ref": "#/$defs/DynamicStringList"
|
|
14016
16473
|
},
|
|
14017
|
-
"
|
|
14018
|
-
"description": "
|
|
14019
|
-
"type": "
|
|
14020
|
-
"default":
|
|
16474
|
+
"name": {
|
|
16475
|
+
"description": "Form field name for the default-method id. Serialized via\nElementInternals; mirrors UIFormElement conventions.\n",
|
|
16476
|
+
"type": "string",
|
|
16477
|
+
"default": ""
|
|
14021
16478
|
},
|
|
14022
|
-
"
|
|
14023
|
-
"description": "
|
|
14024
|
-
"type": "
|
|
14025
|
-
"default":
|
|
16479
|
+
"no-add": {
|
|
16480
|
+
"description": "Hide the trailing \"Add payment method\" CTA (read-only flow,\ncheckout drawer, etc.).\n",
|
|
16481
|
+
"type": "boolean",
|
|
16482
|
+
"default": false
|
|
14026
16483
|
},
|
|
14027
|
-
"
|
|
14028
|
-
"description": "
|
|
16484
|
+
"no-remove": {
|
|
16485
|
+
"description": "Hide per-row remove buttons.",
|
|
14029
16486
|
"type": "boolean",
|
|
14030
16487
|
"default": false
|
|
14031
16488
|
},
|
|
14032
|
-
"
|
|
14033
|
-
"description": "
|
|
14034
|
-
"
|
|
14035
|
-
"enum": [
|
|
14036
|
-
"",
|
|
14037
|
-
"leading",
|
|
14038
|
-
"trailing"
|
|
14039
|
-
],
|
|
14040
|
-
"default": ""
|
|
16489
|
+
"value": {
|
|
16490
|
+
"description": "Id of the row currently marked default (the form value). When\nboth `value` and `methods[].default` are set, `value` wins and\nthe primitive emits `change` to reconcile.\n",
|
|
16491
|
+
"$ref": "#/$defs/DynamicString"
|
|
14041
16492
|
}
|
|
14042
16493
|
},
|
|
14043
16494
|
"required": [
|
|
@@ -14045,62 +16496,224 @@
|
|
|
14045
16496
|
],
|
|
14046
16497
|
"unevaluatedProperties": false,
|
|
14047
16498
|
"x-adiaui": {
|
|
14048
|
-
"anti_patterns": [
|
|
14049
|
-
|
|
16499
|
+
"anti_patterns": [
|
|
16500
|
+
{
|
|
16501
|
+
"fix": "<payment-method-list-ui methods='[\n {\"id\":\"pm_1\",\"default\":true},\n {\"id\":\"pm_2\"}\n]'></payment-method-list-ui>\n",
|
|
16502
|
+
"why": "Two rows marked default. The primitive clears all but the first\nand emits a corrective `change` event; this is wasted round-trips.\nSource of truth should mark exactly one row.\n",
|
|
16503
|
+
"wrong": "<payment-method-list-ui methods='[\n {\"id\":\"pm_1\",\"default\":true},\n {\"id\":\"pm_2\",\"default\":true}\n]'></payment-method-list-ui>\n"
|
|
16504
|
+
},
|
|
16505
|
+
{
|
|
16506
|
+
"fix": "<payment-method-list-ui methods=\"...\"></payment-method-list-ui>\n",
|
|
16507
|
+
"why": "Reinvents 1-of-N default semantics. Drops radiogroup a11y.\nRe-derives the brand-icon dictionary per consumer.\n",
|
|
16508
|
+
"wrong": "A <col-ui> of bespoke <card-ui> rows with manual radio markup\nand a per-row \"make default\" button.\n"
|
|
16509
|
+
},
|
|
16510
|
+
{
|
|
16511
|
+
"fix": "<payment-method-list-ui methods='[{\"id\":\"pm_1\",\"brand\":\"discover\",\"type\":\"card\"}]'>\n</payment-method-list-ui>\n",
|
|
16512
|
+
"why": "\"discover-it\" is a card product, not a brand from the enumerated\nset. The primitive renders the generic credit-card fallback.\n",
|
|
16513
|
+
"wrong": "<payment-method-list-ui methods='[{\"id\":\"pm_1\",\"brand\":\"discover-it\",\"type\":\"card\"}]'>\n</payment-method-list-ui>\n"
|
|
16514
|
+
}
|
|
16515
|
+
],
|
|
16516
|
+
"category": "input",
|
|
14050
16517
|
"composes": [
|
|
14051
|
-
"
|
|
16518
|
+
"card-ui",
|
|
16519
|
+
"button-ui",
|
|
16520
|
+
"icon-ui",
|
|
16521
|
+
"tag-ui",
|
|
16522
|
+
"text-ui",
|
|
16523
|
+
"empty-state-ui"
|
|
14052
16524
|
],
|
|
14053
16525
|
"events": {
|
|
14054
|
-
"
|
|
14055
|
-
"description": "Fired when the
|
|
16526
|
+
"add": {
|
|
16527
|
+
"description": "Fired when the user activates the trailing add CTA. Consumer\nroutes to its add-method flow (drawer / modal / page). Bubbles.\n"
|
|
16528
|
+
},
|
|
16529
|
+
"change": {
|
|
16530
|
+
"description": "Fired when the default method changes — via row activation or\nprogrammatic value set. Bubbles.\n",
|
|
16531
|
+
"detail": {
|
|
16532
|
+
"method": {
|
|
16533
|
+
"description": "The full method record now marked default.",
|
|
16534
|
+
"type": "object"
|
|
16535
|
+
},
|
|
16536
|
+
"previous": {
|
|
16537
|
+
"description": "Id of the previous default (empty string when none).",
|
|
16538
|
+
"type": "string"
|
|
16539
|
+
},
|
|
16540
|
+
"value": {
|
|
16541
|
+
"description": "Id of the new default.",
|
|
16542
|
+
"type": "string"
|
|
16543
|
+
}
|
|
16544
|
+
}
|
|
16545
|
+
},
|
|
16546
|
+
"remove": {
|
|
16547
|
+
"description": "Fired when the user activates a row's remove affordance. Consumer\nremoves the method on its end and writes back via `.remove(id)`\nor by mutating `methods`. Bubbles.\n",
|
|
16548
|
+
"detail": {
|
|
16549
|
+
"id": {
|
|
16550
|
+
"description": "Method id targeted for removal.",
|
|
16551
|
+
"type": "string"
|
|
16552
|
+
},
|
|
16553
|
+
"method": {
|
|
16554
|
+
"description": "The full method record.",
|
|
16555
|
+
"type": "object"
|
|
16556
|
+
}
|
|
16557
|
+
}
|
|
16558
|
+
},
|
|
16559
|
+
"select": {
|
|
16560
|
+
"description": "Fired when the user activates a row without changing the default\n(e.g. an \"Edit\" action). Bubbles.\n",
|
|
16561
|
+
"detail": {
|
|
16562
|
+
"id": {
|
|
16563
|
+
"description": "Method id.",
|
|
16564
|
+
"type": "string"
|
|
16565
|
+
},
|
|
16566
|
+
"method": {
|
|
16567
|
+
"description": "The full method record.",
|
|
16568
|
+
"type": "object"
|
|
16569
|
+
}
|
|
16570
|
+
}
|
|
14056
16571
|
}
|
|
14057
16572
|
},
|
|
14058
16573
|
"examples": [
|
|
14059
16574
|
{
|
|
14060
|
-
"description": "
|
|
14061
|
-
"a2ui": "[\n {\n \"id\": \"
|
|
14062
|
-
"name": "
|
|
16575
|
+
"description": "Saved payment methods in a billing settings panel.",
|
|
16576
|
+
"a2ui": "[\n {\n \"id\": \"pml-settings\",\n \"component\": \"PaymentMethodList\",\n \"name\": \"default-method\",\n \"value\": \"pm_1\",\n \"methods\": [\n {\"id\":\"pm_1\",\"brand\":\"visa\",\"last4\":\"4242\",\"expiry\":\"2027-05-01\",\"holder\":\"Ada Lovelace\",\"type\":\"card\",\"default\":true},\n {\"id\":\"pm_2\",\"brand\":\"mastercard\",\"last4\":\"0009\",\"expiry\":\"2026-06-01\",\"holder\":\"Ada Lovelace\",\"type\":\"card\"},\n {\"id\":\"pm_3\",\"brand\":\"ach\",\"last4\":\"6789\",\"holder\":\"Chase ••6789\",\"type\":\"bank\"}\n ]\n }\n]\n",
|
|
16577
|
+
"name": "settings-list"
|
|
14063
16578
|
},
|
|
14064
16579
|
{
|
|
14065
|
-
"description": "
|
|
14066
|
-
"a2ui": "[\n {\n \"id\": \"
|
|
14067
|
-
"name": "
|
|
16580
|
+
"description": "Checkout-drawer picker — no add CTA; read-only-ish.",
|
|
16581
|
+
"a2ui": "[\n {\n \"id\": \"pml-checkout\",\n \"component\": \"PaymentMethodList\",\n \"name\": \"checkout-method\",\n \"noAdd\": true,\n \"methods\": [\n {\"id\":\"pm_1\",\"brand\":\"visa\",\"last4\":\"4242\",\"expiry\":\"2027-05-01\",\"type\":\"card\",\"default\":true},\n {\"id\":\"pm_2\",\"brand\":\"mastercard\",\"last4\":\"0009\",\"expiry\":\"2026-06-01\",\"type\":\"card\"}\n ]\n }\n]\n",
|
|
16582
|
+
"name": "checkout-drawer"
|
|
14068
16583
|
}
|
|
14069
16584
|
],
|
|
14070
16585
|
"keywords": [
|
|
14071
|
-
"
|
|
14072
|
-
|
|
14073
|
-
|
|
16586
|
+
"payment-method",
|
|
16587
|
+
"payment-methods",
|
|
16588
|
+
"saved-cards",
|
|
16589
|
+
"billing",
|
|
16590
|
+
"cards",
|
|
16591
|
+
"payment-card",
|
|
16592
|
+
"credit-card",
|
|
16593
|
+
"default-card",
|
|
16594
|
+
"wallet",
|
|
16595
|
+
"bank-account",
|
|
16596
|
+
"ach",
|
|
16597
|
+
"method-list"
|
|
16598
|
+
],
|
|
16599
|
+
"name": "PaymentMethodList",
|
|
14074
16600
|
"related": [
|
|
14075
|
-
"
|
|
16601
|
+
"PlanPicker",
|
|
16602
|
+
"Card",
|
|
16603
|
+
"Button",
|
|
16604
|
+
"Tag",
|
|
16605
|
+
"Icon",
|
|
16606
|
+
"EmptyState"
|
|
14076
16607
|
],
|
|
14077
16608
|
"slots": {
|
|
14078
|
-
"
|
|
14079
|
-
"description": "
|
|
16609
|
+
"add": {
|
|
16610
|
+
"description": "Custom add-CTA replacement. When absent the primitive stamps a\ndefault `<button-ui variant=\"outline\" icon=\"plus\">`. Hidden\nentirely when `[no-add]` is set.\n"
|
|
16611
|
+
},
|
|
16612
|
+
"empty": {
|
|
16613
|
+
"description": "Custom empty-state shown when `methods` is empty. Falls back to a\ndefault <empty-state-ui icon=\"credit-card\"> when omitted.\n"
|
|
14080
16614
|
}
|
|
14081
16615
|
},
|
|
14082
16616
|
"states": [
|
|
14083
16617
|
{
|
|
14084
|
-
"description": "Default, ready for interaction.",
|
|
16618
|
+
"description": "Default — rows rendered, ready for interaction.",
|
|
14085
16619
|
"name": "idle"
|
|
16620
|
+
},
|
|
16621
|
+
{
|
|
16622
|
+
"description": "No methods to render.",
|
|
16623
|
+
"attribute": "empty",
|
|
16624
|
+
"name": "empty"
|
|
16625
|
+
},
|
|
16626
|
+
{
|
|
16627
|
+
"description": "All rows non-interactive.",
|
|
16628
|
+
"attribute": "disabled",
|
|
16629
|
+
"name": "disabled"
|
|
14086
16630
|
}
|
|
14087
16631
|
],
|
|
14088
|
-
"status": "
|
|
16632
|
+
"status": "experimental",
|
|
14089
16633
|
"synonyms": {
|
|
14090
|
-
"
|
|
14091
|
-
"
|
|
14092
|
-
"
|
|
14093
|
-
"
|
|
14094
|
-
|
|
14095
|
-
|
|
14096
|
-
"
|
|
14097
|
-
"
|
|
14098
|
-
|
|
16634
|
+
"card": [
|
|
16635
|
+
"credit-card",
|
|
16636
|
+
"debit-card",
|
|
16637
|
+
"payment-method"
|
|
16638
|
+
],
|
|
16639
|
+
"payment": [
|
|
16640
|
+
"billing",
|
|
16641
|
+
"charge"
|
|
16642
|
+
],
|
|
16643
|
+
"saved": [
|
|
16644
|
+
"stored"
|
|
14099
16645
|
]
|
|
14100
16646
|
},
|
|
14101
|
-
"tag": "
|
|
14102
|
-
"tokens": {
|
|
14103
|
-
|
|
16647
|
+
"tag": "payment-method-list-ui",
|
|
16648
|
+
"tokens": {
|
|
16649
|
+
"--payment-method-list-add-justify": {
|
|
16650
|
+
"description": "Justification of the trailing add CTA row.",
|
|
16651
|
+
"default": "flex-start"
|
|
16652
|
+
},
|
|
16653
|
+
"--payment-method-list-bg": {
|
|
16654
|
+
"description": "Host background. Defaults to transparent.",
|
|
16655
|
+
"default": "transparent"
|
|
16656
|
+
},
|
|
16657
|
+
"--payment-method-list-brand-frame": {
|
|
16658
|
+
"description": "Brand-mark frame background.",
|
|
16659
|
+
"default": "var(--a-bg-strong)"
|
|
16660
|
+
},
|
|
16661
|
+
"--payment-method-list-brand-radius": {
|
|
16662
|
+
"description": "Brand-mark frame radius.",
|
|
16663
|
+
"default": "var(--a-radius-md)"
|
|
16664
|
+
},
|
|
16665
|
+
"--payment-method-list-brand-size": {
|
|
16666
|
+
"description": "Brand-mark frame size.",
|
|
16667
|
+
"default": "2.5rem"
|
|
16668
|
+
},
|
|
16669
|
+
"--payment-method-list-disabled-opacity": {
|
|
16670
|
+
"description": "Opacity applied when the host is disabled.",
|
|
16671
|
+
"default": 0.5
|
|
16672
|
+
},
|
|
16673
|
+
"--payment-method-list-gap": {
|
|
16674
|
+
"description": "Gap between rows.",
|
|
16675
|
+
"default": "var(--a-space-2)"
|
|
16676
|
+
},
|
|
16677
|
+
"--payment-method-list-row-bg": {
|
|
16678
|
+
"description": "Default row background.",
|
|
16679
|
+
"default": "var(--a-bg)"
|
|
16680
|
+
},
|
|
16681
|
+
"--payment-method-list-row-bg-default": {
|
|
16682
|
+
"description": "Background tint applied to the default row.",
|
|
16683
|
+
"default": "var(--a-accent-muted)"
|
|
16684
|
+
},
|
|
16685
|
+
"--payment-method-list-row-bg-hover": {
|
|
16686
|
+
"description": "Row hover background.",
|
|
16687
|
+
"default": "var(--a-bg-muted)"
|
|
16688
|
+
},
|
|
16689
|
+
"--payment-method-list-row-border": {
|
|
16690
|
+
"description": "Row border.",
|
|
16691
|
+
"default": "1px solid var(--a-border-subtle)"
|
|
16692
|
+
},
|
|
16693
|
+
"--payment-method-list-row-border-default": {
|
|
16694
|
+
"description": "Border on the default row.",
|
|
16695
|
+
"default": "1px solid var(--a-accent)"
|
|
16696
|
+
},
|
|
16697
|
+
"--payment-method-list-row-gap": {
|
|
16698
|
+
"description": "Gap between brand mark, meta, and actions cells.",
|
|
16699
|
+
"default": "var(--a-space-3)"
|
|
16700
|
+
},
|
|
16701
|
+
"--payment-method-list-row-px": {
|
|
16702
|
+
"description": "Row horizontal padding.",
|
|
16703
|
+
"default": "var(--a-space-4)"
|
|
16704
|
+
},
|
|
16705
|
+
"--payment-method-list-row-py": {
|
|
16706
|
+
"description": "Row vertical padding.",
|
|
16707
|
+
"default": "var(--a-space-3)"
|
|
16708
|
+
},
|
|
16709
|
+
"--payment-method-list-row-radius": {
|
|
16710
|
+
"description": "Row corner radius.",
|
|
16711
|
+
"default": "var(--a-radius-lg)"
|
|
16712
|
+
}
|
|
16713
|
+
},
|
|
16714
|
+
"traits": [
|
|
16715
|
+
"focusable"
|
|
16716
|
+
],
|
|
14104
16717
|
"version": 1
|
|
14105
16718
|
}
|
|
14106
16719
|
},
|
|
@@ -14184,23 +16797,370 @@
|
|
|
14184
16797
|
"description": "Default slot — primary child content."
|
|
14185
16798
|
}
|
|
14186
16799
|
},
|
|
14187
|
-
"states": [
|
|
14188
|
-
{
|
|
14189
|
-
"description": "Default, ready for interaction.",
|
|
14190
|
-
"name": "idle"
|
|
14191
|
-
}
|
|
16800
|
+
"states": [
|
|
16801
|
+
{
|
|
16802
|
+
"description": "Default, ready for interaction.",
|
|
16803
|
+
"name": "idle"
|
|
16804
|
+
}
|
|
16805
|
+
],
|
|
16806
|
+
"status": "stable",
|
|
16807
|
+
"synonyms": {
|
|
16808
|
+
"tags": [
|
|
16809
|
+
"job-status",
|
|
16810
|
+
"deploy-status",
|
|
16811
|
+
"pipeline-indicator"
|
|
16812
|
+
]
|
|
16813
|
+
},
|
|
16814
|
+
"tag": "pipeline-status-ui",
|
|
16815
|
+
"tokens": {},
|
|
16816
|
+
"traits": [],
|
|
16817
|
+
"version": 1
|
|
16818
|
+
}
|
|
16819
|
+
},
|
|
16820
|
+
"PlanPicker": {
|
|
16821
|
+
"title": "PlanPicker",
|
|
16822
|
+
"description": "A form-participating chooser of one of N billing plans. The canonical\nplan-card grid used by both in-app upgrade modals and marketing\npricing pages (SPEC-012 composes this primitive as its core), so\nbenefit copy, pricing strings, recommendation highlighting, and the\nbilling-cycle toggle never drift between surfaces.\n\nEach plan record carries a stable id, name, optional tagline + icon,\na per-cycle price object, a feature list, and optional flags\n(recommended, rank, disabled). One plan may carry recommended:true\n(accent border + tinted bg + shadow); a host-level `current` id\nmarks the user's current plan (muted bg, \"Current plan\" tag, no\nChoose CTA, contextual \"Upgrade\"/\"Downgrade\" labels on siblings).\n\nLayout is grid by default (marketing surfaces) and `layout=\"list\"`\nfor in-app settings panels. The optional `cycle-toggle` boolean\nrenders an internal <segmented-ui> that swaps prices between\nmonthly and annual cycles in place across every card.\n\nSpec: docs/specs/implementation-ready/SPEC-011-plan-picker-in-app-upgrade.md.\n",
|
|
16823
|
+
"type": "object",
|
|
16824
|
+
"allOf": [
|
|
16825
|
+
{
|
|
16826
|
+
"$ref": "#/$defs/ComponentCommon"
|
|
16827
|
+
},
|
|
16828
|
+
{
|
|
16829
|
+
"$ref": "#/$defs/CatalogComponentCommon"
|
|
16830
|
+
}
|
|
16831
|
+
],
|
|
16832
|
+
"properties": {
|
|
16833
|
+
"component": {
|
|
16834
|
+
"const": "PlanPicker"
|
|
16835
|
+
},
|
|
16836
|
+
"currency": {
|
|
16837
|
+
"description": "Default ISO 4217 currency code for price rendering. Overridable\nper-price via plans[].prices[cycle].currency.\n",
|
|
16838
|
+
"type": "string",
|
|
16839
|
+
"default": "USD"
|
|
16840
|
+
},
|
|
16841
|
+
"current": {
|
|
16842
|
+
"description": "Id of the user's CURRENT plan. When set, that card renders with\na muted background, a \"Current plan\" <tag-ui>, and either no CTA\nor a \"Manage\" CTA. Other plans receive contextual upgrade /\ndowngrade CTA labels derived from rank. Unknown ids fail\nsilently (no anchor row).\n",
|
|
16843
|
+
"$ref": "#/$defs/DynamicString"
|
|
16844
|
+
},
|
|
16845
|
+
"cycle": {
|
|
16846
|
+
"description": "Active billing cycle. Drives which `plans[].prices[cycle]` value\nrenders across every card simultaneously. Toggle via the in-host\n`cycle-toggle` (when set) or programmatically via setCycle().\n",
|
|
16847
|
+
"$ref": "#/$defs/DynamicString"
|
|
16848
|
+
},
|
|
16849
|
+
"cycle-toggle": {
|
|
16850
|
+
"description": "When set, the primitive renders an internal <segmented-ui> with\nMonthly / Annual options above the plan grid. When unset, the\nconsumer drives [cycle] externally (e.g. from a parent toolbar).\n",
|
|
16851
|
+
"type": "boolean",
|
|
16852
|
+
"default": false
|
|
16853
|
+
},
|
|
16854
|
+
"data-stream-src": {
|
|
16855
|
+
"description": "Optional endpoint returning the `plans` array (universal\ndata-stream-* trait). On successful load, `plans` is replaced\nand a `load` event fires; on failure an `error` event fires.\n",
|
|
16856
|
+
"type": "string",
|
|
16857
|
+
"default": ""
|
|
16858
|
+
},
|
|
16859
|
+
"disabled": {
|
|
16860
|
+
"description": "Block all interaction across the picker.",
|
|
16861
|
+
"type": "boolean",
|
|
16862
|
+
"default": false
|
|
16863
|
+
},
|
|
16864
|
+
"layout": {
|
|
16865
|
+
"description": "Card layout. `grid` (auto-fit columns, minimum 16rem) for\nmarketing surfaces. `list` (single column rows) for in-app\nsettings panels.\n",
|
|
16866
|
+
"type": "string",
|
|
16867
|
+
"enum": [
|
|
16868
|
+
"grid",
|
|
16869
|
+
"list"
|
|
16870
|
+
],
|
|
16871
|
+
"default": "grid"
|
|
16872
|
+
},
|
|
16873
|
+
"locale": {
|
|
16874
|
+
"description": "Locale for Intl.NumberFormat (price) and cycle labels. Defaults\nto document.documentElement.lang (or \"en-US\" when absent).\n",
|
|
16875
|
+
"type": "string",
|
|
16876
|
+
"default": ""
|
|
16877
|
+
},
|
|
16878
|
+
"name": {
|
|
16879
|
+
"description": "Form field name for the selected plan id. Mirrors UIFormElement\nconventions; serialized via ElementInternals.\n",
|
|
16880
|
+
"type": "string",
|
|
16881
|
+
"default": ""
|
|
16882
|
+
},
|
|
16883
|
+
"plans": {
|
|
16884
|
+
"description": "Array of plan records. Source of truth for the rendered cards.\nShape per record: {id, name, tagline?, prices: {monthly: {amount,\ncurrency?, unit?, note?}, annual?: {...}}, features?: string[],\ncta?: string, recommended?: boolean, rank?: number, icon?: string,\ndisabled?: boolean}. Empty array renders the empty-state.\n",
|
|
16885
|
+
"$ref": "#/$defs/DynamicStringList"
|
|
16886
|
+
},
|
|
16887
|
+
"value": {
|
|
16888
|
+
"description": "Currently selected plan id (form value). Read-write — both the\nform submission key and the [checked] gate on the matching\n<option-card-ui>.\n",
|
|
16889
|
+
"$ref": "#/$defs/DynamicString"
|
|
16890
|
+
}
|
|
16891
|
+
},
|
|
16892
|
+
"required": [
|
|
16893
|
+
"component",
|
|
16894
|
+
"plans"
|
|
16895
|
+
],
|
|
16896
|
+
"unevaluatedProperties": false,
|
|
16897
|
+
"x-adiaui": {
|
|
16898
|
+
"anti_patterns": [
|
|
16899
|
+
{
|
|
16900
|
+
"fix": "<plan-picker-ui plans='[\n {\"id\":\"p1\",\"name\":\"Free\",\"prices\":{\"monthly\":{\"amount\":0}}},\n {\"id\":\"p2\",\"name\":\"Pro\",\"prices\":{\"monthly\":{\"amount\":20}}}\n]'></plan-picker-ui>\n",
|
|
16901
|
+
"why": "`price` is a top-level shortcut not in the schema. Prices are\nkeyed by cycle (monthly / annual). Without a cycle key, the\ncycle toggle has nothing to switch and annual pricing is\ninvisible to consumers.\n",
|
|
16902
|
+
"wrong": "<plan-picker-ui plans='[\n {\"id\":\"p1\",\"name\":\"Free\",\"price\":0},\n {\"id\":\"p2\",\"name\":\"Pro\",\"price\":20}\n]'></plan-picker-ui>\n"
|
|
16903
|
+
},
|
|
16904
|
+
{
|
|
16905
|
+
"fix": "<plan-picker-ui plans='[\n {\"id\":\"t\",\"name\":\"Team\",\"prices\":{\"monthly\":{\"amount\":10}}},\n {\"id\":\"p\",\"name\":\"Pro\",\"recommended\":true,\"prices\":{\"monthly\":{\"amount\":20}}}\n]'></plan-picker-ui>\n",
|
|
16906
|
+
"why": "Two recommended plans cancel each other visually — there is no\n\"the\" recommendation. Pick one.\n",
|
|
16907
|
+
"wrong": "<plan-picker-ui plans='[\n {\"id\":\"t\",\"name\":\"Team\",\"recommended\":true,\"prices\":{\"monthly\":{\"amount\":10}}},\n {\"id\":\"p\",\"name\":\"Pro\",\"recommended\":true,\"prices\":{\"monthly\":{\"amount\":20}}}\n]'></plan-picker-ui>\n"
|
|
16908
|
+
},
|
|
16909
|
+
{
|
|
16910
|
+
"fix": "<plan-picker-ui plans=\"...\" cycle-toggle></plan-picker-ui>\n",
|
|
16911
|
+
"why": "Reinvents the radiogroup keyboard model and the cycle-toggle\nsemantics; pricing strings drift between this surface and the\nmarketing pricing page that uses the canonical primitive.\n",
|
|
16912
|
+
"wrong": "A <col-ui> of bespoke <card-ui> plan cards with manual radio\nmarkup and a per-plan cycle pill.\n"
|
|
16913
|
+
}
|
|
16914
|
+
],
|
|
16915
|
+
"category": "input",
|
|
16916
|
+
"composes": [
|
|
16917
|
+
"option-card-ui",
|
|
16918
|
+
"segmented-ui",
|
|
16919
|
+
"segment-ui",
|
|
16920
|
+
"button-ui",
|
|
16921
|
+
"icon-ui",
|
|
16922
|
+
"text-ui",
|
|
16923
|
+
"tag-ui",
|
|
16924
|
+
"empty-state-ui"
|
|
16925
|
+
],
|
|
16926
|
+
"events": {
|
|
16927
|
+
"change": {
|
|
16928
|
+
"description": "Fired when the selected plan id changes — either via user click\nor programmatic value set. Bubbles.\n",
|
|
16929
|
+
"detail": {
|
|
16930
|
+
"cycle": {
|
|
16931
|
+
"description": "Active billing cycle.",
|
|
16932
|
+
"type": "string"
|
|
16933
|
+
},
|
|
16934
|
+
"previous": {
|
|
16935
|
+
"description": "Previous plan id (empty string when none).",
|
|
16936
|
+
"type": "string"
|
|
16937
|
+
},
|
|
16938
|
+
"value": {
|
|
16939
|
+
"description": "New plan id.",
|
|
16940
|
+
"type": "string"
|
|
16941
|
+
}
|
|
16942
|
+
}
|
|
16943
|
+
},
|
|
16944
|
+
"cycle-change": {
|
|
16945
|
+
"description": "Fired when the active billing cycle changes (cycle-toggle\nclick or programmatic setCycle). Bubbles.\n",
|
|
16946
|
+
"detail": {
|
|
16947
|
+
"cycle": {
|
|
16948
|
+
"description": "New cycle.",
|
|
16949
|
+
"type": "string",
|
|
16950
|
+
"enum": [
|
|
16951
|
+
"monthly",
|
|
16952
|
+
"annual"
|
|
16953
|
+
]
|
|
16954
|
+
},
|
|
16955
|
+
"previous": {
|
|
16956
|
+
"description": "Previous cycle.",
|
|
16957
|
+
"type": "string"
|
|
16958
|
+
}
|
|
16959
|
+
}
|
|
16960
|
+
},
|
|
16961
|
+
"error": {
|
|
16962
|
+
"description": "Fired when a `data-stream-src` fetch fails OR when a user tries\nto select a `disabled: true` plan. Bubbles.\n",
|
|
16963
|
+
"detail": {
|
|
16964
|
+
"reason": {
|
|
16965
|
+
"description": "One of `fetch-failed`, `plan-disabled`.",
|
|
16966
|
+
"type": "string"
|
|
16967
|
+
}
|
|
16968
|
+
}
|
|
16969
|
+
},
|
|
16970
|
+
"load": {
|
|
16971
|
+
"description": "Fired when `data-stream-src` finishes a successful fetch and\n`plans` is populated. Bubbles.\n",
|
|
16972
|
+
"detail": {
|
|
16973
|
+
"count": {
|
|
16974
|
+
"description": "Number of plans loaded.",
|
|
16975
|
+
"type": "integer"
|
|
16976
|
+
}
|
|
16977
|
+
}
|
|
16978
|
+
},
|
|
16979
|
+
"select": {
|
|
16980
|
+
"description": "Fired when the user activates a plan's CTA button — the\ncommitting action that consumers wire to a checkout / upgrade\nflow. Distinct from `change` (selection without commit). Bubbles.\n",
|
|
16981
|
+
"detail": {
|
|
16982
|
+
"cycle": {
|
|
16983
|
+
"description": "Active billing cycle at commit.",
|
|
16984
|
+
"type": "string"
|
|
16985
|
+
},
|
|
16986
|
+
"value": {
|
|
16987
|
+
"description": "Plan id being committed.",
|
|
16988
|
+
"type": "string"
|
|
16989
|
+
}
|
|
16990
|
+
}
|
|
16991
|
+
}
|
|
16992
|
+
},
|
|
16993
|
+
"examples": [
|
|
16994
|
+
{
|
|
16995
|
+
"description": "In-app upgrade modal with three plans + annual default + cycle toggle.",
|
|
16996
|
+
"a2ui": "[\n {\n \"id\": \"pp-upgrade\",\n \"component\": \"PlanPicker\",\n \"name\": \"plan\",\n \"current\": \"plan_team\",\n \"cycle\": \"annual\",\n \"cycleToggle\": true,\n \"plans\": [\n {\"id\":\"plan_free\",\"name\":\"Free\",\"prices\":{\"monthly\":{\"amount\":0}},\"features\":[\"3 projects\",\"Community support\"],\"rank\":1},\n {\"id\":\"plan_team\",\"name\":\"Team\",\"prices\":{\"monthly\":{\"amount\":10,\"unit\":\"seat\"},\"annual\":{\"amount\":8,\"unit\":\"seat\",\"note\":\"billed annually\"}},\"features\":[\"Unlimited projects\",\"Email support\"],\"rank\":2},\n {\"id\":\"plan_pro\",\"name\":\"Pro\",\"prices\":{\"monthly\":{\"amount\":25,\"unit\":\"seat\"},\"annual\":{\"amount\":20,\"unit\":\"seat\",\"note\":\"billed annually\"}},\"features\":[\"Everything in Team\",\"Priority support\"],\"recommended\":true,\"rank\":3}\n ]\n }\n]\n",
|
|
16997
|
+
"name": "in-app-upgrade"
|
|
16998
|
+
},
|
|
16999
|
+
{
|
|
17000
|
+
"description": "Settings-page plan picker — single-column list inside a card.",
|
|
17001
|
+
"a2ui": "[\n {\n \"id\": \"pp-settings\",\n \"component\": \"PlanPicker\",\n \"name\": \"plan\",\n \"current\": \"plan_team\",\n \"layout\": \"list\",\n \"plans\": [\n {\"id\":\"plan_team\",\"name\":\"Team\",\"prices\":{\"monthly\":{\"amount\":10,\"unit\":\"seat\"}},\"features\":[\"Unlimited projects\"],\"rank\":2},\n {\"id\":\"plan_pro\",\"name\":\"Pro\",\"prices\":{\"monthly\":{\"amount\":25,\"unit\":\"seat\"}},\"features\":[\"Everything in Team\",\"Priority support\"],\"recommended\":true,\"rank\":3}\n ]\n }\n]\n",
|
|
17002
|
+
"name": "settings-list"
|
|
17003
|
+
}
|
|
17004
|
+
],
|
|
17005
|
+
"keywords": [
|
|
17006
|
+
"plan-picker",
|
|
17007
|
+
"plans",
|
|
17008
|
+
"pricing",
|
|
17009
|
+
"upgrade",
|
|
17010
|
+
"billing",
|
|
17011
|
+
"tier",
|
|
17012
|
+
"tiers",
|
|
17013
|
+
"subscription",
|
|
17014
|
+
"subscribe",
|
|
17015
|
+
"paywall",
|
|
17016
|
+
"choose-plan",
|
|
17017
|
+
"select-plan",
|
|
17018
|
+
"plan-selection"
|
|
17019
|
+
],
|
|
17020
|
+
"name": "PlanPicker",
|
|
17021
|
+
"related": [
|
|
17022
|
+
"OptionCard",
|
|
17023
|
+
"Segmented",
|
|
17024
|
+
"Segment",
|
|
17025
|
+
"Tag",
|
|
17026
|
+
"Button",
|
|
17027
|
+
"Card",
|
|
17028
|
+
"EmptyState",
|
|
17029
|
+
"Skeleton"
|
|
17030
|
+
],
|
|
17031
|
+
"slots": {
|
|
17032
|
+
"empty": {
|
|
17033
|
+
"description": "Custom empty-state shown when `plans` is empty. Falls back to a\ndefault <empty-state-ui> when not provided.\n"
|
|
17034
|
+
},
|
|
17035
|
+
"footer": {
|
|
17036
|
+
"description": "Optional content below the plan grid (compare-plans link, FAQ,\nfine print).\n"
|
|
17037
|
+
},
|
|
17038
|
+
"header": {
|
|
17039
|
+
"description": "Optional content above the plan grid (e.g. a <header> with a\ntitle and a custom cycle toggle). When absent and\n`cycle-toggle` is set, the primitive stamps its own toggle.\n"
|
|
17040
|
+
}
|
|
17041
|
+
},
|
|
17042
|
+
"states": [
|
|
17043
|
+
{
|
|
17044
|
+
"description": "Default — plans rendered, ready for interaction.",
|
|
17045
|
+
"name": "idle"
|
|
17046
|
+
},
|
|
17047
|
+
{
|
|
17048
|
+
"description": "A `data-stream-src` fetch is in flight.",
|
|
17049
|
+
"attribute": "loading",
|
|
17050
|
+
"name": "loading"
|
|
17051
|
+
},
|
|
17052
|
+
{
|
|
17053
|
+
"description": "No plans to render.",
|
|
17054
|
+
"attribute": "empty",
|
|
17055
|
+
"name": "empty"
|
|
17056
|
+
},
|
|
17057
|
+
{
|
|
17058
|
+
"description": "Last `data-stream-src` fetch failed.",
|
|
17059
|
+
"attribute": "error",
|
|
17060
|
+
"name": "error"
|
|
17061
|
+
},
|
|
17062
|
+
{
|
|
17063
|
+
"description": "All cards non-interactive.",
|
|
17064
|
+
"attribute": "disabled",
|
|
17065
|
+
"name": "disabled"
|
|
17066
|
+
}
|
|
17067
|
+
],
|
|
17068
|
+
"status": "experimental",
|
|
17069
|
+
"synonyms": {
|
|
17070
|
+
"plan": [
|
|
17071
|
+
"tier",
|
|
17072
|
+
"subscription",
|
|
17073
|
+
"package"
|
|
17074
|
+
],
|
|
17075
|
+
"pricing": [
|
|
17076
|
+
"plan",
|
|
17077
|
+
"price",
|
|
17078
|
+
"tier"
|
|
17079
|
+
],
|
|
17080
|
+
"upgrade": [
|
|
17081
|
+
"plan-change",
|
|
17082
|
+
"subscribe",
|
|
17083
|
+
"choose-plan"
|
|
17084
|
+
]
|
|
17085
|
+
},
|
|
17086
|
+
"tag": "plan-picker-ui",
|
|
17087
|
+
"tokens": {
|
|
17088
|
+
"--plan-picker-bg": {
|
|
17089
|
+
"description": "Host background. Defaults to transparent.",
|
|
17090
|
+
"default": "transparent"
|
|
17091
|
+
},
|
|
17092
|
+
"--plan-picker-card-bg": {
|
|
17093
|
+
"description": "Card background (cascades to option-card --option-card-bg).",
|
|
17094
|
+
"default": "var(--a-bg)"
|
|
17095
|
+
},
|
|
17096
|
+
"--plan-picker-card-bg-current": {
|
|
17097
|
+
"description": "Current-plan card background.",
|
|
17098
|
+
"default": "var(--a-bg-muted)"
|
|
17099
|
+
},
|
|
17100
|
+
"--plan-picker-card-bg-recommended": {
|
|
17101
|
+
"description": "Recommended-card background.",
|
|
17102
|
+
"default": "var(--a-accent-muted)"
|
|
17103
|
+
},
|
|
17104
|
+
"--plan-picker-card-border": {
|
|
17105
|
+
"description": "Default card border.",
|
|
17106
|
+
"default": "1px solid var(--a-border)"
|
|
17107
|
+
},
|
|
17108
|
+
"--plan-picker-card-border-recommended": {
|
|
17109
|
+
"description": "Recommended-card accent border.",
|
|
17110
|
+
"default": "2px solid var(--a-accent)"
|
|
17111
|
+
},
|
|
17112
|
+
"--plan-picker-card-px": {
|
|
17113
|
+
"description": "Card horizontal padding.",
|
|
17114
|
+
"default": "var(--a-space-5)"
|
|
17115
|
+
},
|
|
17116
|
+
"--plan-picker-card-py": {
|
|
17117
|
+
"description": "Card vertical padding.",
|
|
17118
|
+
"default": "var(--a-space-5)"
|
|
17119
|
+
},
|
|
17120
|
+
"--plan-picker-card-radius": {
|
|
17121
|
+
"description": "Card corner radius.",
|
|
17122
|
+
"default": "var(--a-radius-lg)"
|
|
17123
|
+
},
|
|
17124
|
+
"--plan-picker-card-shadow-recommended": {
|
|
17125
|
+
"description": "Shadow elevation on the recommended card.",
|
|
17126
|
+
"default": "var(--a-shadow-md)"
|
|
17127
|
+
},
|
|
17128
|
+
"--plan-picker-cycle-fg": {
|
|
17129
|
+
"description": "Per-unit / cycle suffix color (e.g. \"/month\").",
|
|
17130
|
+
"default": "var(--a-fg-muted)"
|
|
17131
|
+
},
|
|
17132
|
+
"--plan-picker-feature-icon-fg": {
|
|
17133
|
+
"description": "Feature-row check icon color.",
|
|
17134
|
+
"default": "var(--a-accent)"
|
|
17135
|
+
},
|
|
17136
|
+
"--plan-picker-features-gap": {
|
|
17137
|
+
"description": "Gap between feature list rows.",
|
|
17138
|
+
"default": "var(--a-space-2)"
|
|
17139
|
+
},
|
|
17140
|
+
"--plan-picker-grid-gap": {
|
|
17141
|
+
"description": "Gap between plan cards in grid layout.",
|
|
17142
|
+
"default": "var(--a-space-4)"
|
|
17143
|
+
},
|
|
17144
|
+
"--plan-picker-grid-min": {
|
|
17145
|
+
"description": "Minimum column width in auto-fit grid.",
|
|
17146
|
+
"default": "16rem"
|
|
17147
|
+
},
|
|
17148
|
+
"--plan-picker-price-fg": {
|
|
17149
|
+
"description": "Price color.",
|
|
17150
|
+
"default": "var(--a-fg-strong, var(--a-fg))"
|
|
17151
|
+
},
|
|
17152
|
+
"--plan-picker-price-size": {
|
|
17153
|
+
"description": "Price font size.",
|
|
17154
|
+
"default": "var(--a-text-3xl, 1.875rem)"
|
|
17155
|
+
},
|
|
17156
|
+
"--plan-picker-toggle-justify": {
|
|
17157
|
+
"description": "Justification of the internal cycle toggle row. `center` for\nmarketing layouts; `start` for in-app settings panels.\n",
|
|
17158
|
+
"default": "center"
|
|
17159
|
+
}
|
|
17160
|
+
},
|
|
17161
|
+
"traits": [
|
|
17162
|
+
"focusable"
|
|
14192
17163
|
],
|
|
14193
|
-
"status": "stable",
|
|
14194
|
-
"synonyms": {
|
|
14195
|
-
"tags": [
|
|
14196
|
-
"job-status",
|
|
14197
|
-
"deploy-status",
|
|
14198
|
-
"pipeline-indicator"
|
|
14199
|
-
]
|
|
14200
|
-
},
|
|
14201
|
-
"tag": "pipeline-status-ui",
|
|
14202
|
-
"tokens": {},
|
|
14203
|
-
"traits": [],
|
|
14204
17164
|
"version": 1
|
|
14205
17165
|
}
|
|
14206
17166
|
},
|
|
@@ -14295,7 +17255,14 @@
|
|
|
14295
17255
|
"button",
|
|
14296
17256
|
"divider"
|
|
14297
17257
|
],
|
|
14298
|
-
"slots": {
|
|
17258
|
+
"slots": {
|
|
17259
|
+
"content": {
|
|
17260
|
+
"description": "Popover body — any interactive content. Hoisted to the top-layer via :popover-open when shown. Positioned via the Popover API + CSS Anchor Positioning per [placement] / [gap]; no manual positioning required."
|
|
17261
|
+
},
|
|
17262
|
+
"trigger": {
|
|
17263
|
+
"description": "Focusable element that opens the popover when activated. Typically <button-ui>, but any focusable element works (button, a link with href). MUST be focusable for keyboard accessibility — bare <span> or <div> children will not respond to keyboard activation. Positioned at the anchor point per [placement]."
|
|
17264
|
+
}
|
|
17265
|
+
},
|
|
14299
17266
|
"states": [
|
|
14300
17267
|
{
|
|
14301
17268
|
"description": "Default, ready for interaction.",
|
|
@@ -15891,7 +18858,7 @@
|
|
|
15891
18858
|
},
|
|
15892
18859
|
"Select": {
|
|
15893
18860
|
"title": "Select",
|
|
15894
|
-
"description": "Single-select dropdown primitive — the canonical AdiaUI
|
|
18861
|
+
"description": "Single- and multi-select dropdown primitive — the canonical AdiaUI\nselect control. Form-bearing via UIFormElement: [name], [value],\n[required], [disabled], fires `change`. Options via native\n<option> / <optgroup> children, programmatic `.options` array, or\nJSON [data-options] (hydrated by <editor-shell>'s wireSelects).\nUse for single-select with > 4 options; for ≤ 4 options use\n<segmented-ui> or <radio-ui>. Multi-select via [multiple]: trigger\nrenders <tag-ui> chips per selection, popover shows checkbox-style\noption list, Backspace removes the last chip, [select-all] adds\nbulk controls, [max-chips] caps the visible chip count with a\n\"+N more\" pill. Form value stays a comma-separated string under\n[name] for native <form> compatibility (parse with .split(',')).\n",
|
|
15895
18862
|
"type": "object",
|
|
15896
18863
|
"allOf": [
|
|
15897
18864
|
{
|
|
@@ -15912,6 +18879,11 @@
|
|
|
15912
18879
|
"type": "string",
|
|
15913
18880
|
"default": ""
|
|
15914
18881
|
},
|
|
18882
|
+
"clearable": {
|
|
18883
|
+
"description": "Multi-select only. Adds a clear-all `x` affordance to the trigger\nwhen at least one chip is present. Click empties value and fires\n`change`.\n",
|
|
18884
|
+
"type": "boolean",
|
|
18885
|
+
"default": false
|
|
18886
|
+
},
|
|
15915
18887
|
"component": {
|
|
15916
18888
|
"const": "Select"
|
|
15917
18889
|
},
|
|
@@ -15950,18 +18922,33 @@
|
|
|
15950
18922
|
"type": "string",
|
|
15951
18923
|
"default": ""
|
|
15952
18924
|
},
|
|
18925
|
+
"max": {
|
|
18926
|
+
"description": "Multi-select only. Maximum allowed selections. Toggling past the\ncap is suppressed; the `invalid` event fires with reason=\"max\".\n`0` (default) = unlimited.\n",
|
|
18927
|
+
"type": "number",
|
|
18928
|
+
"default": 0
|
|
18929
|
+
},
|
|
18930
|
+
"max-chips": {
|
|
18931
|
+
"description": "Multi-select only. Caps the number of chips visible in the\ntrigger. When `value.length > max-chips`, the first N chips\nrender plus a \"+M more\" pill that opens the popover on click.\n`0` (default) = unlimited.\n",
|
|
18932
|
+
"type": "number",
|
|
18933
|
+
"default": 0
|
|
18934
|
+
},
|
|
15953
18935
|
"maxlength": {
|
|
15954
18936
|
"description": "Maximum character length for validation",
|
|
15955
18937
|
"type": "number",
|
|
15956
18938
|
"default": null
|
|
15957
18939
|
},
|
|
18940
|
+
"min": {
|
|
18941
|
+
"description": "Multi-select only. Minimum required selections. Below this floor\nthe host's form validity goes invalid (valueMissing) and the\n`invalid` event fires.\n",
|
|
18942
|
+
"type": "number",
|
|
18943
|
+
"default": 0
|
|
18944
|
+
},
|
|
15958
18945
|
"minlength": {
|
|
15959
18946
|
"description": "Minimum character length for validation",
|
|
15960
18947
|
"type": "number",
|
|
15961
18948
|
"default": null
|
|
15962
18949
|
},
|
|
15963
18950
|
"multiple": {
|
|
15964
|
-
"description": "Enables multi-select (comma-separated
|
|
18951
|
+
"description": "Enables multi-select. Trigger renders <tag-ui> chips per selection\n(not comma-separated text); popover renders checkbox-style option\nrows where clicks toggle without closing; Backspace from the\ntrigger removes the last chip. Form value remains comma-separated\nunder [name] for native <form> compatibility.\n",
|
|
15965
18952
|
"type": "boolean",
|
|
15966
18953
|
"default": false
|
|
15967
18954
|
},
|
|
@@ -16000,6 +18987,11 @@
|
|
|
16000
18987
|
"type": "boolean",
|
|
16001
18988
|
"default": false
|
|
16002
18989
|
},
|
|
18990
|
+
"select-all": {
|
|
18991
|
+
"description": "Multi-select only. Renders a \"Select all\" / \"Clear\" control row\nabove the option list. Click selects every non-disabled option;\nwhen already all selected, click clears.\n",
|
|
18992
|
+
"type": "boolean",
|
|
18993
|
+
"default": false
|
|
18994
|
+
},
|
|
16003
18995
|
"size": {
|
|
16004
18996
|
"description": "Sizing scale via universal `[size]` attribute system (packages/web-components/styles/tokens.css). Matches Input's sizing tokens so a Select rendered alongside an Input feels coherent in a form row.",
|
|
16005
18997
|
"type": "string",
|
|
@@ -16035,11 +19027,15 @@
|
|
|
16035
19027
|
"anti_patterns": [],
|
|
16036
19028
|
"category": "input",
|
|
16037
19029
|
"composes": [
|
|
16038
|
-
"icon-ui"
|
|
19030
|
+
"icon-ui",
|
|
19031
|
+
"tag-ui"
|
|
16039
19032
|
],
|
|
16040
19033
|
"events": {
|
|
16041
19034
|
"change": {
|
|
16042
19035
|
"description": "Fired when selected value changes"
|
|
19036
|
+
},
|
|
19037
|
+
"invalid": {
|
|
19038
|
+
"description": "Multi-select only. Fired when a toggle is suppressed by [min] or\n[max] constraints. detail = { value, reason: 'min' | 'max' }.\n"
|
|
16043
19039
|
}
|
|
16044
19040
|
},
|
|
16045
19041
|
"examples": [
|
|
@@ -16048,6 +19044,11 @@
|
|
|
16048
19044
|
"a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"Card\",\n \"children\": [\n \"hdr\",\n \"photo-sec\",\n \"settings-sec\",\n \"ftr\"\n ]\n },\n {\n \"id\": \"hdr\",\n \"component\": \"Header\",\n \"children\": [\n \"hdr-title\",\n \"hdr-desc\"\n ]\n },\n {\n \"id\": \"hdr-title\",\n \"component\": \"Text\",\n \"slot\": \"heading\",\n \"textContent\": \"Bleed Design Settings\",\n \"variant\": \"section\"\n },\n {\n \"id\": \"hdr-desc\",\n \"component\": \"Text\",\n \"slot\": \"description\",\n \"textContent\": \"Configure bleed margins, upload artwork, and preview before approval.\",\n \"variant\": \"body\"\n },\n {\n \"id\": \"photo-sec\",\n \"component\": \"Section\",\n \"children\": [\n \"photo-col\"\n ]\n },\n {\n \"id\": \"photo-col\",\n \"component\": \"Column\",\n \"children\": [\n \"photo-label\",\n \"photo-img\",\n \"photo-btn\"\n ],\n \"gap\": \"3\"\n },\n {\n \"id\": \"photo-label\",\n \"component\": \"Text\",\n \"textContent\": \"Artwork Upload\",\n \"variant\": \"label\"\n },\n {\n \"id\": \"photo-img\",\n \"component\": \"Image\",\n \"src\": \"https://picsum.photos/400/200\",\n \"aspect\": \"2/1\"\n },\n {\n \"id\": \"photo-btn\",\n \"component\": \"Button\",\n \"text\": \"Upload Photo\",\n \"variant\": \"secondary\"\n },\n {\n \"id\": \"settings-sec\",\n \"component\": \"Section\",\n \"children\": [\n \"settings-col\"\n ]\n },\n {\n \"id\": \"settings-col\",\n \"component\": \"Column\",\n \"children\": [\n \"bleed-mode\",\n \"bleed-margin\",\n \"bleed-unit\",\n \"approved\"\n ],\n \"gap\": \"4\"\n },\n {\n \"id\": \"bleed-mode\",\n \"component\": \"Select\",\n \"label\": \"Bleed Mode\",\n \"name\": \"bleed-mode\",\n \"placeholder\": \"Select mode...\"\n },\n {\n \"id\": \"bleed-margin\",\n \"component\": \"Input\",\n \"label\": \"Bleed Margin\",\n \"name\": \"bleed-margin\",\n \"type\": \"number\",\n \"placeholder\": \"e.g. 3\"\n },\n {\n \"id\": \"bleed-unit\",\n \"component\": \"Select\",\n \"label\": \"Unit\",\n \"name\": \"bleed-unit\",\n \"placeholder\": \"mm\"\n },\n {\n \"id\": \"approved\",\n \"component\": \"CheckBox\",\n \"label\": \"Approved for production\",\n \"name\": \"approved\"\n },\n {\n \"id\": \"ftr\",\n \"component\": \"Footer\",\n \"children\": [\n \"preview-btn\",\n \"apply-btn\"\n ]\n },\n {\n \"id\": \"preview-btn\",\n \"component\": \"Button\",\n \"text\": \"Preview\",\n \"variant\": \"secondary\"\n },\n {\n \"id\": \"apply-btn\",\n \"component\": \"Button\",\n \"text\": \"Apply\",\n \"variant\": \"primary\"\n }\n]",
|
|
16049
19045
|
"name": "bleed-design-settings"
|
|
16050
19046
|
},
|
|
19047
|
+
{
|
|
19048
|
+
"description": "Multi-select with chip trigger + checkbox option list (SPEC-040).",
|
|
19049
|
+
"a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"Card\",\n \"children\": [\"sec\"]\n },\n {\n \"id\": \"sec\",\n \"component\": \"Section\",\n \"children\": [\"col\"]\n },\n {\n \"id\": \"col\",\n \"component\": \"Column\",\n \"children\": [\"tags\"],\n \"gap\": \"3\"\n },\n {\n \"id\": \"tags\",\n \"component\": \"Select\",\n \"multiple\": true,\n \"selectAll\": true,\n \"label\": \"Tags\",\n \"name\": \"tags\",\n \"placeholder\": \"Pick tags...\",\n \"value\": \"urgent,backend\"\n }\n]",
|
|
19050
|
+
"name": "multi-select-tags"
|
|
19051
|
+
},
|
|
16051
19052
|
{
|
|
16052
19053
|
"description": "Simple account creation form with text fields, select, and action buttons.",
|
|
16053
19054
|
"a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"Card\",\n \"children\": [\n \"hdr\",\n \"sec\",\n \"ftr\"\n ]\n },\n {\n \"id\": \"hdr\",\n \"component\": \"Header\",\n \"children\": [\n \"title\",\n \"desc\"\n ]\n },\n {\n \"id\": \"title\",\n \"component\": \"Text\",\n \"slot\": \"heading\",\n \"textContent\": \"Create Account\",\n \"variant\": \"section\"\n },\n {\n \"id\": \"desc\",\n \"component\": \"Text\",\n \"slot\": \"description\",\n \"variant\": \"caption\",\n \"textContent\": \"Fill in your details\"\n },\n {\n \"id\": \"sec\",\n \"component\": \"Section\",\n \"children\": [\n \"form\"\n ]\n },\n {\n \"id\": \"form\",\n \"component\": \"Column\",\n \"children\": [\n \"name\",\n \"email\",\n \"role\"\n ],\n \"gap\": \"4\"\n },\n {\n \"id\": \"name\",\n \"component\": \"Input\",\n \"label\": \"Full Name\",\n \"placeholder\": \"Kim Granlund\",\n \"name\": \"name\",\n \"required\": true\n },\n {\n \"id\": \"email\",\n \"component\": \"Input\",\n \"label\": \"Email\",\n \"type\": \"email\",\n \"placeholder\": \"kim@adia.health\",\n \"name\": \"email\",\n \"required\": true\n },\n {\n \"id\": \"role\",\n \"component\": \"Select\",\n \"label\": \"Role\",\n \"placeholder\": \"Choose role...\",\n \"name\": \"role\"\n },\n {\n \"id\": \"ftr\",\n \"component\": \"Footer\",\n \"children\": [\n \"cancel\",\n \"submit\"\n ]\n },\n {\n \"id\": \"cancel\",\n \"component\": \"Button\",\n \"text\": \"Cancel\",\n \"variant\": \"ghost\"\n },\n {\n \"id\": \"submit\",\n \"component\": \"Button\",\n \"text\": \"Create\",\n \"variant\": \"primary\"\n }\n]",
|
|
@@ -16058,7 +19059,13 @@
|
|
|
16058
19059
|
"select",
|
|
16059
19060
|
"dropdown",
|
|
16060
19061
|
"combobox",
|
|
16061
|
-
"autocomplete"
|
|
19062
|
+
"autocomplete",
|
|
19063
|
+
"multi-select",
|
|
19064
|
+
"multiple",
|
|
19065
|
+
"chips",
|
|
19066
|
+
"tokens",
|
|
19067
|
+
"tags",
|
|
19068
|
+
"picker"
|
|
16062
19069
|
],
|
|
16063
19070
|
"name": "UISelect",
|
|
16064
19071
|
"related": [
|
|
@@ -16111,6 +19118,20 @@
|
|
|
16111
19118
|
"menu",
|
|
16112
19119
|
"select",
|
|
16113
19120
|
"form"
|
|
19121
|
+
],
|
|
19122
|
+
"multi-select": [
|
|
19123
|
+
"multiselect",
|
|
19124
|
+
"multi-pick",
|
|
19125
|
+
"chips",
|
|
19126
|
+
"tokens",
|
|
19127
|
+
"tags",
|
|
19128
|
+
"multiple"
|
|
19129
|
+
],
|
|
19130
|
+
"multiple": [
|
|
19131
|
+
"multi-select",
|
|
19132
|
+
"multiselect",
|
|
19133
|
+
"chips",
|
|
19134
|
+
"select-many"
|
|
16114
19135
|
]
|
|
16115
19136
|
},
|
|
16116
19137
|
"tag": "select-ui",
|
|
@@ -16684,12 +19705,13 @@
|
|
|
16684
19705
|
"default": "current"
|
|
16685
19706
|
},
|
|
16686
19707
|
"variant": {
|
|
16687
|
-
"description": "Visual flavor — arc (rotating quarter-circle), ring (full ring with one colored segment), dots (three bouncing dots).",
|
|
19708
|
+
"description": "Visual flavor — `arc` (rotating quarter-circle, the default glyph spinner), `ring` (full ring with one colored segment rotating around it), `dots` (three bouncing dots — animated in a left-to-right wave), `knight` (horizontal \"knight-rider\" bar — a sliding thumb that bounces back-and-forth across a track; widest variant, reads as a determinate-looking bar but is indeterminate by intent).",
|
|
16688
19709
|
"type": "string",
|
|
16689
19710
|
"enum": [
|
|
16690
19711
|
"arc",
|
|
16691
19712
|
"ring",
|
|
16692
|
-
"dots"
|
|
19713
|
+
"dots",
|
|
19714
|
+
"knight"
|
|
16693
19715
|
],
|
|
16694
19716
|
"default": "arc"
|
|
16695
19717
|
}
|
|
@@ -19169,6 +22191,15 @@
|
|
|
19169
22191
|
"description": "Tag label. Renderer routes this to the `text` attribute, rendered via CSS attr(text) on ::after.",
|
|
19170
22192
|
"$ref": "#/$defs/DynamicString"
|
|
19171
22193
|
},
|
|
22194
|
+
"tone": {
|
|
22195
|
+
"description": "Fill style — orthogonal to [variant]. Default (`solid`) for family\nvariants is a saturated bg with on-strong (near-white) text — the\nchip IS the state. Opt-out via `tone=\"muted\"` for a tinted bg with\nscheme-paired text (matches <badge-ui>'s default look) when the\nchip is metadata in a dense list rather than a status stamp. The\n`default` variant stays quiet chrome regardless of tone unless\n`tone=\"solid\"` is set explicitly (high-contrast neutral inverse).\n",
|
|
22196
|
+
"type": "string",
|
|
22197
|
+
"enum": [
|
|
22198
|
+
"solid",
|
|
22199
|
+
"muted"
|
|
22200
|
+
],
|
|
22201
|
+
"default": "solid"
|
|
22202
|
+
},
|
|
19172
22203
|
"variant": {
|
|
19173
22204
|
"description": "Semantic variant — `default | info | success | warning | danger`.",
|
|
19174
22205
|
"type": "string",
|
|
@@ -19286,6 +22317,341 @@
|
|
|
19286
22317
|
"version": 1
|
|
19287
22318
|
}
|
|
19288
22319
|
},
|
|
22320
|
+
"TagsInput": {
|
|
22321
|
+
"title": "TagsInput",
|
|
22322
|
+
"description": "Free-form token input — type a value, press Enter (or the configured\ndelimiter) to commit it as a chip; Backspace from the empty inline\ninput removes the last chip. Distinct from <select-ui multiple>\n(SPEC-040), which is constrained to a fixed option list — tags-input\nis for OPEN sets (labels, email recipients, keyword inputs). Per\nADR-0025 the inline editor is a contenteditable surface (NO native\n`<input>` wrap). Form-bearing via UIFormElement + ElementInternals:\nthe form value is a JSON-serialized string array under `[name]`.\nEach rendered chip is a `<tag-ui removable>`; the `remove` event\ndelegates back to the host. Optional autocompletion: when\n`.suggestions` is non-empty, a popover renders below the field and\nthe host announces as a combobox per WAI-APG.\n",
|
|
22323
|
+
"type": "object",
|
|
22324
|
+
"allOf": [
|
|
22325
|
+
{
|
|
22326
|
+
"$ref": "#/$defs/ComponentCommon"
|
|
22327
|
+
},
|
|
22328
|
+
{
|
|
22329
|
+
"$ref": "#/$defs/CatalogComponentCommon"
|
|
22330
|
+
}
|
|
22331
|
+
],
|
|
22332
|
+
"properties": {
|
|
22333
|
+
"required": {
|
|
22334
|
+
"description": "Required for form validation. Empty array fails `:invalid`.",
|
|
22335
|
+
"type": "boolean",
|
|
22336
|
+
"default": false
|
|
22337
|
+
},
|
|
22338
|
+
"component": {
|
|
22339
|
+
"const": "TagsInput"
|
|
22340
|
+
},
|
|
22341
|
+
"delimiter": {
|
|
22342
|
+
"description": "Inline character that commits the typed value as a chip. The\nsentinel `enter` disables in-line commit — only the Enter key\n(or programmatic `addToken`) commits. Default is `,`.",
|
|
22343
|
+
"type": "string",
|
|
22344
|
+
"default": ","
|
|
22345
|
+
},
|
|
22346
|
+
"disabled": {
|
|
22347
|
+
"description": "Block all interaction; dim the field.",
|
|
22348
|
+
"type": "boolean",
|
|
22349
|
+
"default": false
|
|
22350
|
+
},
|
|
22351
|
+
"max": {
|
|
22352
|
+
"description": "Maximum number of tokens. `0` (default) means unlimited.",
|
|
22353
|
+
"type": "number",
|
|
22354
|
+
"default": 0
|
|
22355
|
+
},
|
|
22356
|
+
"maxLength": {
|
|
22357
|
+
"description": "Maximum per-token character count. `0` (default) means unlimited.",
|
|
22358
|
+
"type": "number",
|
|
22359
|
+
"default": 0
|
|
22360
|
+
},
|
|
22361
|
+
"min": {
|
|
22362
|
+
"description": "Minimum required tokens for form validity.",
|
|
22363
|
+
"type": "number",
|
|
22364
|
+
"default": 0
|
|
22365
|
+
},
|
|
22366
|
+
"minLength": {
|
|
22367
|
+
"description": "Minimum per-token character count after `transform` is applied.",
|
|
22368
|
+
"type": "number",
|
|
22369
|
+
"default": 1
|
|
22370
|
+
},
|
|
22371
|
+
"name": {
|
|
22372
|
+
"description": "Form field name. Serializes the token list as JSON under this key.",
|
|
22373
|
+
"type": "string",
|
|
22374
|
+
"default": ""
|
|
22375
|
+
},
|
|
22376
|
+
"pasteSplit": {
|
|
22377
|
+
"description": "Regex character-class fragment matched against pasted text to\nsplit it into multiple tokens. Default `,\\n` splits on commas\nand newlines. Use `\"\"` to disable paste-splitting entirely.",
|
|
22378
|
+
"type": "string",
|
|
22379
|
+
"default": ",\n"
|
|
22380
|
+
},
|
|
22381
|
+
"placeholder": {
|
|
22382
|
+
"description": "Placeholder text for the inline input when no chips are committed.",
|
|
22383
|
+
"type": "string",
|
|
22384
|
+
"default": "Add tag…"
|
|
22385
|
+
},
|
|
22386
|
+
"readonly": {
|
|
22387
|
+
"description": "Block edits; allow inspection (chips render without remove buttons).",
|
|
22388
|
+
"type": "boolean",
|
|
22389
|
+
"default": false
|
|
22390
|
+
},
|
|
22391
|
+
"size": {
|
|
22392
|
+
"description": "Sizing scale via universal `[size]` attribute system. Matches\nInput + Combobox sizing tokens so a TagsInput rendered alongside\neither feels coherent in a form row.",
|
|
22393
|
+
"type": "string",
|
|
22394
|
+
"enum": [
|
|
22395
|
+
"sm",
|
|
22396
|
+
"md",
|
|
22397
|
+
"lg"
|
|
22398
|
+
],
|
|
22399
|
+
"default": "md"
|
|
22400
|
+
},
|
|
22401
|
+
"suggestions": {
|
|
22402
|
+
"description": "Optional autocomplete strings rendered in a popover below the\nfield. Suggestions are hints, not gates — the typed value still\nwins on commit. JS property only (array reflection skipped).",
|
|
22403
|
+
"$ref": "#/$defs/DynamicStringList"
|
|
22404
|
+
},
|
|
22405
|
+
"transform": {
|
|
22406
|
+
"description": "Normalize tokens on commit. `lowercase` lowercases, `trim` strips\nleading + trailing whitespace, `strip-spaces` removes all\nwhitespace, `\"\"` (default) preserves the typed value.",
|
|
22407
|
+
"type": "string",
|
|
22408
|
+
"enum": [
|
|
22409
|
+
"",
|
|
22410
|
+
"lowercase",
|
|
22411
|
+
"trim",
|
|
22412
|
+
"strip-spaces"
|
|
22413
|
+
],
|
|
22414
|
+
"default": ""
|
|
22415
|
+
},
|
|
22416
|
+
"unique": {
|
|
22417
|
+
"description": "Reject duplicate tokens silently (no `invalid` event for accidental dups).",
|
|
22418
|
+
"type": "boolean",
|
|
22419
|
+
"default": true
|
|
22420
|
+
},
|
|
22421
|
+
"validateFn": {
|
|
22422
|
+
"description": "Per-token validator. Sync `(value, index) => boolean` rejects\nfalse synchronously; async `(value, index) => Promise<boolean>`\nflips the host into `[validating]` while pending. JS property\nonly — not serializable in A2UI JSON; wire post-mount.",
|
|
22423
|
+
"type": "object",
|
|
22424
|
+
"default": null
|
|
22425
|
+
},
|
|
22426
|
+
"value": {
|
|
22427
|
+
"description": "Current token list (string array). Setting `.value = ['a','b']`\nreplaces the rendered chips. Reflection skipped — array values\ndo not round-trip through attribute strings.",
|
|
22428
|
+
"$ref": "#/$defs/DynamicStringList"
|
|
22429
|
+
}
|
|
22430
|
+
},
|
|
22431
|
+
"required": [
|
|
22432
|
+
"component"
|
|
22433
|
+
],
|
|
22434
|
+
"unevaluatedProperties": false,
|
|
22435
|
+
"x-adiaui": {
|
|
22436
|
+
"anti_patterns": [
|
|
22437
|
+
{
|
|
22438
|
+
"fix": "{\"component\": \"Select\", \"multiple\": true, \"options\": [{\"id\": \"a\", \"label\": \"A\"}]}\n",
|
|
22439
|
+
"why": "TagsInput does NOT accept `options`. It is the OPEN-set primitive — any\ntyped string is valid. For closed option lists, use the multi-select\nprimitive with `multiple: true`.\n",
|
|
22440
|
+
"wrong": "{\"component\": \"TagsInput\", \"options\": [{\"id\": \"a\", \"label\": \"A\"}]}\n"
|
|
22441
|
+
},
|
|
22442
|
+
{
|
|
22443
|
+
"fix": "{\"component\": \"TagsInput\", \"value\": [\"bug\", \"high-priority\"]}\n",
|
|
22444
|
+
"why": "Comma-separated string is invalid for `value`. The contract requires\na string array.\n",
|
|
22445
|
+
"wrong": "{\"component\": \"TagsInput\", \"value\": \"bug,high-priority\"}\n"
|
|
22446
|
+
},
|
|
22447
|
+
{
|
|
22448
|
+
"fix": "{\"component\": \"TagsInput\", \"value\": [\"Tag 1\"]}\n",
|
|
22449
|
+
"why": "Chips are rendered automatically from `value`. Slotting Tag children\ndecouples the rendered DOM from the form value and breaks Backspace\nremoval + the `change` event payload.\n",
|
|
22450
|
+
"wrong": "{\"component\": \"TagsInput\", \"children\": [\n {\"component\": \"Tag\", \"text\": \"Tag 1\"}\n]}\n"
|
|
22451
|
+
}
|
|
22452
|
+
],
|
|
22453
|
+
"category": "input",
|
|
22454
|
+
"composes": [
|
|
22455
|
+
"tag-ui",
|
|
22456
|
+
"icon-ui"
|
|
22457
|
+
],
|
|
22458
|
+
"events": {
|
|
22459
|
+
"change": {
|
|
22460
|
+
"description": "Fired after `value` changes (token added or removed).",
|
|
22461
|
+
"detail": {
|
|
22462
|
+
"added": {
|
|
22463
|
+
"description": "Tokens added by this change (`[]` when only removals occurred).",
|
|
22464
|
+
"type": "array"
|
|
22465
|
+
},
|
|
22466
|
+
"removed": {
|
|
22467
|
+
"description": "Tokens removed by this change (`[]` when only additions occurred).",
|
|
22468
|
+
"type": "array"
|
|
22469
|
+
},
|
|
22470
|
+
"value": {
|
|
22471
|
+
"description": "Current token list (string array).",
|
|
22472
|
+
"type": "array"
|
|
22473
|
+
}
|
|
22474
|
+
}
|
|
22475
|
+
},
|
|
22476
|
+
"commit": {
|
|
22477
|
+
"description": "Fired immediately before a token is committed. Call\n`event.preventDefault()` to reject the candidate token.",
|
|
22478
|
+
"detail": {
|
|
22479
|
+
"accepted": {
|
|
22480
|
+
"description": "True unless the consumer calls `preventDefault()`.",
|
|
22481
|
+
"type": "boolean"
|
|
22482
|
+
},
|
|
22483
|
+
"value": {
|
|
22484
|
+
"description": "Candidate token text (post-transform).",
|
|
22485
|
+
"type": "string"
|
|
22486
|
+
}
|
|
22487
|
+
}
|
|
22488
|
+
},
|
|
22489
|
+
"input": {
|
|
22490
|
+
"description": "Fired on each keystroke in the inline input (pre-commit).",
|
|
22491
|
+
"detail": {
|
|
22492
|
+
"query": {
|
|
22493
|
+
"description": "Current typed text in the inline input.",
|
|
22494
|
+
"type": "string"
|
|
22495
|
+
}
|
|
22496
|
+
}
|
|
22497
|
+
},
|
|
22498
|
+
"invalid": {
|
|
22499
|
+
"description": "Fired when a candidate token is rejected. Reasons cover all\nbuilt-in validators and the user-supplied `validateFn`.",
|
|
22500
|
+
"detail": {
|
|
22501
|
+
"reason": {
|
|
22502
|
+
"description": "One of `duplicate` / `too-short` / `too-long` / `validator` / `max`.",
|
|
22503
|
+
"type": "string"
|
|
22504
|
+
},
|
|
22505
|
+
"value": {
|
|
22506
|
+
"description": "Rejected token text.",
|
|
22507
|
+
"type": "string"
|
|
22508
|
+
}
|
|
22509
|
+
}
|
|
22510
|
+
}
|
|
22511
|
+
},
|
|
22512
|
+
"examples": [
|
|
22513
|
+
{
|
|
22514
|
+
"description": "Label input with lowercase normalization + max 10 tags + 2 pre-committed values.",
|
|
22515
|
+
"a2ui": "[\n {\"id\": \"root\", \"component\": \"Card\", \"children\": [\"sec\"]},\n {\"id\": \"sec\", \"component\": \"Section\", \"children\": [\"field\"]},\n {\n \"id\": \"field\",\n \"component\": \"Field\",\n \"label\": \"Labels\",\n \"children\": [\"tags\"]\n },\n {\n \"id\": \"tags\",\n \"component\": \"TagsInput\",\n \"name\": \"labels\",\n \"placeholder\": \"Add a label, press Enter\",\n \"transform\": \"lowercase\",\n \"max\": 10,\n \"value\": [\"bug\", \"high-priority\"]\n }\n]",
|
|
22516
|
+
"name": "canonical-labels"
|
|
22517
|
+
},
|
|
22518
|
+
{
|
|
22519
|
+
"description": "Recipient picker with Enter-only commit (commas are legal in display names).",
|
|
22520
|
+
"a2ui": "[\n {\n \"id\": \"to\",\n \"component\": \"TagsInput\",\n \"name\": \"to\",\n \"placeholder\": \"Email…\",\n \"delimiter\": \"enter\",\n \"transform\": \"trim\"\n }\n]",
|
|
22521
|
+
"name": "email-recipients"
|
|
22522
|
+
}
|
|
22523
|
+
],
|
|
22524
|
+
"keywords": [
|
|
22525
|
+
"tags-input",
|
|
22526
|
+
"tag-input",
|
|
22527
|
+
"token-input",
|
|
22528
|
+
"chips-input",
|
|
22529
|
+
"chip-input",
|
|
22530
|
+
"labels",
|
|
22531
|
+
"recipients",
|
|
22532
|
+
"keywords",
|
|
22533
|
+
"tags",
|
|
22534
|
+
"email-input",
|
|
22535
|
+
"multi-value-input"
|
|
22536
|
+
],
|
|
22537
|
+
"name": "UITagsInput",
|
|
22538
|
+
"related": [
|
|
22539
|
+
"tag",
|
|
22540
|
+
"select",
|
|
22541
|
+
"combobox",
|
|
22542
|
+
"field",
|
|
22543
|
+
"input"
|
|
22544
|
+
],
|
|
22545
|
+
"slots": {
|
|
22546
|
+
"chip": {
|
|
22547
|
+
"description": "Custom chip template — receives `{value, index}` per token.\nWhen absent, each token renders as a default\n`<tag-ui removable text=\"<value>\">`."
|
|
22548
|
+
}
|
|
22549
|
+
},
|
|
22550
|
+
"states": [
|
|
22551
|
+
{
|
|
22552
|
+
"description": "No tokens; no typed text.",
|
|
22553
|
+
"name": "idle"
|
|
22554
|
+
},
|
|
22555
|
+
{
|
|
22556
|
+
"description": "One or more tokens committed.",
|
|
22557
|
+
"attribute": "populated",
|
|
22558
|
+
"name": "populated"
|
|
22559
|
+
},
|
|
22560
|
+
{
|
|
22561
|
+
"description": "User is typing into the inline input.",
|
|
22562
|
+
"attribute": "editing",
|
|
22563
|
+
"name": "editing"
|
|
22564
|
+
},
|
|
22565
|
+
{
|
|
22566
|
+
"description": "Suggestion popover is open.",
|
|
22567
|
+
"attribute": "suggesting",
|
|
22568
|
+
"name": "suggesting"
|
|
22569
|
+
},
|
|
22570
|
+
{
|
|
22571
|
+
"description": "Async `validateFn` is in flight.",
|
|
22572
|
+
"attribute": "validating",
|
|
22573
|
+
"name": "validating"
|
|
22574
|
+
},
|
|
22575
|
+
{
|
|
22576
|
+
"description": "Non-interactive; dimmed.",
|
|
22577
|
+
"attribute": "disabled",
|
|
22578
|
+
"name": "disabled"
|
|
22579
|
+
},
|
|
22580
|
+
{
|
|
22581
|
+
"description": "Read-only; chips render without remove affordance.",
|
|
22582
|
+
"attribute": "readonly",
|
|
22583
|
+
"name": "readonly"
|
|
22584
|
+
}
|
|
22585
|
+
],
|
|
22586
|
+
"status": "experimental",
|
|
22587
|
+
"synonyms": {
|
|
22588
|
+
"chips-input": [
|
|
22589
|
+
"tags-input",
|
|
22590
|
+
"chip-input",
|
|
22591
|
+
"token-input"
|
|
22592
|
+
],
|
|
22593
|
+
"labels": [
|
|
22594
|
+
"tags",
|
|
22595
|
+
"tag-input",
|
|
22596
|
+
"labels-input"
|
|
22597
|
+
],
|
|
22598
|
+
"recipients": [
|
|
22599
|
+
"email-input",
|
|
22600
|
+
"tags-input",
|
|
22601
|
+
"to-field"
|
|
22602
|
+
],
|
|
22603
|
+
"tags-input": [
|
|
22604
|
+
"tag-input",
|
|
22605
|
+
"chip-input",
|
|
22606
|
+
"token-input",
|
|
22607
|
+
"tokenizer"
|
|
22608
|
+
],
|
|
22609
|
+
"token-input": [
|
|
22610
|
+
"tags-input",
|
|
22611
|
+
"chip-input",
|
|
22612
|
+
"tokenizer"
|
|
22613
|
+
]
|
|
22614
|
+
},
|
|
22615
|
+
"tag": "tags-input-ui",
|
|
22616
|
+
"tokens": {
|
|
22617
|
+
"--tags-input-bg": {
|
|
22618
|
+
"description": "Host background color."
|
|
22619
|
+
},
|
|
22620
|
+
"--tags-input-border": {
|
|
22621
|
+
"description": "Host border color (idle)."
|
|
22622
|
+
},
|
|
22623
|
+
"--tags-input-border-hover": {
|
|
22624
|
+
"description": "Host border color on hover."
|
|
22625
|
+
},
|
|
22626
|
+
"--tags-input-chip-bg-invalid": {
|
|
22627
|
+
"description": "Chip background color when a chip is marked invalid (validator rejection echo)."
|
|
22628
|
+
},
|
|
22629
|
+
"--tags-input-fg": {
|
|
22630
|
+
"description": "Host foreground (typed-text color)."
|
|
22631
|
+
},
|
|
22632
|
+
"--tags-input-focus-ring": {
|
|
22633
|
+
"description": "Focus-ring box-shadow when the host is focus-within."
|
|
22634
|
+
},
|
|
22635
|
+
"--tags-input-gap": {
|
|
22636
|
+
"description": "Gap between chips and the inline input."
|
|
22637
|
+
},
|
|
22638
|
+
"--tags-input-placeholder-fg": {
|
|
22639
|
+
"description": "Placeholder color for the empty inline input."
|
|
22640
|
+
},
|
|
22641
|
+
"--tags-input-px": {
|
|
22642
|
+
"description": "Horizontal padding inside the chip-cluster wrapper."
|
|
22643
|
+
},
|
|
22644
|
+
"--tags-input-py": {
|
|
22645
|
+
"description": "Vertical padding inside the chip-cluster wrapper."
|
|
22646
|
+
},
|
|
22647
|
+
"--tags-input-radius": {
|
|
22648
|
+
"description": "Host border radius."
|
|
22649
|
+
}
|
|
22650
|
+
},
|
|
22651
|
+
"traits": [],
|
|
22652
|
+
"version": 1
|
|
22653
|
+
}
|
|
22654
|
+
},
|
|
19289
22655
|
"Text": {
|
|
19290
22656
|
"title": "Text",
|
|
19291
22657
|
"description": "Typography wrapper that applies role tokens. Supports truncation and line clamping.",
|
|
@@ -19457,7 +22823,7 @@
|
|
|
19457
22823
|
},
|
|
19458
22824
|
"Textarea": {
|
|
19459
22825
|
"title": "Textarea",
|
|
19460
|
-
"description": "Multi-line text input primitive — the host IS the contenteditable\nsurface (per ADR-0025, no native <textarea> wrapped underneath).\nForm-bearing via UIFormElement: [name], [value], [required],\n[disabled], [readonly], fires `change` on blur and `input` per\nkeystroke. Enter inserts a newline
|
|
22826
|
+
"description": "Multi-line text input primitive — the host IS the contenteditable\nsurface (per ADR-0025, no native <textarea> wrapped underneath).\nForm-bearing via UIFormElement: [name], [value], [required],\n[disabled], [readonly], fires `change` on blur and `input` per\nkeystroke. Enter (without Shift) dispatches a bubbling `submit`\nevent — Shift+Enter inserts a newline. This is unconditional;\nthere is no opt-in/opt-out attribute. For Enter-to-send composers\nuse <chat-input-ui> inside <chat-composer>. Wrap in <field-ui\nlabel=\"…\"> for the canonical labeled stack.\n",
|
|
19461
22827
|
"type": "object",
|
|
19462
22828
|
"allOf": [
|
|
19463
22829
|
{
|