@propellerads/error-label
v7.0.0
Published
The `!` mark at the end of a field and the list of errors behind it. Every field in the library draws its errors with it: `@propellerads/input` for text, passwords, numbers and textareas, and Select, TagsInput, RadioGroup, TimePicker, EditableField and Im
Keywords
Readme
ErrorLabel
The ! mark at the end of a field and the list of errors behind it. Every
field in the library draws its errors with it: @propellerads/input for text,
passwords, numbers and textareas, and Select, TagsInput, RadioGroup, TimePicker,
EditableField and ImageUploader.
Version 6 is built the way Button is: one stylesheet, the list is Base UI's Popover, every colour, gap, corner and duration comes from @propellerads/tokens.
Installation
bun add @propellerads/error-labelThe built entry imports its own stylesheet. The tokens are the app's:
import '@propellerads/tokens/common.css';
import '@propellerads/tokens/propellerads.css'; // or monetag / propush / zeydooUse
In a field of the library it is already there. On its own:
import ErrorLabel, {errorLabelTextId} from '@propellerads/error-label';
<input id="bid" aria-invalid aria-describedby={errorLabelTextId('bid')} />
<ErrorLabel elementId="bid" errors={['The bid is below the minimum']} />
<ErrorLabel elementId="bid" tone="warning" errors={['The bid is 8× the market average']} />- The mark is a 20px disc in the tone, as in v5, with the
!in the page colour: it reads as a hole in the disc in either theme. It grows in from 80% the moment the error appears. - The list opens on hover and on click, so it works under a finger as well as a
pointer. It appears from 95% in
--duration-200, stands above the mark, flips below it at the edge of the screen, and closes on Escape or a click outside. - The errors are kept beside the mark as hidden text. Point the control's
aria-describedbyaterrorLabelTextId(elementId)and a screen reader reads them on focus. - An error with an empty message still shows the mark, and opens nothing.
Props
| Prop | Type | Default | What it does |
|------------------|-----------------------------|-------------|-----------------------------------------------------------|
| elementId | string | — | The mark gets error-label-${elementId}, as in v5 |
| errors | readonly string[] | — | Nothing renders for an empty list |
| tone | 'danger' \| 'warning' | 'danger' | Red with white text, or yellow with dark text |
| mode | 'tooltip' \| 'inline' | 'tooltip' | inline writes the list out beside the mark |
| onClick | () => void | — | Called when the mark is clicked |
| hasDescription | boolean | true | Off when the field writes the hidden text itself |
| errorColor | string | — | Deprecated: any value switches to tone="warning" |
Tokens
| What | Token |
|---------------|--------------------------------------------------------------|
| Danger | --color-danger, list text --color-light |
| Warning | --color-warning, list text --color-dark (white falls to 1.91) |
| The ! | --color-light-inversion, the page colour |
| List | the tone, --shadow-middle, --radius-8, --font-description |
| Motion | --duration-200 in, --duration-100 out |
--error-label-z-index is 3000 by default, the layer of Dialog. The list is
rendered at the end of <body>, so inside a dialog it draws on top of it. A
modal of its own that stands higher needs the variable raised.
