mirror of
https://github.com/detleph/components.git
synced 2026-09-04 00:26:01 +02:00
Add Input component
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"framer-motion": "^7.5.1",
|
"framer-motion": "^7.5.1",
|
||||||
|
"lodash.uniqueid": "^4.0.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-router-dom": "^6.4.1",
|
"react-router-dom": "^6.4.1",
|
||||||
@@ -27,6 +28,7 @@
|
|||||||
"@storybook/builder-vite": "^0.2.3",
|
"@storybook/builder-vite": "^0.2.3",
|
||||||
"@storybook/react": "^6.5.12",
|
"@storybook/react": "^6.5.12",
|
||||||
"@storybook/testing-library": "^0.0.13",
|
"@storybook/testing-library": "^0.0.13",
|
||||||
|
"@types/lodash.uniqueid": "^4.0.7",
|
||||||
"@types/react": "^18.0.17",
|
"@types/react": "^18.0.17",
|
||||||
"@types/react-dom": "^18.0.6",
|
"@types/react-dom": "^18.0.6",
|
||||||
"@vitejs/plugin-react": "^2.1.0",
|
"@vitejs/plugin-react": "^2.1.0",
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<HTMLInputElement>["onChange"];
|
||||||
|
placeholder?: string;
|
||||||
|
label?: string;
|
||||||
|
icon?: typeof ReactComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Input: React.FC<InputProps> = ({ value, onChange, placeholder, label, icon: Icon }) => {
|
||||||
|
const [id] = useState(uniqueId());
|
||||||
|
const input = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.inputContainer} onClick={() => input.current?.focus()}>
|
||||||
|
{Icon && (
|
||||||
|
<span className={styles.iconContainer}>
|
||||||
|
<Icon />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className={styles.innerInput}>
|
||||||
|
<input type="text" id={id} className={styles.input} placeholder={label ? " " : placeholder} ref={input} />
|
||||||
|
<label htmlFor={id} className={styles.label}>
|
||||||
|
{label}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Input;
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import Input from "./Input";
|
||||||
|
|
||||||
|
export default Input;
|
||||||
@@ -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<typeof Input>;
|
||||||
|
|
||||||
|
const Template: ComponentStory<typeof Input> = (args) => <Input {...args} />;
|
||||||
|
|
||||||
|
export const DefaultInput = Template.bind({});
|
||||||
|
|
||||||
|
DefaultInput.args = {
|
||||||
|
value: "test",
|
||||||
|
icon: Icon,
|
||||||
|
label: "test",
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user