ํฐ์คํ ๋ฆฌ ๋ทฐ
์นดํ
๊ณ ๋ฆฌ ์์
๐ฝ React + Tailwind๋ก ๋๋กญ๋ค์ด ๋ง๋ค๊ธฐ (Dropdown ์ปดํฌ๋ํธ)
B_log 2025. 5. 18. 14:51๋ฐ์ํ
๐ฝ 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
- NumberofDiscIntersections#Codility#Sort#Python
- ๋ ์ง ๊ณ์ฐ#BOJ#์์ ํ์#Python
- ํ ํ๋ก์ ํธ#๋ฐฑ์ค์๊ณ ๋ฆฌ์ฆ#Python
- django
- django#slicing
- filter#isalnum#lower
- ์ํธ์ฝ๋#dp#BOJ#Python
- ํ ๋งํ #๋ฐฑ์ค์๊ณ ๋ฆฌ์ฆ#Python
- ๋๋ฌด์๋ฅด๊ธฐ#BOJ#์ด๋ถํ์#Python
- ๋ณ๋ ๋์ดํธ#BOJ#ํ์๋ฒ#Python
- PassingCars#Codility#Python
- Swift#Tuples#Range
- ์์ด์ฌ์ดํด#BOJ#Python
- ๋ฏธ๋ก ํ์#๋ฐฑ์ค์๊ณ ๋ฆฌ์ฆ#Python
- ๋ฐฑ์ค ์๊ณ ๋ฆฌ์ฆ#BackTracking
- ์ข ์ด์๋ฅด๊ธฐ#๋ถํ ์ ๋ณต#BOJ#Python
- ๊ณต์ ๊ธฐ ์ค์น#BOJ#์ด๋ถํ์#Python
- Brackets#Stacks and Queues#Codility#Python
- Triangle#Sorting#Codility#Python
- ๋ฆฌ๋ชจ์ปจ#์์ ํ์#BOJ#Python
- ๋ฐฐ์ดํฉ์น๊ธฐ#๋ถํ ์ ๋ณต#BOJ#Python
- API#lazy#
- ํฐํ๋น์น#๋ฆฌ์ฝ#xbox#controller
- Distinct#Codility#Python
- N์ผ๋ก ํํ#DP#Programmers#Python
- ๋์ ์๋ฅด๊ธฐ#์ด๋ถํ์#BOJ#Python
- ํ์ด์ฌ์๊ณ ๋ฆฌ์ฆ์ธํฐ๋ทฐ#4์ฅ
- ๋ฐ๋ณต์์ด#๋ฐฑ์ค์๊ณ ๋ฆฌ์ฆ#Python
- ์ฟผ๋ํธ๋ฆฌ#BOJ#๋ถํ ์ ๋ณต#Python
- ์ฌ์๊ฐ์#๋ฐฑ์ค์๊ณ ๋ฆฌ์ฆ#Python
์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
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 |
๊ธ ๋ณด๊ดํจ