Skip to content
This repository has been archived by the owner on Jul 2, 2024. It is now read-only.

Commit

Permalink
Abstract out validation logic into custom component
Browse files Browse the repository at this point in the history
  • Loading branch information
khelif96 committed Oct 31, 2023
1 parent 2d8f306 commit c5559ca
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { CustomStoryObj, CustomMeta } from "test_utils/types";
import TextInputWithGlyph from ".";

export default {
title: "Components/TextInput/TextInputWithGlyph",
component: TextInputWithGlyph,
} satisfies CustomMeta<typeof TextInputWithGlyph>;

Expand Down
1 change: 1 addition & 0 deletions src/components/TextInputWithGlyph/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@ const IconWrapper = styled.div`
justify-content: center;
`;

export type { TextInputWithGlyphProps };
export default TextInputWithGlyph;
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { CustomMeta, CustomStoryObj } from "test_utils/types";
import TextInputWithValidation from ".";

export default {
title: "Components/TextInput/TextInputWithValidation",
component: TextInputWithValidation,
} satisfies CustomMeta<typeof TextInputWithValidation>;

export const Default: CustomStoryObj<typeof TextInputWithValidation> = {
render: (args) => <TextInputWithValidation {...args} />,
argTypes: {},
args: {
validator: (v) => v !== "bad",
label: "Some search field",
},
};
72 changes: 72 additions & 0 deletions src/components/TextInputWithValidation/index.tsx
Original file line number Diff line number Diff line change
@@ -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<TextInputWithValidationProps> =
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 (
<TextInputWithGlyph
value={input}
type="search"
onChange={(e) => handleOnChange(e.target.value)}
placeholder={placeholder}
onKeyPress={(e: React.KeyboardEvent<HTMLInputElement>) =>
e.key === "Enter" && handleOnSubmit()
}
ref={ref}
icon={
isValid ? (
<IconButton
onClick={handleOnSubmit}
aria-label="Select plus button"
>
<Icon glyph="Plus" />
</IconButton>
) : (
<IconTooltip glyph="Warning" fill={yellow.base}>
{validatorErrorMessage}
</IconTooltip>
)
}
{...rest}
/>
);
});

TextInputWithValidation.displayName = "TextInputWithValidation";
export default TextInputWithValidation;

0 comments on commit c5559ca

Please sign in to comment.