본문 바로가기

프론트엔드/Library

[Library] React와 NextUI를 활용한 커스텀 셀렉터 컴포넌트 구현 가이드 (feat. TailwindCSS)

반응형

[Library] React와 NextUI를 활용한 커스텀 셀렉터 컴포넌트 구현 가이드 (feat. TailwindCSS)

사용 기술 스택: `@nextui-org/react`, `React`, `TailwindCSS`

 

1. 프로젝트 설정

먼저, 이 프로젝트에 필요한 라이브러리를 설치합니다.

$ npm install @nextui-org/react

 

 

2. 데모 예시

 

3. 커스텀 셀렉터 컴포넌트 구현

이 컴포넌트는 @nextui-org/react에서 제공하는 Select와 SelectItem 컴포넌트를 사용합니다.

 

"use client";

import { Select, SelectItem } from "@nextui-org/react";
import React, { useState } from "react";

const items = {
  ALL: "모든 타입",
  LEGACY: "Legacy",
  V1: "Version 1",
  V2: "Version 2",
  V3: "Version 3",
};

const selectItems = Object.entries(items).map((v) => ({
  key: v[0],
  label: v[1],
}));

export default function CustomSelector() {
  const [isOpen, setIsOpen] = useState(false);

  const triggerRadius = isOpen ? "rounded-t-md rounded-b-none" : "rounded-md";
  const listItemHeight = "min-h-12";

  return (
    <Select
      isOpen={isOpen}
      onOpenChange={() => setIsOpen((prev) => !prev)}
      variant="bordered"
      defaultSelectedKeys={[selectItems[0].key]}
      classNames={{
        base: ["max-w-32"],
        trigger: [
          "border",
          listItemHeight,
          triggerRadius,
          "data-[open=true]:border-codeit_purple",
          "data-[focus=true]:border-codeit_purple",
          "data-[hover=true]:border-codeit_purple",
        ],
        listbox: "p-0",
        selectorIcon: ["!ease-in-out", "!duration-[250ms]"], // chevron icon
      }}
      selectionMode="single" // 사용자가 드롭다운 목록에서 하나의 옵션만 선택할 수 있음.
      disallowEmptySelection // 항상 최소 하나 이상의 옵션이 선택되어 있도록 강제하는 옵션
      listboxProps={{
        variant: "light",
      }}
      popoverProps={{
        offset: 0, // 팝업의 수평 위치를 조절해서 Select 컴포넌트와 정확히 일치하게 팝업이 나타납니다. 띄어지지 않음.
        classNames: {
          content: [
            "p-0",
            "border",
            "border-default-200",
            "shadow-none",
            "rounded-b-md rounded-t-none",
          ],
        },
      }}
    >
      {selectItems.map(({ key, label }) => (
        <SelectItem
          key={key}
          classNames={{
            base: ["m-0", "text-neutral-400", listItemHeight],
          }}
          showDivider // 각 항목 사이에 구분선을 표시합니다.
          hideSelectedIcon // 선택된 항목 옆에 표시되는 아이콘을 숨깁니다.
        >
          {label}
        </SelectItem>
      ))}
    </Select>
  );
}

 

4.  상태 관리

isOpen 상태를 사용하여 셀렉터의 열림/닫힘 상태를 관리합니다. 이 상태에 따라 셀렉터의 모서리 스타일(triggerRadius)이 변경됩니다.

 

 

5. Select 컴포넌트

Select 컴포넌트는 사용자가 선택할 수 있는 옵션 목록을 제공합니다. 주요 프로퍼티는 다음과 같습니다:

  • isOpen: 셀렉터의 현재 열림 상태를 나타냅니다.
  • onOpenChange: 셀렉터의 열림/닫힘 상태를 토글하는 함수입니다.
  • variant: 셀렉터의 스타일을 지정합니다.
  • defaultSelectedKeys: 기본 선택 항목을 설정합니다.
  • classNames: 각 부분에 대한 커스텀 스타일을 지정합니다.
  • selectionMode: 단일 선택 모드를 설정합니다.
  • disallowEmptySelection: 최소 하나 이상의 항목이 선택되도록 강제합니다.

 

 

6. SelectItem 컴포넌트

SelectItem 컴포넌트는 셀렉터 내의 개별 항목을 나타냅니다. 각 항목은 key와 label을 통해 고유하게 식별됩니다. showDivider와 hideSelectedIcon 프로퍼티를 사용하여 항목 사이에 구분선을 표시하고 선택된 아이콘을 숨깁니다.

반응형