diff --git a/src/components/TextInputWithGlyph/TextInputWithGlyph.stories.tsx b/src/components/TextInputWithGlyph/TextInputWithGlyph.stories.tsx index 21753e3f51..d48a190661 100644 --- a/src/components/TextInputWithGlyph/TextInputWithGlyph.stories.tsx +++ b/src/components/TextInputWithGlyph/TextInputWithGlyph.stories.tsx @@ -5,6 +5,7 @@ import { CustomStoryObj, CustomMeta } from "test_utils/types"; import TextInputWithGlyph from "."; export default { + title: "Components/TextInput/TextInputWithGlyph", component: TextInputWithGlyph, } satisfies CustomMeta; diff --git a/src/components/TextInputWithGlyph/index.tsx b/src/components/TextInputWithGlyph/index.tsx index c9bfa9f212..d301274e33 100644 --- a/src/components/TextInputWithGlyph/index.tsx +++ b/src/components/TextInputWithGlyph/index.tsx @@ -38,4 +38,5 @@ const IconWrapper = styled.div` justify-content: center; `; +export type { TextInputWithGlyphProps }; export default TextInputWithGlyph; diff --git a/src/components/TextInputWithValidation/TextInputWithValidation.stories.tsx b/src/components/TextInputWithValidation/TextInputWithValidation.stories.tsx new file mode 100644 index 0000000000..2b1d61246c --- /dev/null +++ b/src/components/TextInputWithValidation/TextInputWithValidation.stories.tsx @@ -0,0 +1,16 @@ +import { CustomMeta, CustomStoryObj } from "test_utils/types"; +import TextInputWithValidation from "."; + +export default { + title: "Components/TextInput/TextInputWithValidation", + component: TextInputWithValidation, +} satisfies CustomMeta; + +export const Default: CustomStoryObj = { + render: (args) => , + argTypes: {}, + args: { + validator: (v) => v !== "bad", + label: "Some search field", + }, +}; diff --git a/src/components/TextInputWithValidation/index.tsx b/src/components/TextInputWithValidation/index.tsx new file mode 100644 index 0000000000..08f0d91f12 --- /dev/null +++ b/src/components/TextInputWithValidation/index.tsx @@ -0,0 +1,72 @@ +import { useState, forwardRef } from "react"; +import IconButton from "@leafygreen-ui/icon-button"; +import { palette } from "@leafygreen-ui/palette"; +import Icon from "components/Icon"; +import IconTooltip from "components/IconTooltip"; +import TextInputWithGlyph from "components/TextInputWithGlyph"; +import type { TextInputWithGlyphProps } from "components/TextInputWithGlyph"; + +const { yellow } = palette; +type TextInputWithValidationProps = { + onSubmit?: (value: string) => void; + validator?: (value: string) => boolean; + validatorErrorMessage?: string; + label?: React.ReactNode; + placeholder?: string; +} & TextInputWithGlyphProps; + +const TextInputWithValidation: React.FC = + forwardRef((props, ref) => { + const { + onSubmit = () => {}, + placeholder = "", + validator = () => true, + validatorErrorMessage = "", + ...rest + } = props; + + const [input, setInput] = useState(""); + const isValid = validator(input); + + const handleOnSubmit = () => { + if (isValid) { + onSubmit(input); + setInput(""); + } + }; + + const handleOnChange = (value: string) => { + setInput(value); + }; + + return ( + handleOnChange(e.target.value)} + placeholder={placeholder} + onKeyPress={(e: React.KeyboardEvent) => + e.key === "Enter" && handleOnSubmit() + } + ref={ref} + icon={ + isValid ? ( + + + + ) : ( + + {validatorErrorMessage} + + ) + } + {...rest} + /> + ); + }); + +TextInputWithValidation.displayName = "TextInputWithValidation"; +export default TextInputWithValidation;