Skip to content

Commit

Permalink
Add DomainInputField
Browse files Browse the repository at this point in the history
  • Loading branch information
raix committed Jul 21, 2024
1 parent 6ed5fa5 commit d2c9ac3
Showing 1 changed file with 63 additions and 0 deletions.
63 changes: 63 additions & 0 deletions ui/components/DomainInputField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { useContext } from "react";
import { useFocusRing } from "react-aria";
import {
TextField as AriaTextField,
type TextFieldProps as AriaTextFieldProps,
type ValidationResult
} from "react-aria-components";
import { FormValidationContext } from "react-aria-components";
import { tv } from "tailwind-variants";
import { Description } from "./Description";
import { fieldBorderStyles } from "./Field";
import { FieldError } from "./FieldError";
import { Group } from "./Group";
import { Input } from "./Input";
import { Label } from "./Label";
import { focusRing } from "./focusRing";
import { composeTailwindRenderProps } from "./utils";

const inputStyles = tv({
extend: focusRing,
base: "border rounded-md overflow-hidden border border-red-500",
variants: {
isFocused: fieldBorderStyles.variants.isFocusWithin,
...fieldBorderStyles.variants
}
});

export interface DomainInputFieldProps
extends AriaTextFieldProps,
Partial<Pick<HTMLInputElement, "autocomplete" | "placeholder">> {
domain: string;
label?: string;
description?: string;
errorMessage?: string | ((validation: ValidationResult) => string);
}

export function DomainInputField({
name,
domain,
label,
description,
errorMessage,
placeholder,
autocomplete,
children,
className,
...props
}: Readonly<DomainInputFieldProps>) {
const errors = useContext(FormValidationContext);
const isInvalid = Boolean(name != null && name in errors ? errors?.[name] : undefined);
const { focusProps, isFocusVisible } = useFocusRing();
return (
<AriaTextField {...props} name={name} className={composeTailwindRenderProps(className, "flex flex-col gap-1")}>
{label && <Label>{label}</Label>}
<Group className={inputStyles({ isInvalid, isFocusVisible })}>
<Input {...focusProps} isEmbedded placeholder={placeholder} autoComplete={autocomplete} />
<div className="flex min-w-fit max-w-fit shrink-0 items-center p-2 text-muted-foreground text-xs">{domain}</div>
</Group>
{description && <Description>{description}</Description>}
<FieldError>{errorMessage}</FieldError>
</AriaTextField>
);
}

0 comments on commit d2c9ac3

Please sign in to comment.