Current section
Files
Jump to
Current section
Files
live_interaction_contracts
README.md
README.md
# live_interaction_contracts
Executable interaction contracts for Phoenix LiveView.
This package checks whether browser-native interaction state survives LiveView
patches. It ships a conformance harness, a delegation ledger, and a small set of
unstyled reference components that are backed by those contracts.
Use it when you need to know whether a popover, menu, tooltip, select, combobox,
dialog adapter, focus handoff, or async query shell is safe under LiveView DOM
patching.
## Why this exists
LiveView gives the server authority over rendered HTML, but many interaction
machines keep their state in the browser: top-layer popovers, active descendants,
focus, selection, pending input, and listbox shells.
The hard failures happen when both sides think they own the same state. A patch
replaces a node, a client hook rebinds, the server renders stale results, or the
browser keeps state that the server cannot observe.
`live_interaction_contracts` turns those cases into executable contracts. Each
green claim is backed by browser tests across Chromium, Firefox, and WebKit.
Amber and unknown cases stay explicit.
The shortest proof is the harness's **one patch, three outcomes** trial: the same
acknowledged diff leaves the same DOM node alive in a popover, a raw modal dialog,
and an `open`-protected modal dialog. The popover stays coherent, the raw dialog is
torn into `open=false` while `:modal` still matches, and the protected dialog stays
coherent while its server-rendered child still updates. The controlled comparison is
raw versus protected dialog; popover is the native-safe contrast.
## What ships
- A Mix task that runs the conformance harness against real browsers.
- A generated delegation ledger that classifies each state machine as green,
amber, red, or unknown.
- Reference components for `<.popover>`, `<.tooltip>`, `<.menu>`, `<.select>`,
and `<.combobox>`.
- A `LiveInteractionContracts.Channel` helper for monotonic async query results.
- Contract documents that define the state ownership rules.
- A consumer contract runner that checks an already-started LiveView app in a real
browser and emits machine-readable evidence.
The components are intentionally unstyled. They are reference primitives, not a
finished UI kit. The future UI kit direction is Temper UI; this package is the
proof layer underneath it.
## Install
For harness, ledger, and CI use:
```elixir
{:live_interaction_contracts, "~> 1.0", only: [:dev, :test], runtime: false}
```
If you also use the reference components at runtime:
```elixir
{:live_interaction_contracts, "~> 1.0"}
```
The harness requires `elixir`, `node`, and Playwright browsers:
```sh
npm install --save-dev playwright@1.61.1
npx playwright install chromium firefox webkit
```
The reference components require Phoenix LiveView 1.1 or later. Their client JS
ships as Phoenix colocated hooks. After `mix compile`, register the extracted
hooks in your `app.js`:
```javascript
import {hooks as licHooks} from "phoenix-colocated/live_interaction_contracts";
new LiveSocket("/live", Socket, {hooks: {...hooks, ...licHooks}});
```
## Reference component example
```elixir
defmodule MyAppWeb.Demo do
use Phoenix.Component
use LiveInteractionContracts.Components
def demo(assigns) do
~H"""
<.popover id="demo" placement="bottom">
<:trigger>Open</:trigger>
<:content>Patch-safe by contract.</:content>
</.popover>
"""
end
end
```
## Run the harness
Run these commands from your Phoenix project:
```sh
# all stable browser engines
mix live_interaction_contracts.test
# one browser
mix live_interaction_contracts.test --browser chromium
# one suite
mix live_interaction_contracts.test --suite combobox
# early warning against LiveView main
mix live_interaction_contracts.test --lv "github:phoenixframework/phoenix_live_view#main"
# regenerate the delegation ledger
mix live_interaction_contracts.ledger
# advisory app audit for patch-safety and dual-write risk
mix live_interaction_contracts.audit --path /path/to/app
# compare two harness result sets
mix live_interaction_contracts.compare --a before.json --b after.json
```
By default, the harness tests against your project's LiveView version.
## Check your own LiveView
Skills and code review can predict ownership risks; this command verifies the real
result. Start your application, then point a strict v1 JSON contract at it:
```sh
mix live_interaction_contracts.check \
--url http://127.0.0.1:4000 \
--contract test/interaction_contracts/account_menu.json
```
The contract describes real click activation, a click that causes a LiveView patch,
a subject-local attribute whose change proves the patch arrived, and before/after
expectations for DOM object identity, popover, dialog, or focus state. The runner
writes `live-interaction-contracts-result.json` and exits non-zero for failed,
inconclusive, or invalid runs. See `BLUEPRINT.md` and
`priv/harness/consumer-popover-contract.json` for the v1 format.
Targets are restricted to loopback by default because contract clicks may cause real
application side effects. `--allow-remote` exists only for an explicitly safe test
environment; do not point the runner at production.
### 1.x compatibility
Because this package is already published as 1.x, existing Mix tasks, component APIs,
v1 contract fields, result fields, and exit-code meanings are compatibility
constraints. New probes and optional evidence may be added within 1.x; removing or
reinterpreting existing fields requires a new contract/result schema and a package
major release. M1 hardening is additive and does not weaken existing contracts.
## Current v1 coverage
Green reference machines:
- Popover
- Tooltip
- Menu
- Select
- Combobox
- Cursor coordination
- Versioned async query channel
Amber:
- Dialog adapter, with documented restrictions.
Unknown:
- Native select popup open-state.
- Real-device IME behavior.
## Read next
- `SPEC.md`: v1 frozen scope and project claims.
- `KERNEL.md`: the state ownership model.
- `CONFORMANCE.md`: harness and CI behavior.
- `BUILDING_COMPONENTS.md`: how to add the next contract-backed component.
- `PROJECT_MAP.md`: where the detailed evidence lives in this repository.