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:
Justin Edmund 2023-06-05 20:21:35 -07:00
parent 6a7cfb230d
commit 07e43f4309
3 changed files with 132 additions and 17 deletions

View 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] {
}

View 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

View file

@ -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;
}
}