Input Tag

Input Tag คือ view ที่ใช้รับค่าชุดข้อมูลของ tag

Source Code

ReactJs Styled Components
Copy
import { useEffect, useRef, useState } from "react";
import styled, { css } from "styled-components";
import IconPlus from "../element/icon/IconPlus";

export default function InputTag({
  value,
  width = "100%",
  onChange,
  placeHolder,
  design = "outline",
  className,
  style,
  borderWidth = "1px",
  borderColor = "var(--border)",
  borderRadius = "8px",
  backgroundColor = "var(--background-solid)",
  fontSize = "16px",
  label,
  padding = "12px 12px 8px",
  margin,
}) {
  const [tags, setTags] = useState([]);

  const inputRef = useRef();

  useEffect(() => {
    if (value && value.length >= 0) {
      setTags([...value]);
    }
  }, [value]);

  const removeTag = (i) => {
    const newTags = [...tags];
    newTags.splice(i, 1);
    updateTags(newTags);
  };

  const inputKeyDown = (e) => {
    const val = e.target.value;
    if (e.keyCode == 32 || (e.keyCode == 13 && val)) {
      if (tags.find((tag) => tag.toLowerCase() === val.toLowerCase())) {
        return;
      }
      if (val) {
        const tmpTrim = val?.trim();
        updateTags([...tags, tmpTrim]);
        inputRef.current.value = null;
      }
    }
  };

  const onBlurChange = (e) => {
    const val = e.target.value;
    if (val && tags.length == 0) {
      setTags([val]);
      inputRef.current.value = null;
      if (onChange) {
        onChange([val]);
      }
    } else if (val && tags.length > 0) {
      const dubValue = tags.filter(
        (item, index) => tags.indexOf(item) !== index
      );
      if (!dubValue) {
        setTags([...tags, val]);
        if (onChange) {
          onChange([...tags, val]);
        }
      }
      inputRef.current.value = null;
    }
  };

  const updateTags = (tagValue) => {
    if (onChange) {
      onChange(tagValue);
    }
    setTags(tagValue);
  };

  return (
    <Styled
      className={className}
      style={style}
      $width={width}
      $design={design}
      $borderWidth={borderWidth}
      $borderColor={borderColor}
      $borderRadius={borderRadius}
      $backgroundColor={backgroundColor}
      $fontSize={fontSize}
      $padding={padding}
      $margin={margin}
    >
      {label && <small>{label}</small>}
      <ul className={"tag-list"}>
        {tags.map((tag, i) => (
          <li key={"tag-" + i} className="li li-tag">
            <span className="txt">{tag}</span>
            <button
              type="button"
              className="remove-button"
              onClick={() => {
                removeTag(i);
              }}
            >
              <IconPlus color="#fff" width="10px" />
            </button>
          </li>
        ))}

        <li className={"li li-input"}>
          <input
            ref={inputRef}
            placeholder={placeHolder || "Type Here"}
            type="text"
            onKeyDown={inputKeyDown}
            onBlur={onBlurChange}
          />
        </li>
      </ul>
    </Styled>
  );
}
const Styled = styled.div`
  ${({ $design }) => designStyles($design)};
  margin: ${({ $margin }) => $margin};
  small {
    margin-bottom: 5px;
    font-weight: bold;
    display: block;
  }
  .tag-list {
    display: inline-flex;
    flex-wrap: wrap;
    margin: 0;
    width: ${({ $width }) => $width};
    border-radius: ${({ $borderRadius }) => $borderRadius};
    display: flex;
    flex-wrap: wrap;
    padding: ${({ $padding }) => $padding};
    margin-bottom: 10px;
    .place_holder {
      position: absolute;
      font-size: ${({ $fontSize }) => $fontSize};
      color: #888;
    }
    .li {
      background-color: var(--primary);
      align-items: center;
      border-radius: 50px;
      color: #fff;
      display: flex;
      font-weight: 300;
      font-size: ${({ $fontSize }) => $fontSize};
      list-style: none;
      margin-bottom: 5px;
      margin-right: 5px;
      margin-left: 5px;
      padding: 5px 10px;
    }

    .remove-button {
      align-items: center;
      appearance: none;
      background: #333333;
      border: none;
      border-radius: 50%;
      color: white;
      cursor: pointer;
      display: inline-flex;
      font-size: ${({ $fontSize }) => $fontSize};
      height: 15px;
      justify-content: center;
      line-height: 0;
      margin-left: 8px;
      padding: 0;
      transform: rotate(45deg);
      width: 15px;
      line-height: 15px;
      text-align: center;
    }

    .li-input {
      background: none;
      flex-grow: 1;
      padding: 0;
      font-size: ${({ $fontSize }) => $fontSize};
      display: flex;
    }
    .li-input input {
      font-size: ${({ $fontSize }) => $fontSize};
    }
    input:focus,
    select:focus,
    textarea:focus,
    button:focus {
      outline: none;
    }
    .txt {
      padding-left: 5px;
    }
    .li-input input {
      background-color: transparent;
      border: none;
    }
  }
`;

const designStyles = (design) =>
  ({
    solid: css`
      .tag-list {
        color: var(--txt-normal);
        background-color: ${({ $backgroundColor }) => $backgroundColor};
        border-style: none;
      }
    `,
    none: css`
      .tag-list {
        color: var(--txt-normal);
        background-color: transparent;
        border-style: none;
      }
    `,
    outline: css`
      .tag-list {
        color: var(--txt-normal);
        background-color: transparent;
        border-style: solid;
        border-width: ${({ $borderWidth }) => $borderWidth};
        border-color: ${({ $borderColor }) => $borderColor};
      }
    `,
  }[design]);

Usage

ReactJs Styled Components
Copy
import InputTag from "../../example/InputTag";

export default function TestView() {
  return (
    <div className="test-view">
      <InputTag
        design="solid"
        width="600px"
        onChange={(e) => console.log(JSON.stringify(e))}
      />
    </div>
  );
}

Properties

Property

Description

Type

Default

className

ใช้กำหนดลักษณะเฉพาะของ view

string

style

inline style ของ view

CSSProperties

value

ค่าเริ่มต้นชุดข้อมูลของ view

array

width

ความกว้างภายในเนื้อหาของ view

string

"100%"

onChange

ฟังก์ชันจะทำงานเมื่อมีการเปลี่ยนค่า

function

placeHolder

ข้อความตัวอย่าง

string

design

รูปแบบดีไซน์ พื้นฐานของ view เช่น solid (มีสีพื้นหลัง), outline (มีเส้นขอบ) และ none (ไม่มีสีพื้นหลังและเส้นขอบ)

string

"outline"

borderWidth

ความกว้างเส้นขอบนอกสุดของ view

string

"1px"

borderColor

สีของเส้นขอบนอกสุดของ view

string

"var(--border)"

borderRadius

ความโค้งมนของ view

string

"8px"

backgroundColor

สีพื้นหลังของ view

string

"var(--background-solid)"

fontSize

ขนาดตัวอักษรของ view

string

"16px"

label

คำอธิบายของ view

string

padding

พื้นที่ว่างระหว่างเส้นขอบของ view และ เนื้อหาของ view

string

"12px 12px 8px"

margin

พื้นที่ว่างระหว่างขอบนอกสุดของ view และ view อื่น

string

Requirements

styled-components

ยักซ่า (Yakxar)
สร้างสรรค์และแบ่งปันสื่อดิจิทัลง่ายๆ ที่นี่
© 2025 ยักซ่า (Yakxar)