ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

๋ฐ˜์‘ํ˜•

๐Ÿ”ฝ React + Tailwind๋กœ ๋“œ๋กญ๋‹ค์šด ๋งŒ๋“ค๊ธฐ (Dropdown ์ปดํฌ๋„ŒํŠธ)

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” React์™€ Tailwind CSS๋ฅผ ์‚ฌ์šฉํ•ด
๊ฐ„๋‹จํ•˜๋ฉด์„œ๋„ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ๊ฐ€๋Šฅํ•œ ๋“œ๋กญ๋‹ค์šด(Dropdown) ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค.


โœ… ์™„์„ฑ ๊ธฐ๋Šฅ ์š”์•ฝ

  • ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๋ชฉ๋ก์ด ์•„๋ž˜๋กœ ํŽผ์ณ์ง
  • ํ•ญ๋ชฉ ํด๋ฆญ ์‹œ ํ•ด๋‹น ํ•ญ๋ชฉ ์„ ํƒ ๋ฐ ๋“œ๋กญ๋‹ค์šด ๋‹ซํž˜
  • ์„ ํƒ๋œ ๊ฐ’ ํ‘œ์‹œ
  • ์™ธ๋ถ€ ํด๋ฆญ ์‹œ ์ž๋™ ๋‹ซํž˜
  • Tailwind CSS๋กœ ์‰ฝ๊ฒŒ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ๊ฐ€๋Šฅ

๐Ÿ“ ํŒŒ์ผ ๊ตฌ์กฐ

components/
  โ””โ”€โ”€ Dropdown.jsx
App.jsx

๐Ÿงฉ 1. Dropdown ์ปดํฌ๋„ŒํŠธ (Dropdown.jsx)

import React, { useState, useRef, useEffect } from 'react'

function Dropdown({ options = [], placeholder = '์„ ํƒํ•˜์„ธ์š”', onSelect }) {
  const [isOpen, setIsOpen] = useState(false)
  const [selected, setSelected] = useState(null)
  const dropdownRef = useRef(null)

  const handleSelect = (option) => {
    setSelected(option)
    setIsOpen(false)
    onSelect?.(option)
  }

  // ๋ฐ”๊นฅ ํด๋ฆญ ์‹œ ๋‹ซํž˜
  useEffect(() => {
    function handleClickOutside(e) {
      if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
        setIsOpen(false)
      }
    }
    document.addEventListener('mousedown', handleClickOutside)
    return () => document.removeEventListener('mousedown', handleClickOutside)
  }, [])

  return (
    <div ref={dropdownRef} className="relative w-full">
      <button
        onClick={() => setIsOpen((prev) => !prev)}
        className="w-full px-4 py-3 bg-gray-100 rounded-xl text-left text-sm font-medium text-gray-800 hover:bg-gray-200 transition"
      >
        {selected?.label || placeholder}
      </button>

      {isOpen && (
        <ul className="absolute z-10 mt-2 w-full bg-white shadow-md rounded-xl border border-gray-200">
          {options.map((option) => (
            <li
              key={option.value}
              onClick={() => handleSelect(option)}
              className="px-4 py-2 text-sm hover:bg-gray-100 cursor-pointer rounded-xl"
            >
              {option.label}
            </li>
          ))}
        </ul>
      )}
    </div>
  )
}

export default Dropdown

๐Ÿงช 2. ์‚ฌ์šฉ ์˜ˆ์‹œ (App.jsx)

import { useState } from 'react'
import Dropdown from './components/Dropdown'

function App() {
  const [selectedOption, setSelectedOption] = useState(null)

  const options = [
    { label: 'ํ•œ๊ตญ์–ด', value: 'ko' },
    { label: 'English', value: 'en' },
    { label: 'ๆ—ฅๆœฌ่ชž', value: 'ja' },
  ]

  return (
    <div className="min-h-screen bg-gray-50 flex items-center justify-center p-6">
      <div className="w-full max-w-xs space-y-4">
        <Dropdown
          options={options}
          placeholder="์–ธ์–ด๋ฅผ ์„ ํƒํ•˜์„ธ์š”"
          onSelect={(option) => {
            setSelectedOption(option)
            console.log('์„ ํƒ๋จ:', option)
          }}
        />
        {selectedOption && (
          <p className="text-sm text-gray-600">์„ ํƒํ•œ ์–ธ์–ด: {selectedOption.label}</p>
        )}
      </div>
    </div>
  )
}

export default App

๐ŸŽจ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ํฌ์ธํŠธ

ํ•ญ๋ชฉ ์ ์šฉ ํด๋ž˜์Šค
๋ฒ„ํŠผ ์ƒ‰์ƒ bg-gray-100, hover:bg-gray-200
์„ ํƒ ๋ชฉ๋ก ์Šคํƒ€์ผ hover:bg-gray-100, text-sm, rounded-xl
์œ„์น˜ ์กฐ์ ˆ absolute mt-2 โ†’ ํ•„์š” ์‹œ bottom-full ๋“ฑ

โœ… ๋งˆ๋ฌด๋ฆฌ

Tailwind CSS์™€ React๋งŒ์œผ๋กœ๋„ ๋“œ๋กญ๋‹ค์šด UI๋ฅผ ์ถฉ๋ถ„ํžˆ ์œ ์—ฐํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ธฐ๋ณธ์ ์ธ ์ƒํƒœ ๊ด€๋ฆฌ์™€ DOM ์ด๋ฒคํŠธ๋งŒ ๋‹ค๋ฃจ๋ฉด, ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—†์ด๋„ ์‹ค์šฉ์ ์ธ ๋“œ๋กญ๋‹ค์šด์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์ฃ !


๐Ÿ“Œ ๋‹ค์Œ ๊ธ€ ์˜ˆ๊ณ 

  • โœ… Select ์ปดํฌ๋„ŒํŠธ๋ฅผ form๊ณผ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•
  • โœ… ํ•ญ๋ชฉ์— ์•„์ด์ฝ˜ ์ถ”๊ฐ€ํ•˜๊ธฐ
  • โœ… ๋“œ๋กญ๋‹ค์šด์„ ๋ชจ๋‹ฌ/ํˆดํŒ์œผ๋กœ ํ™•์žฅํ•˜๊ธฐ

ํ•„์š”ํ•˜์‹  ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค๋ฉด ๋Œ“๊ธ€๋กœ ๋‚จ๊ฒจ์ฃผ์„ธ์š” ๐Ÿ˜Š

๋ฐ˜์‘ํ˜•
๋Œ“๊ธ€
๋ฐ˜์‘ํ˜•
๊ณต์ง€์‚ฌํ•ญ
์ตœ๊ทผ์— ์˜ฌ๋ผ์˜จ ๊ธ€
์ตœ๊ทผ์— ๋‹ฌ๋ฆฐ ๋Œ“๊ธ€
Total
Today
Yesterday
๋งํฌ
TAG more
ยซ   2025/07   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
๊ธ€ ๋ณด๊ด€ํ•จ