From 6a10faca68aa80a648f8a8fb3a8088b0dea39265 Mon Sep 17 00:00:00 2001 From: Dakshesh Jain <65905942+dakshesh14@users.noreply.github.com> Date: Thu, 23 Feb 2023 15:36:46 +0530 Subject: [PATCH] feat: made new multi-level select listbox (#326) --- apps/app/components/core/index.ts | 1 + .../components/core/multi-level-select.tsx | 137 ++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 apps/app/components/core/multi-level-select.tsx diff --git a/apps/app/components/core/index.ts b/apps/app/components/core/index.ts index 8146660a1c..01a190d079 100644 --- a/apps/app/components/core/index.ts +++ b/apps/app/components/core/index.ts @@ -8,3 +8,4 @@ export * from "./issues-view-filter"; export * from "./issues-view"; export * from "./link-modal"; export * from "./not-authorized-view"; +export * from "./multi-level-select"; diff --git a/apps/app/components/core/multi-level-select.tsx b/apps/app/components/core/multi-level-select.tsx new file mode 100644 index 0000000000..db74f8bd26 --- /dev/null +++ b/apps/app/components/core/multi-level-select.tsx @@ -0,0 +1,137 @@ +import React, { useState } from "react"; + +import { Listbox, Transition } from "@headlessui/react"; + +import { CheckIcon, ChevronUpDownIcon } from "@heroicons/react/20/solid"; + +type TSelectOption = { + id: string; + label: string; + value: any; + children?: + | (TSelectOption & { + children?: null; + })[] + | null; +}; + +type TMultipleSelectProps = { + options: TSelectOption[]; + selected: TSelectOption | null; + setSelected: (value: any) => void; + label: string; +}; + +export const MultiSelect: React.FC = (props) => { + const { options, selected, setSelected, label } = props; + + const [openChildFor, setOpenChildFor] = useState(null); + + return ( +
+ { + if (value?.children === null) { + setSelected(value); + setOpenChildFor(null); + } else setOpenChildFor(value); + }} + > + {({ open }) => ( +
+ setOpenChildFor(null)} + className="relative w-full cursor-default rounded-lg bg-white py-2 pl-3 pr-10 text-left shadow-md focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 sm:text-sm" + > + {selected?.label ?? label} + + + + + + {options.map((option) => ( + + `relative cursor-default select-none py-2 pl-10 pr-4 ${ + active ? "bg-amber-100 text-amber-900" : "text-gray-900" + }` + } + onClick={(e: any) => { + if (option.children !== null) { + e.preventDefault(); + setOpenChildFor(option); + } + }} + value={option} + > + {({ selected }) => ( + <> + {openChildFor?.id === option.id && ( +
+ {option.children?.map((child) => ( + + `relative cursor-default select-none py-2 pl-10 pr-4 ${ + active ? "bg-amber-100 text-amber-900" : "text-gray-900" + }` + } + as="div" + value={child} + > + {({ selected }) => ( + <> + + {child.label} + + {selected ? ( + + + ) : null} + + )} + + ))} + +
+
+ )} + + {option.label} + + {selected ? ( + + + ) : null} + + )} + + ))} + + +
+ )} + +
+ ); +};