Household pattern
ContractLink
The pill that connects an outcome to the contract line that produced it.
States
Allowed by (acted)
Asked because (Ask first)
Asked because (limit hit)
Refused by (hard rule)
Blocked by (Never)
Small
As a button
no href
When to use
- On every TraceEvent, ApprovalCard and Receipt.
- Anywhere an outcome is shown away from the editor.
When not to
- As a general-purpose tag or chip.
- To link to anything other than a contract line.
Props
| Name | Type | Notes |
|---|---|---|
| link* | ContractLink | From describeLink(event, contract): prefix, parts, text, anchor. |
| tone* | "acted" | "asked" | "downgraded" | "refused" | Use linkToneFor(event). Never infer a tone from the link text. |
| href | string | The editor route. The anchor is appended as a hash. Without href it renders as a button. |
| onClick / size | () => void, "sm" | "md" |
* required
Accessibility invariants
- The accessible name is the full sentence plus "Open this line in the contract".
- Renders as a real link when it navigates and a real button when it does not.
- Text changes under what-if crossfade and are announced by the surrounding aria-live region, not by the pill.
Agent instructions
For anything generating UI from this system
Whenever you show an evaluated event, call describeLink(event, contract) and render a ContractLink with that result, tone from linkToneFor(event), and href pointing at the template's editor route. Do not compose the sentence yourself and do not change the prefix wording (Allowed by, Asked because, Refused by, Blocked by).