Text input component #30
@ -12,7 +12,8 @@ export interface TextInputProps
|
||||
error?: boolean;
|
||||
|
stne3960 marked this conversation as resolved
|
||||
fullWidth?: boolean;
|
||||
customWidth?: string;
|
||||
label?: string;
|
||||
label: string;
|
||||
|
stne3960 marked this conversation as resolved
Outdated
ansv7779
commented
Should label really be optional? Will that not lead to accessibility issues? Should label really be optional? Will that not lead to accessibility issues?
stne3960
commented
In practical implementation, probably not, that was how the component was designed in the specification. In practical implementation, probably not, that was how the component was designed in the specification.
|
||||
hideLabel?: boolean;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
@ -70,6 +71,7 @@ export default function TextInput({
|
||||
fullWidth = false,
|
||||
customWidth,
|
||||
label,
|
||||
hideLabel = false,
|
||||
message,
|
||||
className = "",
|
||||
...props
|
||||
@ -78,6 +80,7 @@ export default function TextInput({
|
||||
const widthStyle = customWidth ? { width: customWidth } : undefined;
|
||||
const stateClasses = error ? errorStateClasses : defaultStateClasses;
|
||||
const inputPadding = Icon ? "pr-(--padding-md)" : "px-(--padding-md)";
|
||||
const showVisibleLabel = !hideLabel;
|
||||
|
||||
const inputField = (
|
||||
<div
|
||||
@ -103,6 +106,7 @@ export default function TextInput({
|
||||
)}
|
||||
<input
|
||||
id={inputId}
|
||||
aria-label={hideLabel ? label : undefined}
|
||||
className={clsx(
|
||||
"flex-1 min-w-0 h-full bg-transparent border-none outline-none",
|
||||
"text-base-ink-max placeholder:text-base-ink-placeholder",
|
||||
@ -114,13 +118,13 @@ export default function TextInput({
|
||||
</div>
|
||||
);
|
||||
|
||||
if (!label && !message) {
|
||||
if (!showVisibleLabel && !message) {
|
||||
return inputField;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-(--spacing-sm)">
|
||||
{label && (
|
||||
{showVisibleLabel && (
|
||||
<label htmlFor={inputId} className="body-bold-md text-base-ink-strong">
|
||||
{label}
|
||||
</label>
|
||||
|
||||
@ -49,9 +49,9 @@ export default function ComponentLibrary() {
|
||||
<section className="mt-lg">
|
||||
<h2 className="mb-md">Text Input Sizes</h2>
|
||||
<div className="flex flex-wrap items-center gap-md">
|
||||
<TextInput size="sm" placeholder="Small" />
|
||||
<TextInput size="md" placeholder="Medium" />
|
||||
<TextInput size="lg" placeholder="Large" />
|
||||
<TextInput size="sm" placeholder="Small" label="Small input" hideLabel />
|
||||
<TextInput size="md" placeholder="Medium" label="Medium input" hideLabel />
|
||||
<TextInput size="lg" placeholder="Large" label="Large input" hideLabel />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -62,16 +62,22 @@ export default function ComponentLibrary() {
|
||||
size="sm"
|
||||
placeholder="Small with icon"
|
||||
Icon={SearchIcon}
|
||||
label="Small search"
|
||||
hideLabel
|
||||
/>
|
||||
<TextInput
|
||||
size="md"
|
||||
placeholder="Medium with icon"
|
||||
Icon={SearchIcon}
|
||||
label="Medium search"
|
||||
hideLabel
|
||||
/>
|
||||
<TextInput
|
||||
size="lg"
|
||||
placeholder="Large with icon"
|
||||
Icon={SearchIcon}
|
||||
label="Large search"
|
||||
hideLabel
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
@ -79,24 +85,24 @@ export default function ComponentLibrary() {
|
||||
<section className="mt-lg">
|
||||
<h2 className="mb-md">Text Input States</h2>
|
||||
<div className="flex flex-wrap items-center gap-md">
|
||||
<TextInput placeholder="Default" />
|
||||
<TextInput placeholder="Error state" error />
|
||||
<TextInput placeholder="Default" label="Default state" hideLabel />
|
||||
<TextInput placeholder="Error state" error label="Error state" hideLabel />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mt-lg">
|
||||
<h2 className="mb-md">Text Input With/Without Placeholder</h2>
|
||||
<div className="flex flex-wrap items-center gap-md">
|
||||
<TextInput placeholder="Placeholder" />
|
||||
<TextInput />
|
||||
<TextInput placeholder="Placeholder" label="With placeholder" hideLabel />
|
||||
<TextInput label="Without placeholder" hideLabel />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mt-lg">
|
||||
<h2 className="mb-md">Text Input Width Options</h2>
|
||||
<div className="flex flex-col gap-md">
|
||||
<TextInput placeholder="Full width" fullWidth />
|
||||
<TextInput placeholder="Custom width" customWidth="300px" />
|
||||
<TextInput placeholder="Full width" fullWidth label="Full width input" hideLabel />
|
||||
<TextInput placeholder="Custom width" customWidth="300px" label="Custom width input" hideLabel />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user
Without having seen an example of a full form with validation it's hard to tell if this is the path forward. We can probably leave it for now.
I am wondering about using built-in form validation and the
:validand related pseudo-selectors and how it works with accessibility without it.I’d keep the error prop for now. Native validation works for some cases but gets awkward once you have server errors or custom validation. An explicit error state keeps the component predictable.