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