A labelled text input with an optional hint or error, and a reveal button for passwords.
import { Field } from "@meowerse/ui"; · source packages/ui/src/components/Field.tsx
variants and states
letters, digits and _ only
with a hint
password — with a reveal button
that name is taken — try another
error
disabled
floating label — labelPlacement="float": rests inside while empty, moves onto the border once focused or filled
12–128 characters
floating label, filled — stays visible on the border; never runs under the reveal button
props
prop
type
default
required
type (html)
HTMLInputTypeAttribute
"text"
no
label
string the visible label, always shown and tied to the input.
—
yes
labelPlacement
"above" | "float" where the label sits: above the input, or float — inside the empty input like a placeholder, moving up
onto its top border once it is focused or filled, so it stays visible (CSS only, works without JS).
"above"
no
hint
string helper text shown below the input, linked with aria-describedby.
—
no
error
string an error message shown instead of the hint; also sets aria-invalid.
—
no
…plus all InputHTMLAttributes<HTMLInputElement>.
css custom properties
variable
dark
light
--c-bg-elev
#111113
#f1f0ec
--c-danger
#ff6b63
#b42318
--c-fg
#ededeb
#1a1a1c
--c-fg-muted
#b3b3af
#46464a
--c-fg-subtle
#8c8c88
#5e5e5b
--c-focus
#00ff82
#0a6e3c
--c-line-input
#6a6a70
#7a7973
--control-height
44px
same
--d-fast
120ms
same
--disabled-opacity
0.5
same
--ease
cubic-bezier(.16,1,.3,1)
same
--fs-2
0.8125rem
same
--fs-4
1rem
same
--r-m
4px
same
--sp-1
4px
same
--sp-2
8px
same
--sp-3
12px
same
Classes: .mw-field. Set any of these variables on an ancestor (or wrap a subtree in .mw-theme--dark / .mw-theme--light) to restyle just that part of a page.
usage
with a hint
tsx
import { Field } from "@meowerse/ui";
<Field label="username" hint="letters, digits and _ only" autoCapitalize="none" autoCorrect="off" spellCheck={false} />
import { Field } from "@meowerse/ui";
<Field label="password" labelPlacement="float" type="password" defaultValue="correct horse" hint="12–128 characters" />
accessibility
The label is always visible and tied to the input.
With labelPlacement="float" the label is still the input's real <label>, so its accessible name doesn't change; it only moves (CSS alone, no JS), keeping a long label on one line with an ellipsis.
The hint and the error are linked with aria-describedby; an error sets aria-invalid and is announced.
The reveal button is 44×44 px and named "show password" or "hide password".
Inputs are 16 px, so phones don't zoom in.
key
does
Tab
moves to the input, then to the reveal button
do and don't
[ ok ] do
Say what is wrong and how to fix it in the error.
Use autoCapitalize="none" for usernames.
[fail] don't
Don't use the placeholder as the label.
Don't validate on every keystroke before the person has finished.