KQ-1506 · SHY/LABEL
Shy Label
A text field whose label sits inside it and steps aside as you type: focus lifts it above the field on springs.glide with its letters hopping in a ripple from the caret's side, leaving a faint imprint inside, and as the text reaches the imprint each nearby letter hops up and away along a curved, tipping path on its own spring, shrinks and flies to its twin in the raised label, which hops on springs.flick and settles on springs.recoil as its letter regroups. Deleting brings the letters back down on springs.glide. Validation slides the message 4 px into place on glide over the hint while the border, label and an end icon popping in on snap take the state's colour; it is a real input with a real label, so the keyboard, selection and autofill are the browser's own.
The Coldbrook Steep
Brew notes and new roasts, monthly.
We send one letter a month.
empty · checked when you leave
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/shy-label
Props
- label
- string
- default —
- The field's label: inside the field at rest, above it once there is focus or text. Its accessible text is a real <label for>.
- value / defaultValue
- string
- default — / ""
- The text, controlled or uncontrolled.
- onValueChange
- (value: string) => void
- default —
- Fires on every edit with the new text.
- hint
- string
- default —
- A line under the field while there is no validation message.
- state
- "default" | "success" | "error"
- default "default"
- The validation state: the border, raised label and an end icon take its colour, and message slides in under the field.
- message
- string
- default —
- Shown and announced under the field for success and error; the hint returns for default.
- type
- "text" | "email" | "password" | "search" | "tel" | "url"
- default "text"
- The input's type; a password measures its dots for the caret.
- name
- string
- default —
- A form field name for the input.
- autoComplete
- string
- default —
- Passed to the input.
- scatter
- number
- default 0.6
- How lively the letters are as they step aside, 0 to 1: 0 just fades them, 1 sends them on high, tilting arcs.
- reach
- number
- default 20
- How far ahead of the caret, in px, a letter starts to step aside.
- size
- "sm" | "md" | "lg"
- default "md"
- Field height (40, 48 or 56 px) and type size.
- color
- "cobalt" | "signal" | "ember" | "rose" | string
- default "cobalt"
- The focused border and raised label: a preset tuned for both themes or any CSS colour.
- required
- boolean
- default false
- Passed to the input.
- disabled
- boolean
- default false
- Disables the input and dims the field.
- onFocus / onBlur
- (event: React.FocusEvent<HTMLInputElement>) => void
- default —
- The input's focus handlers, e.g. to validate on blur.
- className
- string
- default —
- Classes for the outer column.
| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | — | The field's label: inside the field at rest, above it once there is focus or text. Its accessible text is a real <label for>. |
| value / defaultValue | string | — / "" | The text, controlled or uncontrolled. |
| onValueChange | (value: string) => void | — | Fires on every edit with the new text. |
| hint | string | — | A line under the field while there is no validation message. |
| state | "default" | "success" | "error" | "default" | The validation state: the border, raised label and an end icon take its colour, and message slides in under the field. |
| message | string | — | Shown and announced under the field for success and error; the hint returns for default. |
| type | "text" | "email" | "password" | "search" | "tel" | "url" | "text" | The input's type; a password measures its dots for the caret. |
| name | string | — | A form field name for the input. |
| autoComplete | string | — | Passed to the input. |
| scatter | number | 0.6 | How lively the letters are as they step aside, 0 to 1: 0 just fades them, 1 sends them on high, tilting arcs. |
| reach | number | 20 | How far ahead of the caret, in px, a letter starts to step aside. |
| size | "sm" | "md" | "lg" | "md" | Field height (40, 48 or 56 px) and type size. |
| color | "cobalt" | "signal" | "ember" | "rose" | string | "cobalt" | The focused border and raised label: a preset tuned for both themes or any CSS colour. |
| required | boolean | false | Passed to the input. |
| disabled | boolean | false | Disables the input and dims the field. |
| onFocus / onBlur | (event: React.FocusEvent<HTMLInputElement>) => void | — | The input's focus handlers, e.g. to validate on blur. |
| className | string | — | Classes for the outer column. |