first commit
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
"use client";
|
||||
import classNames from "classnames";
|
||||
import { forwardRef } from "react";
|
||||
import style from "./textbox.module.css";
|
||||
|
||||
export type TextboxWidth = "80%" | "100%" | "50%" | "custom";
|
||||
export type TextboxVariant = "solid" | "transparent" | "search";
|
||||
export type TextboxIcon = "none" | "search";
|
||||
export type TextboxType = "text" | "password" | "email" | "number" | "comments";
|
||||
|
||||
interface TextboxProps {
|
||||
name?: string;
|
||||
type: TextboxType;
|
||||
value: string;
|
||||
placeholder?: string;
|
||||
width?: TextboxWidth;
|
||||
variant?: TextboxVariant;
|
||||
icon?: TextboxIcon;
|
||||
onChange?: (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
|
||||
onKeyUp?: (e: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
|
||||
onClick?: (e: React.MouseEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
|
||||
style?: React.CSSProperties;
|
||||
limitSize?: number | undefined;
|
||||
}
|
||||
|
||||
const Textbox = forwardRef<HTMLInputElement | HTMLTextAreaElement, TextboxProps>((props, ref) => {
|
||||
const {
|
||||
width = "80%",
|
||||
variant = "solid",
|
||||
icon = "none",
|
||||
placeholder,
|
||||
type = "text",
|
||||
limitSize = undefined,
|
||||
} = props;
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
const getWidth = (base: any) => {
|
||||
if (width === "100%") {
|
||||
return classNames(base, style.textboxWidth100);
|
||||
} else if (width === "80%") {
|
||||
return classNames(base, style.textboxWidth80);
|
||||
} else if (width === "50%") {
|
||||
return classNames(base, style.textboxWidth50);
|
||||
}
|
||||
return classNames(base);
|
||||
};
|
||||
|
||||
const getClassNames = () => {
|
||||
const classList: classNames.ArgumentArray = [];
|
||||
|
||||
classList.push(style.textbox);
|
||||
|
||||
if (variant === "transparent") {
|
||||
classList.push(style.textboxTransparent);
|
||||
} else if (variant === "solid") {
|
||||
classList.push(style.textboxSolid);
|
||||
} else if (variant === "search") {
|
||||
classList.push(style.textboxSearch);
|
||||
}
|
||||
|
||||
if (width === "100%") {
|
||||
classList.push(style.textboxWidth100);
|
||||
} else if (width === "80%") {
|
||||
classList.push(style.textboxWidth80);
|
||||
} else if (width === "50%") {
|
||||
classList.push(style.textboxWidth50);
|
||||
}
|
||||
|
||||
if (icon === "search") {
|
||||
classList.push(style.textboxIconSearch);
|
||||
} else if (icon === "none") {
|
||||
if (variant === "transparent") {
|
||||
classList.push(style.textboxIconNoneTransparent);
|
||||
} else {
|
||||
classList.push(style.textboxIconNoneSolid);
|
||||
}
|
||||
}
|
||||
|
||||
return classNames(classList);
|
||||
};
|
||||
|
||||
const calcRemaining = () => {
|
||||
if (limitSize) {
|
||||
return limitSize - props.value.length;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{variant !== "search" && placeholder && (
|
||||
<div className={getWidth(style.textboxLabelContainer)}>
|
||||
<div className={style.textboxLabel}>{placeholder}</div>
|
||||
{limitSize && <span> [{calcRemaining()}]</span>}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{type === "comments" ? (
|
||||
<textarea
|
||||
className={getClassNames()}
|
||||
id={props.name}
|
||||
onChange={props.onChange}
|
||||
onKeyUp={props.onKeyUp}
|
||||
onClick={props.onClick}
|
||||
value={props.value}
|
||||
style={props.style}
|
||||
ref={ref as React.Ref<HTMLTextAreaElement>}
|
||||
{...(limitSize && { maxLength: limitSize })}
|
||||
/>
|
||||
) : (
|
||||
<input
|
||||
className={getClassNames()}
|
||||
placeholder={variant === "search" ? placeholder : ""}
|
||||
type={type}
|
||||
id={props.name}
|
||||
value={props.value}
|
||||
onChange={props.onChange}
|
||||
onKeyUp={props.onKeyUp}
|
||||
onClick={props.onClick}
|
||||
style={props.style}
|
||||
ref={ref as React.Ref<HTMLInputElement>}
|
||||
{...(limitSize && { maxLength: limitSize })}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
Textbox.displayName = "Textbox";
|
||||
|
||||
export default Textbox;
|
||||
@@ -0,0 +1,80 @@
|
||||
.textboxLabelContainer {
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.textboxLabelContainer span {
|
||||
color: var(--gray-light);
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.textboxLabel {
|
||||
color: var(--black);
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
padding-top: 10px;
|
||||
padding-left: 5px;
|
||||
line-height: 40px;
|
||||
margin-right: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.textbox {
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
height: 42px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--black);
|
||||
}
|
||||
|
||||
.textboxTransparent {
|
||||
border: inset 1.5px #2b0b5f;
|
||||
color: var(--white-darkest);
|
||||
background-color: transparent;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.textboxSolid {
|
||||
border: solid 1px var(--gray-dark);
|
||||
background: var(--white-dark);
|
||||
background: linear-gradient(180deg, var(--white-dark) 0%, var(--white) 100%);
|
||||
}
|
||||
|
||||
.textboxSearch {
|
||||
border: solid 1px var(--wine-dark);
|
||||
background: var(--wine);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.textboxIconNoneTransparent {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.textboxIconNoneSolid {
|
||||
background: var(--white-dark);
|
||||
background: linear-gradient(180deg, var(--white-dark) 0%, var(--white) 100%);
|
||||
}
|
||||
|
||||
.textboxIconSearch {
|
||||
background-image: url("/icon-search.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: 6px center;
|
||||
background-size: 28px 28px;
|
||||
padding-left: 42px;
|
||||
}
|
||||
|
||||
.textboxWidth50 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.textboxWidth80 {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.textboxWidth100 {
|
||||
width: 100%;
|
||||
}
|
||||
Reference in New Issue
Block a user