Add Popover component
* Popover is a wrapper of Radix's Popover component that we will use to wrap the combobox. * Move styles that were in PopoverContent.scss to Popover.scss
This commit is contained in:
parent
6a7cfb230d
commit
07e43f4309
3 changed files with 132 additions and 17 deletions
26
components/common/Popover/index.scss
Normal file
26
components/common/Popover/index.scss
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
.Popover {
|
||||
animation: scaleIn $duration-zoom ease-out;
|
||||
background: var(--dialog-bg);
|
||||
border-radius: $card-corner;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.18);
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.24);
|
||||
outline: none;
|
||||
overflow: hidden;
|
||||
padding: $unit;
|
||||
transform-origin: var(--radix-popover-content-transform-origin);
|
||||
width: var(--radix-popover-trigger-width);
|
||||
z-index: 5;
|
||||
|
||||
&.Flush {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.Arrow {
|
||||
fill: var(--dialog-bg);
|
||||
filter: drop-shadow(0px 1px 1px rgb(0 0 0 / 0.18));
|
||||
margin-top: -1px;
|
||||
}
|
||||
}
|
||||
|
||||
[data-radix-popper-content-wrapper] {
|
||||
}
|
||||
106
components/common/Popover/index.tsx
Normal file
106
components/common/Popover/index.tsx
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
import React, {
|
||||
ComponentProps,
|
||||
PropsWithChildren,
|
||||
ReactNode,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react'
|
||||
import classNames from 'classnames'
|
||||
|
||||
import * as PopoverPrimitive from '@radix-ui/react-popover'
|
||||
import ChevronIcon from '~public/icons/Chevron.svg'
|
||||
|
||||
import './index.scss'
|
||||
|
||||
interface Props extends ComponentProps<'div'> {
|
||||
open: boolean
|
||||
disabled?: boolean
|
||||
icon?: {
|
||||
src: string
|
||||
alt: string
|
||||
}
|
||||
trigger?: {
|
||||
className?: string
|
||||
placeholder?: string
|
||||
}
|
||||
value?: {
|
||||
element: ReactNode
|
||||
rawValue: string
|
||||
}
|
||||
onOpenChange?: () => void
|
||||
}
|
||||
|
||||
const Popover = React.forwardRef<HTMLDivElement, Props>(function Popover(
|
||||
{ children, ...props }: PropsWithChildren<Props>,
|
||||
forwardedRef
|
||||
) {
|
||||
// Component state
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
// Element classes
|
||||
const triggerClasses = classNames(
|
||||
{
|
||||
SelectTrigger: true,
|
||||
Disabled: props.disabled,
|
||||
},
|
||||
props.trigger?.className
|
||||
)
|
||||
|
||||
// Hooks
|
||||
useEffect(() => {
|
||||
setOpen(props.open)
|
||||
}, [props.open])
|
||||
|
||||
// Elements
|
||||
const value = props.value ? (
|
||||
<span className="Value" data-value={props.value?.rawValue}>
|
||||
{props.value?.element}
|
||||
</span>
|
||||
) : (
|
||||
<span className="Value Empty">{props.placeholder}</span>
|
||||
)
|
||||
|
||||
const icon = props.icon ? (
|
||||
<img alt={props.icon.alt} src={props.icon.src} />
|
||||
) : (
|
||||
''
|
||||
)
|
||||
|
||||
const arrow = !props.disabled ? (
|
||||
<i className="SelectIcon">
|
||||
<ChevronIcon />
|
||||
</i>
|
||||
) : (
|
||||
''
|
||||
)
|
||||
|
||||
return (
|
||||
<PopoverPrimitive.Root
|
||||
open={open}
|
||||
onOpenChange={props.onOpenChange}
|
||||
modal={true}
|
||||
>
|
||||
<PopoverPrimitive.Trigger
|
||||
className={triggerClasses}
|
||||
data-placeholder={!props.value}
|
||||
>
|
||||
{icon}
|
||||
{value}
|
||||
{arrow}
|
||||
</PopoverPrimitive.Trigger>
|
||||
<PopoverPrimitive.Content
|
||||
className={classNames({ Popover: true }, props.className)}
|
||||
sideOffset={8}
|
||||
ref={forwardedRef}
|
||||
>
|
||||
{children}
|
||||
</PopoverPrimitive.Content>
|
||||
</PopoverPrimitive.Root>
|
||||
)
|
||||
})
|
||||
|
||||
Popover.defaultProps = {
|
||||
disabled: false,
|
||||
}
|
||||
|
||||
export default Popover
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
.Popover {
|
||||
animation: scaleIn $duration-zoom ease-out;
|
||||
background: var(--dialog-bg);
|
||||
border-radius: $card-corner;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.18);
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.24);
|
||||
outline: none;
|
||||
padding: $unit;
|
||||
transform-origin: var(--radix-popover-content-transform-origin);
|
||||
z-index: 5;
|
||||
|
||||
.Arrow {
|
||||
fill: var(--dialog-bg);
|
||||
filter: drop-shadow(0px 1px 1px rgb(0 0 0 / 0.18));
|
||||
margin-top: -1px;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue