mirror of
https://github.com/detleph/components.git
synced 2026-09-04 08:36:03 +02:00
Add Input component
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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