textmachine/frontend/src/ui/TextField.tsx

35 lines
1.3 KiB
TypeScript

import { Input, Label, Text, TextField as AriaTextField } from 'react-aria-components';
import field from './Field.module.css';
import styles from './TextField.module.css';
interface Props {
label: string;
value: string;
onChange: (value: string) => void;
/**
* The hint in an empty field; it has a job of its own — to say what happens if the field is left
* untouched.
*/
placeholder?: string;
/** The line under the field: what exactly an empty field will end in, not general advice. */
hint?: string;
}
// An ordinary text field of a form. It differs from FilterField in role, not in look: a filter has
// no label and sends nothing, here a label is mandatory — this is a form.
export function TextField({ label, value, onChange, placeholder, hint }: Props) {
return (
<AriaTextField className={styles.field} value={value} onChange={onChange}>
<Label className={styles.label}>{label}</Label>
<Input className={`${field.input} ${field.framed}`} placeholder={placeholder} />
{/* slot="description" is not decoration: the library hangs `aria-describedby` on it, and
without that the hint is not heard by the one who needs it most of all. */}
{hint && (
<Text className={styles.hint} slot="description">
{hint}
</Text>
)}
</AriaTextField>
);
}