TextField
ui forminput
Formularfeld-Wrapper: TextInput, TextArea und SelectInput mit optionalem Label (via SectionLabel) und Hinweistext. Einheitliche Höhe/Padding über die Field-Tokens; SelectInput hat ein eigenes Chevron statt des System-Pfeils.
Abhängigkeiten
Barrierefreiheit
- Feld ist von einem <label> umschlossen — Klick auf das Label fokussiert das Control.
- Eigenes Select-Chevron; appearance:none entfernt den System-Pfeil.
Beispiele
Eingaben
<TextInput label="Name" placeholder="Gemeinde" hint="Pflichtfeld" />
<TextArea label="Notiz" />
<SelectInput label="Plan">
<option>free</option>
<option>pro</option>
</SelectInput> Genutzte Tokens · 21
--accent--bg--border--control-height--ease-standard--fg--field-chevron--field-chevron-offset--field-chevron-pad--field-font-size--field-line-height--field-pad-x--field-pad-y--field-radius--focus-ring--font-stage--motion-fast--muted--surface--text-base--text-xs
Quelldateien
components/ui/TextField.tsx tsx
import type {
InputHTMLAttributes,
ReactNode,
SelectHTMLAttributes,
TextareaHTMLAttributes,
} from 'react';
import { SectionLabel } from './SectionLabel';
import styles from './TextField.module.css';
interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
label?: string;
hint?: string;
}
export function TextInput({ label, hint, className, id, ...rest }: InputProps) {
return (
<label className={styles.field}>
{label && <SectionLabel as="span">{label}</SectionLabel>}
<input id={id} className={`${styles.input} ${className ?? ''}`} {...rest} />
{hint && <span className={styles.hint}>{hint}</span>}
</label>
);
}
interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
label?: string;
hint?: string;
}
export function TextArea({ label, hint, className, ...rest }: TextareaProps) {
return (
<label className={styles.field}>
{label && <SectionLabel as="span">{label}</SectionLabel>}
<textarea className={`${styles.textarea} ${className ?? ''}`} {...rest} />
{hint && <span className={styles.hint}>{hint}</span>}
</label>
);
}
interface SelectProps extends SelectHTMLAttributes<HTMLSelectElement> {
label?: string;
hint?: string;
children?: ReactNode;
}
export function SelectInput({ label, hint, className, children, ...rest }: SelectProps) {
return (
<label className={styles.field}>
{label && <SectionLabel as="span">{label}</SectionLabel>}
<select className={`${styles.select} ${className ?? ''}`} {...rest}>
{children}
</select>
{hint && <span className={styles.hint}>{hint}</span>}
</label>
);
}
components/ui/TextField.module.css css
.field {
display: flex;
flex-direction: column;
gap: 6px;
}
.input,
.textarea,
.select {
width: 100%;
border-radius: var(--field-radius);
border: 1px solid var(--border);
background: var(--bg);
font-size: var(--field-font-size);
line-height: var(--field-line-height);
font-family: inherit;
color: var(--fg);
outline: none;
box-sizing: border-box;
transition:
border-color var(--motion-fast) var(--ease-standard),
box-shadow var(--motion-fast) var(--ease-standard);
}
.input,
.textarea {
padding: var(--field-pad-y) var(--field-pad-x);
}
.input {
height: var(--control-height);
}
.textarea {
font-family: var(--font-stage);
font-size: var(--text-base);
min-height: 80px;
resize: vertical;
}
/* Native `<select>` ignoriert vertikales Padding nicht so verlässlich wie
* `<input>` — daher height + line-height:1 ohne Y-Padding, plus eigenes
* Chevron-Background (appearance:none entfernt das System-Pfeil-Icon). */
.select {
height: var(--control-height);
padding: 0 var(--field-chevron-pad) 0 var(--field-pad-x);
line-height: 1;
cursor: pointer;
appearance: none;
background-image: var(--field-chevron);
background-repeat: no-repeat;
background-position: right var(--field-chevron-offset) center;
background-size: 12px 12px;
}
.select:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.input:focus-visible,
.textarea:focus-visible,
.select:focus-visible {
border-color: var(--accent);
box-shadow: var(--focus-ring);
background-color: var(--surface);
}
.hint {
font-size: var(--text-xs);
color: var(--muted);
}
Holen
# MCP (Claude Code / Cursor)
get_component({ name: "text-field" })
# Registry direkt
https://www.ekklesi.tools/design/registry/components/text-field.json