diff --git a/package.json b/package.json index 100a9d6..f767129 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "framer-motion": "^7.5.1", + "lodash.uniqueid": "^4.0.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.4.1", @@ -27,6 +28,7 @@ "@storybook/builder-vite": "^0.2.3", "@storybook/react": "^6.5.12", "@storybook/testing-library": "^0.0.13", + "@types/lodash.uniqueid": "^4.0.7", "@types/react": "^18.0.17", "@types/react-dom": "^18.0.6", "@vitejs/plugin-react": "^2.1.0", diff --git a/src/components/input/Input.module.scss b/src/components/input/Input.module.scss new file mode 100644 index 0000000..1249506 --- /dev/null +++ b/src/components/input/Input.module.scss @@ -0,0 +1,68 @@ +@import "../../styles/colors.scss"; + +.inputContainer { + background: #f0f0f0; + width: 15rem; + + display: flex; + + font-size: 1rem; + font-family: sans-serif; + + padding: 10px 14px; + + border-radius: 100vh; +} + +.iconContainer { + display: block; + + width: 1.7em; + height: 1.7em; + justify-self: center; + align-self: center; + + display: flex; + justify-content: center; + align-items: center; + + svg { + width: 100%; + height: 100%; + + fill: $unimportant; + } +} + +.innerInput { + padding-left: 16px; + + width: 100%; + position: relative; + display: flex; + justify-content: center; + align-items: center; +} + +.label { + color: $unimportant; + + position: absolute; + left: 16px; + transition: transform 100ms, left 100ms; +} + +.input { + width: 100%; + background: none; + outline: none; + border: none; + + font-size: inherit; + + &:focus ~ .label, + &:not(:placeholder-shown) ~ .label { + left: 100%; + transform: translateX(calc(-100% - 0.5em)) scale(0.8); + } +} diff --git a/src/components/input/Input.tsx b/src/components/input/Input.tsx new file mode 100644 index 0000000..e32909b --- /dev/null +++ b/src/components/input/Input.tsx @@ -0,0 +1,37 @@ +import React, { useRef, useState } from "react"; +import uniqueId from "lodash.uniqueid"; + +import styles from "./Input.module.scss"; +import { ReactComponent } from "../../assets/svgr-custom"; + +interface InputProps { + value: string; + onChange?: React.HTMLAttributes["onChange"]; + placeholder?: string; + label?: string; + icon?: typeof ReactComponent; +} + +const Input: React.FC = ({ value, onChange, placeholder, label, icon: Icon }) => { + const [id] = useState(uniqueId()); + const input = useRef(null); + + return ( +
input.current?.focus()}> + {Icon && ( + + + + )} + +
+ + +
+
+ ); +}; + +export default Input; diff --git a/src/components/input/index.ts b/src/components/input/index.ts new file mode 100644 index 0000000..523987d --- /dev/null +++ b/src/components/input/index.ts @@ -0,0 +1,3 @@ +import Input from "./Input"; + +export default Input; diff --git a/src/stories/Input.stories.tsx b/src/stories/Input.stories.tsx new file mode 100644 index 0000000..02238a0 --- /dev/null +++ b/src/stories/Input.stories.tsx @@ -0,0 +1,19 @@ +import React from "react"; + +import { ComponentStory, ComponentMeta } from "@storybook/react"; +// @ts-ignore +import { ReactComponent as Icon } from "../assets/search.svg"; + +import Input from "../components/input"; + +export default { title: "Input", component: Input } as ComponentMeta; + +const Template: ComponentStory = (args) => ; + +export const DefaultInput = Template.bind({}); + +DefaultInput.args = { + value: "test", + icon: Icon, + label: "test", +};