Components
Input
A text field, and the Field parts that label and describe it. Field wires the association itself, so no id strings are ever typed twice.
Sizes
sm is 24px, md is the 28px workhorse, and lg is 36px for a prominent form. title uses larger type for inline title editing. The native size attribute is omitted so Dowel's visual scale can use the name.
import { Input } from "@karnstack/dowel";
<Input name="compact-search" size="sm" placeholder="Search components" />
<Input name="search" placeholder="Search components" />
<Input name="prominent-search" size="lg" placeholder="Search components" />Borderless editing
Use variant="bare" when the surrounding composer is already the surface. The control stays transparent and borderless, so hierarchy comes from type and spacing instead of another box.
<Input
aria-label="Issue title"
name="title"
variant="bare"
size="title"
placeholder="Add title"
/>
<Textarea
aria-label="Issue description"
name="description"
variant="bare"
placeholder="What needs to change, and why?"
/>Textarea
Textarea shares Input's surface and bare variants and integrates with Field labels, descriptions, validation, and form values.
Keep it useful for customers.
<Field.Root>
<Field.Label>Release notes</Field.Label>
<Textarea name="releaseNotes" placeholder="What changed?" />
<Field.Description>Keep it useful for customers.</Field.Description>
</Field.Root>Field
A dowel Input inside Field.Root is associated with its label automatically. Field.Label omits htmlFor on purpose: a hand-written one would win over the generated association, which is the exact bug Field exists to remove.
Lowercase letters and dashes only.
import { Field, Input } from "@karnstack/dowel";
<Field.Root>
<Field.Label>Workspace name</Field.Label>
<Input name="workspace" placeholder="karnstack" />
<Field.Description>
Lowercase letters and dashes only.
</Field.Description>
</Field.Root>Validation
invalid sets aria-invalid and turns the border to the danger tone. It is applied conditionally, so leaving it unset never clobbers an aria-invalid that Field validation computed — add Field.Error with a match to surface the message Field computes.
<Field.Root>
<Field.Label>Email</Field.Label>
<Input name="email" invalid defaultValue="not-an-email" />
</Field.Root>
<Input aria-label="Immutable value" name="immutable" disabled defaultValue="Read only" />