chore: change headlessui api to new

This commit is contained in:
Joel
2025-01-26 15:02:31 +08:00
parent c044cc5160
commit fd5028da5b
22 changed files with 305 additions and 220 deletions

View File

@ -1,6 +1,6 @@
import { Fragment, useCallback } from 'react'
import type { ElementType, ReactNode } from 'react'
import { Dialog, Transition } from '@headlessui/react'
import { Dialog, DialogPanel, DialogTitle, Transition } from '@headlessui/react'
import classNames from '@/utils/classnames'
// https://headlessui.com/react/dialog
@ -34,7 +34,7 @@ const CustomDialog = ({
return (
<Transition appear show={show} as={Fragment}>
<Dialog as="div" className="relative z-40" onClose={close}>
<Transition.Child
{/* <Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
@ -44,11 +44,13 @@ const CustomDialog = ({
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-black bg-opacity-25" />
</Transition.Child>
</Transition.Child> */}
{/* TODO: to new Transition */}
<div className="fixed inset-0 bg-black bg-opacity-25" />
<div className="fixed inset-0 overflow-y-auto">
<div className="flex items-center justify-center min-h-full">
<Transition.Child
{/* <Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
@ -57,14 +59,14 @@ const CustomDialog = ({
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className={classNames('w-full max-w-[800px] p-6 overflow-hidden transition-all transform bg-components-panel-bg border-[0.5px] border-components-panel-border shadow-xl rounded-2xl', className)}>
<DialogPanel className={classNames('w-full max-w-[800px] p-6 overflow-hidden transition-all transform bg-components-panel-bg border-[0.5px] border-components-panel-border shadow-xl rounded-2xl', className)}>
{Boolean(title) && (
<Dialog.Title
<DialogTitle
as={titleAs || 'h3'}
className={classNames('pr-8 pb-3 title-2xl-semi-bold text-text-primary', titleClassName)}
>
{title}
</Dialog.Title>
</DialogTitle>
)}
<div className={classNames(bodyClassName)}>
{children}
@ -74,8 +76,27 @@ const CustomDialog = ({
{footer}
</div>
)}
</Dialog.Panel>
</Transition.Child>
</DialogPanel>
</Transition.Child> */}
{/* TODO: to new Transition */}
<DialogPanel className={classNames('w-full max-w-[800px] p-6 overflow-hidden transition-all transform bg-components-panel-bg border-[0.5px] border-components-panel-border shadow-xl rounded-2xl', className)}>
{Boolean(title) && (
<DialogTitle
as={titleAs || 'h3'}
className={classNames('pr-8 pb-3 title-2xl-semi-bold text-text-primary', titleClassName)}
>
{title}
</DialogTitle>
)}
<div className={classNames(bodyClassName)}>
{children}
</div>
{Boolean(footer) && (
<div className={classNames('flex items-center justify-end gap-2 px-6 pb-6 pt-3', footerClassName)}>
{footer}
</div>
)}
</DialogPanel>
</div>
</div>
</Dialog>

View File

@ -1,5 +1,5 @@
'use client'
import { Dialog } from '@headlessui/react'
import { Dialog, DialogBackdrop, DialogTitle } from '@headlessui/react'
import { useTranslation } from 'react-i18next'
import { XMarkIcon } from '@heroicons/react/24/outline'
import Button from '../button'
@ -48,21 +48,21 @@ export default function Drawer({
>
<div className={cn('flex w-screen h-screen justify-end', positionCenter && '!justify-center')}>
{/* mask */}
<Dialog.Overlay
<DialogBackdrop
className={cn('z-40 fixed inset-0', mask && 'bg-black bg-opacity-30')}
/>
<div className={cn('relative z-50 flex flex-col justify-between bg-components-panel-bg w-full max-w-sm p-6 overflow-hidden text-left align-middle shadow-xl', panelClassname)}>
<>
{title && <Dialog.Title
{title && <DialogTitle
as="h3"
className="text-lg font-medium leading-6 text-text-primary"
>
{title}
</Dialog.Title>}
{showClose && <Dialog.Title className="flex items-center mb-4" as="div">
</DialogTitle>}
{showClose && <DialogTitle className="flex items-center mb-4" as="div">
<XMarkIcon className='w-4 h-4 text-text-tertiary' onClick={onClose} />
</Dialog.Title>}
{description && <Dialog.Description className='text-text-tertiary text-xs font-normal mt-2'>{description}</Dialog.Description>}
</DialogTitle>}
{description && <div className='text-text-tertiary text-xs font-normal mt-2'>{description}</div>}
{children}
</>
{footer || (footer === null

View File

@ -1,6 +1,6 @@
import { Fragment, useCallback } from 'react'
import type { ReactNode } from 'react'
import { Dialog, Transition } from '@headlessui/react'
import { Dialog, DialogPanel, Transition } from '@headlessui/react'
import cn from '@/utils/classnames'
type DialogProps = {
@ -22,7 +22,7 @@ const DialogWrapper = ({
return (
<Transition appear show={show} as={Fragment}>
<Dialog as="div" className="relative z-40" onClose={close}>
<Transition.Child
{/* <Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
@ -32,11 +32,13 @@ const DialogWrapper = ({
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-black bg-opacity-25" />
</Transition.Child>
</Transition.Child> */}
{/* TODO: to new Transition */}
<div className="fixed inset-0 bg-black bg-opacity-25" />
<div className="fixed inset-0">
<div className={cn('flex flex-col items-end justify-center min-h-full pb-2', inWorkflow ? 'pt-[112px]' : 'pt-[64px] pr-2')}>
<Transition.Child
{/* <Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
@ -45,10 +47,14 @@ const DialogWrapper = ({
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className={cn('grow flex flex-col relative w-[420px] h-0 p-0 overflow-hidden text-left align-middle transition-all transform bg-components-panel-bg-alt border-components-panel-border shadow-xl', inWorkflow ? 'border-t-[0.5px] border-l-[0.5px] border-b-[0.5px] rounded-l-2xl' : 'border-[0.5px] rounded-2xl', className)}>
<DialogPanel className={cn('grow flex flex-col relative w-[420px] h-0 p-0 overflow-hidden text-left align-middle transition-all transform bg-components-panel-bg-alt border-components-panel-border shadow-xl', inWorkflow ? 'border-t-[0.5px] border-l-[0.5px] border-b-[0.5px] rounded-l-2xl' : 'border-[0.5px] rounded-2xl', className)}>
{children}
</Dialog.Panel>
</Transition.Child>
</DialogPanel>
</Transition.Child> */}
{/* TODO: to new Transition */}
<DialogPanel className={cn('grow flex flex-col relative w-[420px] h-0 p-0 overflow-hidden text-left align-middle transition-all transform bg-components-panel-bg-alt border-components-panel-border shadow-xl', inWorkflow ? 'border-t-[0.5px] border-l-[0.5px] border-b-[0.5px] rounded-l-2xl' : 'border-[0.5px] rounded-2xl', className)}>
{children}
</DialogPanel>
</div>
</div>
</Dialog>

View File

@ -5,7 +5,7 @@ import React, { Fragment } from 'react'
import { usePathname } from 'next/navigation'
import { useTranslation } from 'react-i18next'
import { RiCloseLine } from '@remixicon/react'
import { Listbox, Transition } from '@headlessui/react'
import { Listbox, ListboxButton, ListboxOption, ListboxOptions, Transition } from '@headlessui/react'
import { CheckIcon, ChevronDownIcon } from '@heroicons/react/20/solid'
import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks'
import type { Item } from '@/app/components/base/select'
@ -67,7 +67,7 @@ const VoiceParamConfig = ({
<>
<div className='mb-4 flex items-center justify-between'>
<div className='text-text-primary system-xl-semibold'>{t('appDebug.voice.voiceSettings.title')}</div>
<div className='p-1 cursor-pointer' onClick={onClose}><RiCloseLine className='w-4 h-4 text-text-tertiary'/></div>
<div className='p-1 cursor-pointer' onClick={onClose}><RiCloseLine className='w-4 h-4 text-text-tertiary' /></div>
</div>
<div className='mb-3'>
<div className='mb-1 py-1 flex items-center text-text-secondary system-sm-semibold'>
@ -92,7 +92,7 @@ const VoiceParamConfig = ({
}}
>
<div className='relative h-8'>
<Listbox.Button
<ListboxButton
className={'w-full h-full rounded-lg border-0 bg-gray-100 py-1.5 pl-3 pr-10 sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-gray-200 group-hover:bg-gray-200 cursor-pointer'}>
<span className={classNames('block truncate text-left', !languageItem?.name && 'text-gray-400')}>
{languageItem?.name ? t(`common.voice.language.${languageItem?.value.replace('-', '')}`) : localLanguagePlaceholder}
@ -103,7 +103,7 @@ const VoiceParamConfig = ({
aria-hidden="true"
/>
</span>
</Listbox.Button>
</ListboxButton>
<Transition
as={Fragment}
leave="transition ease-in duration-100"
@ -111,10 +111,10 @@ const VoiceParamConfig = ({
leaveTo="opacity-0"
>
<Listbox.Options
<ListboxOptions
className="absolute z-10 mt-1 px-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg border-gray-200 border-[0.5px] focus:outline-none sm:text-sm">
{languages.map((item: Item) => (
<Listbox.Option
<ListboxOption
key={item.value}
className={({ active }) =>
`relative cursor-pointer select-none py-2 pl-3 pr-9 rounded-lg hover:bg-gray-100 text-gray-700 ${active ? 'bg-gray-100' : ''
@ -133,14 +133,14 @@ const VoiceParamConfig = ({
'absolute inset-y-0 right-0 flex items-center pr-4 text-gray-700',
)}
>
<CheckIcon className="h-5 w-5" aria-hidden="true"/>
<CheckIcon className="h-5 w-5" aria-hidden="true" />
</span>
)}
</>
)}
</Listbox.Option>
</ListboxOption>
))}
</Listbox.Options>
</ListboxOptions>
</Transition>
</div>
</Listbox>
@ -160,7 +160,7 @@ const VoiceParamConfig = ({
}}
>
<div className={'grow relative h-8'}>
<Listbox.Button
<ListboxButton
className={'w-full h-full rounded-lg border-0 bg-gray-100 py-1.5 pl-3 pr-10 sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-gray-200 group-hover:bg-gray-200 cursor-pointer'}>
<span
className={classNames('block truncate text-left', !voiceItem?.name && 'text-gray-400')}>{voiceItem?.name ?? localVoicePlaceholder}</span>
@ -170,7 +170,7 @@ const VoiceParamConfig = ({
aria-hidden="true"
/>
</span>
</Listbox.Button>
</ListboxButton>
<Transition
as={Fragment}
leave="transition ease-in duration-100"
@ -178,10 +178,10 @@ const VoiceParamConfig = ({
leaveTo="opacity-0"
>
<Listbox.Options
<ListboxOptions
className="absolute z-10 mt-1 px-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg border-gray-200 border-[0.5px] focus:outline-none sm:text-sm">
{voiceItems?.map((item: Item) => (
<Listbox.Option
<ListboxOption
key={item.value}
className={({ active }) =>
`relative cursor-pointer select-none py-2 pl-3 pr-9 rounded-lg hover:bg-gray-100 text-gray-700 ${active ? 'bg-gray-100' : ''
@ -199,14 +199,14 @@ const VoiceParamConfig = ({
'absolute inset-y-0 right-0 flex items-center pr-4 text-gray-700',
)}
>
<CheckIcon className="h-5 w-5" aria-hidden="true"/>
<CheckIcon className="h-5 w-5" aria-hidden="true" />
</span>
)}
</>
)}
</Listbox.Option>
</ListboxOption>
))}
</Listbox.Options>
</ListboxOptions>
</Transition>
</div>
</Listbox>

View File

@ -1,4 +1,4 @@
import { Dialog, Transition } from '@headlessui/react'
import { Dialog, DialogPanel, Transition } from '@headlessui/react'
import { Fragment } from 'react'
import { RiCloseLargeLine } from '@remixicon/react'
import classNames from '@/utils/classnames'
@ -27,7 +27,7 @@ export default function FullScreenModal({
return (
<Transition show={open} as={Fragment}>
<Dialog as="div" className={classNames('modal-dialog', wrapperClassName)} onClose={onClose}>
<Transition.Child
{/* <Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
@ -37,7 +37,9 @@ export default function FullScreenModal({
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-background-overlay-backdrop backdrop-blur-[6px]" />
</Transition.Child>
</Transition.Child> */}
{/* TODO: to new Transition */}
<div className="fixed inset-0 bg-background-overlay-backdrop backdrop-blur-[6px]" />
<div
className="fixed inset-0 h-screen w-screen p-4"
@ -47,7 +49,7 @@ export default function FullScreenModal({
}}
>
<div className="w-full h-full bg-background-default-subtle rounded-2xl border border-effects-highlight relative">
<Transition.Child
{/* <Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
@ -56,7 +58,7 @@ export default function FullScreenModal({
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className={classNames(
<DialogPanel className={classNames(
'h-full',
overflowVisible ? 'overflow-visible' : 'overflow-hidden',
className,
@ -72,8 +74,26 @@ export default function FullScreenModal({
<RiCloseLargeLine className='w-3.5 h-3.5 text-components-button-tertiary-text' />
</div>}
{children}
</Dialog.Panel>
</Transition.Child>
</DialogPanel>
</Transition.Child> */}
{/* TODO: to new Transition */}
<DialogPanel className={classNames(
'h-full',
overflowVisible ? 'overflow-visible' : 'overflow-hidden',
className,
)}>
{closable
&& <div
className='absolute z-50 top-3 right-3 w-9 h-9 flex items-center justify-center rounded-[10px]
bg-components-button-tertiary-bg hover:bg-components-button-tertiary-bg-hover cursor-pointer'
onClick={(e) => {
e.stopPropagation()
onClose()
}}>
<RiCloseLargeLine className='w-3.5 h-3.5 text-components-button-tertiary-text' />
</div>}
{children}
</DialogPanel>
</div>
</div>
</Dialog>

View File

@ -1,4 +1,4 @@
import { Dialog, Transition } from '@headlessui/react'
import { Dialog, DialogPanel, DialogTitle, Transition } from '@headlessui/react'
import { Fragment } from 'react'
import { RiCloseLine } from '@remixicon/react'
import classNames from '@/utils/classnames'
@ -30,7 +30,7 @@ export default function Modal({
return (
<Transition appear show={isShow} as={Fragment}>
<Dialog as="div" className={classNames('relative z-[60]', wrapperClassName)} onClose={onClose}>
<Transition.Child
{/* <Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
@ -40,7 +40,9 @@ export default function Modal({
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-background-overlay" />
</Transition.Child>
</Transition.Child> */}
{/* TODO: to new Transition */}
<div className="fixed inset-0 bg-background-overlay" />
<div
className="fixed inset-0 overflow-y-auto"
@ -50,7 +52,7 @@ export default function Modal({
}}
>
<div className="flex min-h-full items-center justify-center p-4 text-center">
<Transition.Child
{/* <Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
@ -59,20 +61,20 @@ export default function Modal({
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className={classNames(
<DialogPanel className={classNames(
'w-full max-w-[480px] transform rounded-2xl bg-components-panel-bg p-6 text-left align-middle shadow-xl transition-all',
overflowVisible ? 'overflow-visible' : 'overflow-hidden',
className,
)}>
{title && <Dialog.Title
{title && <DialogTitle
as="h3"
className="title-2xl-semi-bold text-text-primary"
>
{title}
</Dialog.Title>}
{description && <Dialog.Description className='text-text-secondary body-md-regular mt-2'>
</DialogTitle>}
{description && <div className='text-text-secondary body-md-regular mt-2'>
{description}
</Dialog.Description>}
</div>}
{closable
&& <div className='absolute z-10 top-6 right-6 w-5 h-5 rounded-2xl flex items-center justify-center hover:cursor-pointer hover:bg-state-base-hover'>
<RiCloseLine className='w-4 h-4 text-text-tertiary' onClick={
@ -83,8 +85,34 @@ export default function Modal({
} />
</div>}
{children}
</Dialog.Panel>
</Transition.Child>
</DialogPanel>
</Transition.Child> */}
{/* TODO: to new Transition */}
<DialogPanel className={classNames(
'w-full max-w-[480px] transform rounded-2xl bg-components-panel-bg p-6 text-left align-middle shadow-xl transition-all',
overflowVisible ? 'overflow-visible' : 'overflow-hidden',
className,
)}>
{title && <DialogTitle
as="h3"
className="title-2xl-semi-bold text-text-primary"
>
{title}
</DialogTitle>}
{description && <div className='text-text-secondary body-md-regular mt-2'>
{description}
</div>}
{closable
&& <div className='absolute z-10 top-6 right-6 w-5 h-5 rounded-2xl flex items-center justify-center hover:cursor-pointer hover:bg-state-base-hover'>
<RiCloseLine className='w-4 h-4 text-text-tertiary' onClick={
(e) => {
e.stopPropagation()
onClose()
}
} />
</div>}
{children}
</DialogPanel>
</div>
</div>
</Dialog>

View File

@ -1,7 +1,7 @@
'use client'
import { useTranslation } from 'react-i18next'
import { Fragment } from 'react'
import { Menu, Transition } from '@headlessui/react'
import { Menu, MenuButton, MenuItem, MenuItems, Transition } from '@headlessui/react'
import NotionIcon from '../../notion-icon'
import s from './index.module.css'
import cn from '@/utils/classnames'
@ -25,7 +25,7 @@ export default function WorkspaceSelector({
{
({ open }) => (
<>
<Menu.Button className={`flex items-center justify-center h-7 rounded-md hover:bg-gray-50 ${open && 'bg-gray-50'} cursor-pointer`}>
<MenuButton className={`flex items-center justify-center h-7 rounded-md hover:bg-gray-50 ${open && 'bg-gray-50'} cursor-pointer`}>
<NotionIcon
className='ml-1 mr-2'
src={currentWorkspace?.workspace_icon}
@ -34,7 +34,7 @@ export default function WorkspaceSelector({
<div className='mr-1 w-[90px] text-left text-sm font-medium text-gray-700 truncate' title={currentWorkspace?.workspace_name}>{currentWorkspace?.workspace_name}</div>
<div className='mr-1 px-1 h-[18px] bg-primary-50 rounded-lg text-xs font-medium text-primary-600'>{currentWorkspace?.pages.length}</div>
<div className={cn(s['down-arrow'], 'mr-2 w-3 h-3')} />
</Menu.Button>
</MenuButton>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
@ -44,7 +44,7 @@ export default function WorkspaceSelector({
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items
<MenuItems
className={cn(
s.popup,
`absolute left-0 top-8 w-80
@ -55,7 +55,7 @@ export default function WorkspaceSelector({
<div className="p-1 max-h-50 overflow-auto">
{
items.map(item => (
<Menu.Item key={item.workspace_id}>
<MenuItem key={item.workspace_id}>
<div
className='flex items-center px-3 h-9 hover:bg-gray-50 cursor-pointer'
onClick={() => onSelect(item.workspace_id)}
@ -70,11 +70,11 @@ export default function WorkspaceSelector({
{item.pages.length} {t('common.dataSource.notion.selector.pageSelected')}
</div>
</div>
</Menu.Item>
</MenuItem>
))
}
</div>
</Menu.Items>
</MenuItems>
</Transition>
</>
)

View File

@ -1,4 +1,4 @@
import { Popover, Transition } from '@headlessui/react'
import { Popover, PopoverButton, PopoverPanel, Transition } from '@headlessui/react'
import { Fragment, cloneElement, useRef } from 'react'
import cn from '@/utils/classnames'
@ -59,7 +59,7 @@ export default function CustomPopover({
onMouseEnter: () => onMouseEnter(open),
})}
>
<Popover.Button
<PopoverButton
ref={buttonRef}
disabled={disabled}
className={cn(
@ -70,9 +70,9 @@ export default function CustomPopover({
)}
>
{btnElement}
</Popover.Button>
</PopoverButton>
<Transition as={Fragment}>
<Popover.Panel
<PopoverPanel
className={cn(
'absolute z-10 w-full max-w-sm px-4 mt-1 sm:px-0 lg:max-w-3xl',
position === 'bottom' && '-translate-x-1/2 left-1/2',
@ -109,7 +109,7 @@ export default function CustomPopover({
})}
</div>
)}
</Popover.Panel>
</PopoverPanel>
</Transition>
</div>
</>

View File

@ -1,7 +1,7 @@
'use client'
import type { FC } from 'react'
import React, { Fragment, useEffect, useState } from 'react'
import { Combobox, Listbox, Transition } from '@headlessui/react'
import { Combobox, ComboboxButton, ComboboxInput, ComboboxOption, ComboboxOptions, Listbox, ListboxButton, ListboxOption, ListboxOptions, Transition } from '@headlessui/react'
import { ChevronDownIcon, ChevronUpIcon, XMarkIcon } from '@heroicons/react/20/solid'
import Badge from '../badge/index'
import { RiCheckLine } from '@remixicon/react'
@ -101,7 +101,7 @@ const Select: FC<ISelectProps> = ({
<div className={classNames('relative')}>
<div className='group text-text-secondary'>
{allowSearch
? <Combobox.Input
? <ComboboxInput
className={`w-full rounded-lg border-0 ${bgClassName} py-1.5 pl-3 pr-10 shadow-sm sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-state-base-hover group-hover:bg-state-base-hover ${disabled ? 'cursor-not-allowed' : 'cursor-pointer'}`}
onChange={(event) => {
if (!disabled)
@ -109,28 +109,28 @@ const Select: FC<ISelectProps> = ({
}}
displayValue={(item: Item) => item?.name}
/>
: <Combobox.Button onClick={
: <ComboboxButton onClick={
() => {
if (!disabled)
setOpen(!open)
}
} className={classNames(`flex items-center h-9 w-full rounded-lg border-0 ${bgClassName} py-1.5 pl-3 pr-10 shadow-sm sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-state-base-hover group-hover:bg-state-base-hover`, optionClassName)}>
<div className='w-0 grow text-left truncate' title={selectedItem?.name}>{selectedItem?.name}</div>
</Combobox.Button>}
<Combobox.Button className="absolute inset-y-0 right-0 flex items-center rounded-r-md px-2 focus:outline-none" onClick={
</ComboboxButton>}
<ComboboxButton className="absolute inset-y-0 right-0 flex items-center rounded-r-md px-2 focus:outline-none" onClick={
() => {
if (!disabled)
setOpen(!open)
}
}>
{open ? <ChevronUpIcon className="h-5 w-5" /> : <ChevronDownIcon className="h-5 w-5" />}
</Combobox.Button>
</ComboboxButton>
</div>
{(filteredItems.length > 0 && open) && (
<Combobox.Options className={`absolute z-10 mt-1 px-1 max-h-60 w-full overflow-auto rounded-md bg-components-panel-bg-blur backdrop-blur-sm py-1 text-base shadow-lg border-components-panel-border border-[0.5px] focus:outline-none sm:text-sm ${overlayClassName}`}>
<ComboboxOptions className={`absolute z-10 mt-1 px-1 max-h-60 w-full overflow-auto rounded-md bg-components-panel-bg-blur backdrop-blur-sm py-1 text-base shadow-lg border-components-panel-border border-[0.5px] focus:outline-none sm:text-sm ${overlayClassName}`}>
{filteredItems.map((item: Item) => (
<Combobox.Option
<ComboboxOption
key={item.value}
value={item}
className={({ active }: { active: boolean }) =>
@ -161,9 +161,9 @@ const Select: FC<ISelectProps> = ({
)}
</>
)}
</Combobox.Option>
</ComboboxOption>
))}
</Combobox.Options>
</ComboboxOptions>
)}
</div>
</Combobox >
@ -210,9 +210,9 @@ const SimpleSelect: FC<ISelectProps> = ({
}}
>
<div className={classNames('group/simple-select relative h-9', wrapperClassName)}>
{renderTrigger && <Listbox.Button className='w-full'>{renderTrigger(selectedItem)}</Listbox.Button>}
{renderTrigger && <ListboxButton className='w-full'>{renderTrigger(selectedItem)}</ListboxButton>}
{!renderTrigger && (
<Listbox.Button className={classNames(`flex items-center w-full h-full rounded-lg border-0 bg-components-input-bg-normal pl-3 pr-10 sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-state-base-hover-alt group-hover/simple-select:bg-state-base-hover-alt ${disabled ? 'cursor-not-allowed' : 'cursor-pointer'}`, className)}>
<ListboxButton className={classNames(`flex items-center w-full h-full rounded-lg border-0 bg-components-input-bg-normal pl-3 pr-10 sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-state-base-hover-alt group-hover/simple-select:bg-state-base-hover-alt ${disabled ? 'cursor-not-allowed' : 'cursor-pointer'}`, className)}>
<span className={classNames('block truncate text-left system-sm-regular text-components-input-text-filled', !selectedItem?.name && 'text-components-input-text-placeholder')}>{selectedItem?.name ?? localPlaceholder}</span>
<span className="absolute inset-y-0 right-0 flex items-center pr-2">
{(selectedItem && !notClearable)
@ -234,7 +234,7 @@ const SimpleSelect: FC<ISelectProps> = ({
/>
)}
</span>
</Listbox.Button>
</ListboxButton>
)}
{!disabled && (
@ -245,9 +245,9 @@ const SimpleSelect: FC<ISelectProps> = ({
leaveTo="opacity-0"
>
<Listbox.Options className={classNames('absolute z-10 mt-1 px-1 max-h-60 w-full overflow-auto rounded-md bg-components-panel-bg-blur backdrop-blur-sm py-1 text-base shadow-lg border-components-panel-border border-[0.5px] focus:outline-none sm:text-sm', optionWrapClassName)}>
<ListboxOptions className={classNames('absolute z-10 mt-1 px-1 max-h-60 w-full overflow-auto rounded-md bg-components-panel-bg-blur backdrop-blur-sm py-1 text-base shadow-lg border-components-panel-border border-[0.5px] focus:outline-none sm:text-sm', optionWrapClassName)}>
{items.map((item: Item) => (
<Listbox.Option
<ListboxOption
key={item.value}
className={({ active }) =>
classNames(
@ -276,9 +276,9 @@ const SimpleSelect: FC<ISelectProps> = ({
</>)}
</>
)}
</Listbox.Option>
</ListboxOption>
))}
</Listbox.Options>
</ListboxOptions>
</Transition>
)}
</div>

View File

@ -1,7 +1,8 @@
'use client'
import { Menu, Transition } from '@headlessui/react'
import { Menu, MenuButton, MenuItem, MenuItems, Transition } from '@headlessui/react'
import { Fragment } from 'react'
import { GlobeAltIcon } from '@heroicons/react/24/outline'
import cn from '@/utils/classnames'
type ISelectProps = {
items: Array<{ value: string; name: string }>
@ -21,14 +22,14 @@ export default function Select({
<div className="w-56 text-right">
<Menu as="div" className="relative inline-block text-left">
<div>
<Menu.Button className="inline-flex w-full h-[44px]justify-center items-center
<MenuButton className="inline-flex w-full h-[44px]justify-center items-center
rounded-lg px-[10px] py-[6px]
text-gray-900 text-[13px] font-medium
border border-gray-200
hover:bg-gray-100">
<GlobeAltIcon className="w-5 h-5 mr-1" aria-hidden="true" />
{item?.name}
</Menu.Button>
</MenuButton>
</div>
<Transition
as={Fragment}
@ -39,14 +40,13 @@ export default function Select({
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="absolute right-0 mt-2 w-[200px] origin-top-right divide-y divide-gray-100 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none z-10">
<MenuItems className="absolute right-0 mt-2 w-[200px] origin-top-right divide-y divide-gray-100 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none z-10">
<div className="px-1 py-1 ">
{items.map((item) => {
return <Menu.Item key={item.value}>
return <MenuItem key={item.value}>
{({ active }) => (
<button
className={`${active ? 'bg-gray-100' : ''
} group flex w-full items-center rounded-lg px-3 py-2 text-sm text-gray-700`}
className={cn(active && 'bg-gray-100', 'group flex w-full items-center rounded-lg px-3 py-2 text-sm text-gray-700')}
onClick={(evt) => {
evt.preventDefault()
onChange && onChange(item.value)
@ -55,12 +55,12 @@ export default function Select({
{item.name}
</button>
)}
</Menu.Item>
</MenuItem>
})}
</div>
</Menu.Items>
</MenuItems>
</Transition>
</Menu>
</div>
@ -77,9 +77,9 @@ export function InputSelect({
<div className="w-full">
<Menu as="div" className="w-full">
<div>
<Menu.Button className="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 sm:text-sm h-[38px] text-left">
<MenuButton className="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder:text-gray-400 sm:text-sm h-[38px] text-left">
{item?.name}
</Menu.Button>
</MenuButton>
</div>
<Transition
as={Fragment}
@ -90,14 +90,13 @@ export function InputSelect({
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="absolute right-0 mt-2 w-full origin-top-right divide-y divide-gray-100 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none z-10">
<MenuItems className="absolute right-0 mt-2 w-full origin-top-right divide-y divide-gray-100 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none z-10">
<div className="px-1 py-1 ">
{items.map((item) => {
return <Menu.Item key={item.value}>
return <MenuItem key={item.value}>
{({ active }) => (
<button
className={`${active ? 'bg-gray-100' : ''
} group flex w-full items-center rounded-md px-2 py-2 text-sm`}
className={`${active ? 'bg-gray-100' : ''} group flex w-full items-center rounded-md px-2 py-2 text-sm`}
onClick={() => {
onChange && onChange(item.value)
}}
@ -105,12 +104,12 @@ export function InputSelect({
{item.name}
</button>
)}
</Menu.Item>
</MenuItem>
})}
</div>
</Menu.Items>
</MenuItems>
</Transition>
</Menu>
</div>