Household pattern
HardRule
A plain-language never that takes a deliberate hold or explicit acknowledgement to turn off and one tap to turn back on.
States
On
the resting state
Never buy alcohol
Confirming
the reason and both confirmation paths
Never buy alcohol
Anything with alcohol in it is a decision for a person, every time.
Click confirmation
Never buy alcohol
Anything with alcohol in it is a decision for a person, every time.
Off
one tap to turn back on
Never buy alcohol
Anything with alcohol in it is a decision for a person, every time.
Read-only
Never order from a store other than Greenleaf Market and Valley Wholesale
Highlighted (linked to)
Never buy alcohol
When to use
- One per hard rule in the contract, in a list under a "Never" heading.
- Read-only wherever a refusal needs to show the rule that caused it.
When not to
- For anything the user should be able to flip casually. That is a Toggle or a ladder rung.
- For limits with a number in them. Those are Ceilings.
Props
| Name | Type | Notes |
|---|---|---|
| rule* | HardRule | text, why, forbids, enabled. |
| onChange | (enabled: boolean) => void | Called after a completed hold or acknowledged confirmation (off), or a single tap (on). |
| id | string | Anchor id, `rule-<ruleId>`. |
| defaultConfirming / defaultAlternative | boolean | Initially expand confirmation and its click alternative; for state demos. |
| readOnly / highlighted | boolean | State flags. |
* required
Accessibility invariants
- Keep the one-second pointer/keyboard hold. The alternative path uses native click activation, an acknowledgement checkbox, and an explicit confirmation button for assistive technology.
- An incomplete hold cancels on blur. Completing a change returns focus to the rule action.
- The rule's reason is shown before the destructive control appears, so a screen-reader user hears why first.
- Off is shown with a strike-through, a chip that says Off, and an open-lock glyph. Never only a colour.
- Turning back on is a plain button. Undoing should always be easier than doing.
Agent instructions
For anything generating UI from this system
List HardRule components for contract.hardRules under a heading such as "Never". Pass the rule and an onChange that calls setHardRule from lib/contract/update. Do not wrap it in a Toggle, do not add a confirm dialog of your own, and do not offer a way to edit the rule's wording; only enabled changes. Use id="rule-" + rule.id.