Skip to content

Commit

Permalink
⚡️: 공용 드롭다운 컴포넌트로 분리
Browse files Browse the repository at this point in the history
  • Loading branch information
nrkcode committed Jan 22, 2025
1 parent 9a8971e commit 9880931
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 75 deletions.
72 changes: 72 additions & 0 deletions src/common/components/dropDown/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { ChevronDown } from "lucide-react"
import { useMemo, useState } from "react"

import TbButton from "@/common/components/button/TbButton"
import { cn } from "@/util/utils"

type DropDownPT = {
dropDownText: string
selectList: { id: string; name: string }[]
onClickFunc: (id: string) => void
contentClassName?: (item: { id: string; name: string }) => string
}

export const TbDropDown = ({
dropDownText,
selectList,
onClickFunc,
contentClassName,
}: DropDownPT) => {
const [dropdownOpen, setDropdownOpen] = useState(false)

const itemsWithClassNames = useMemo(
() =>
selectList.map((item) => ({
...item,
className: contentClassName ? contentClassName(item) : "",
})),
[selectList, contentClassName], // selectList나 contentClassName 변경 시 재계산
)

return (
<div className="relative w-fit">
<TbButton
color="tableWhite"
size="table"
onClick={() => setDropdownOpen((e) => !e)}
className="flex w-28 justify-between gap-1 md:w-32"
>
<div className="flex w-full justify-center text-xs md:text-sm">
{dropDownText}
</div>
<ChevronDown
className={`transform ${dropdownOpen ? "rotate-180" : "rotate-0"}`}
size={16}
/>
</TbButton>
{dropdownOpen && (
<div className="absolute z-10 mt-2 flex w-full flex-col gap-1 overflow-hidden rounded-2xl border border-gray-300 bg-white text-black transition duration-200 ease-in focus:ring-2 focus:ring-gray-200">
{itemsWithClassNames.map(
(item: { id: string; className?: string; name: string }) => (
<button
key={item.id}
onClick={() => {
setDropdownOpen(false)
onClickFunc(item.id)
console.log(item, contentClassName?.(item))
}}
color="clear"
className={cn(
item.className,
"w-full rounded-none px-4 py-2 text-center text-xs text-gray-700 hover:bg-gray-200 hover:text-black md:text-sm",
)}
>
{item.name}
</button>
),
)}
</div>
)}
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
FilterColumnList,
type FilterPickerPT,
} from "@/features/realtime/components/types/table/types"
import { TbDropDown } from "@/common/components/dropDown"

export function FileterPicker({
activeFilter,
Expand All @@ -33,43 +34,13 @@ export function FileterPicker({
return (
<div className="absolute z-10 mt-2 flex w-fit flex-col gap-1 rounded-2xl bg-white p-5 text-slate-700 shadow-md transition duration-200 ease-in">
<div className="flex items-center gap-2">
<div className="relative w-fit">
<TbButton
color="tableWhite"
size="table"
onClick={() => setDropdownOpen((e) => !e)}
className="flex w-36 justify-between gap-1 border border-gray-300 text-slate-700"
>
<div className="flex w-full justify-center text-xs md:text-sm">
{text ? text.name : "필터 선택"}
</div>
<ChevronDown
className={`transform ${dropdownOpen ? "rotate-180" : "rotate-0"}`}
size={16}
/>
</TbButton>
{dropdownOpen && (
<div className="absolute z-10 mt-2 flex w-full flex-col gap-1 overflow-hidden rounded-2xl border border-gray-300 bg-white text-slate-700 transition duration-200 ease-in focus:ring-2 focus:ring-gray-200">
{columnList.map(
({ id, name }) =>
!activeFilter[id] && (
<TbButton
key={id}
onClick={() => {
setSelected(id)
setDropdownOpen(false)
}}
color="transparent"
className="w-full rounded-none px-4 py-2 text-center text-xs text-gray-700 hover:bg-gray-100 md:text-sm"
>
{name}
</TbButton>
),
)}
</div>
)}
</div>

<TbDropDown
dropDownText={text ? text.name : "필터 선택"}
selectList={columnList}
onClickFunc={(id) => {
setSelected(id)
}}
/>
<TbButton
color="tableGray"
size="table"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
SortColumnList,
type SortPickerPT,
} from "@/features/realtime/components/types/table/types"
import { TbDropDown } from "@/common/components/dropDown"

export function SortPicker({
sortingState,
Expand All @@ -18,8 +19,6 @@ export function SortPicker({
toggleState,
updateState,
}: SortPickerPT) {
const [dropdownOpen, setDropdownOpen] = useState(false)

const handleSortState = (column: string) => {
setSortingState((prev: Record<string, boolean>) => ({
...prev,
Expand All @@ -32,42 +31,17 @@ export function SortPicker({
return (
<div className="absolute z-10 mt-2 flex w-fit flex-col gap-1 rounded-2xl bg-white p-5 text-slate-700 shadow-md transition duration-200 ease-in">
<div className="flex items-center gap-2">
<div className="relative w-fit">
<TbButton
color="tableWhite"
size="table"
onClick={() => setDropdownOpen((e) => !e)}
className="flex w-32 justify-between gap-1 md:w-40"
>
<div className="flex w-full justify-center text-xs md:text-sm">
{text ? text.name : "정렬 기준"}
</div>
<ChevronDown
className={`transform ${dropdownOpen ? "rotate-180" : "rotate-0"}`}
size={16}
/>
</TbButton>
{dropdownOpen && (
<div className="absolute z-10 mt-2 flex w-full flex-col gap-1 overflow-hidden rounded-2xl border border-gray-300 bg-white text-black transition duration-200 ease-in focus:ring-2 focus:ring-gray-200">
{SortColumnList.map(({ id, name }) => (
<TbButton
key={id}
onClick={() => {
setCurrentSortColumn(id)
setDropdownOpen(false)
handleSortState(currentSortColumn)
}}
color="transparent"
className={`w-full rounded-none px-4 py-2 text-center text-xs text-gray-700 hover:bg-gray-100 md:text-sm ${
currentSortColumn === id ? "bg-gray-100 font-bold" : ""
}`}
>
{name}
</TbButton>
))}
</div>
)}
</div>
<TbDropDown
dropDownText={text ? text.name : "정렬 기준"}
selectList={SortColumnList}
onClickFunc={(id) => {
setCurrentSortColumn(id)
handleSortState(currentSortColumn)
}}
contentClassName={({ id }) =>
currentSortColumn === id ? "bg-gray-100 font-bold" : ""
}
/>
<TbButton
color="tableWhite"
size="table"
Expand Down

0 comments on commit 9880931

Please sign in to comment.