(frontend) add a Popover primitive

easily use buttons toggling styled RAC popovers
This commit is contained in:
Emmanuel Pelletier
2024-07-21 16:00:37 +02:00
parent 789bce5092
commit d6b5e9a50c
5 changed files with 79 additions and 5 deletions

View File

@@ -146,6 +146,7 @@ const config: Config = {
2: { value: '2' },
},
radii: {
4: { value: '0.25rem' },
6: { value: '0.375rem' },
8: { value: '0.5rem' },
16: { value: '1rem' },
@@ -187,7 +188,7 @@ const config: Config = {
text: { value: '{colors.white}' },
warm: { value: '{colors.blue.300}' },
subtle: { value: '{colors.blue.100}' },
'subtle-text': { value: '{colors.sky.700}' },
'subtle-text': { value: '{colors.blue.700}' },
},
danger: {
DEFAULT: { value: '{colors.red.600}' },

View File

@@ -15,7 +15,7 @@ export const Box = ({
}: BoxProps) => {
const { t } = useTranslation()
return (
<BoxDiv asScreen>
<BoxDiv type="screen">
{!!title && <H lvl={1}>{title}</H>}
{children}
{!!withBackButton && (

View File

@@ -9,14 +9,18 @@ const box = cva({
flex: 1,
},
variants: {
asScreen: {
true: {
type: {
screen: {
margin: 'auto',
width: '38rem',
maxWidth: '100%',
marginTop: '6rem',
textAlign: 'center',
},
popover: {
padding: 'boxPadding.xs',
minWidth: '10rem',
},
},
variant: {
default: {
@@ -42,7 +46,6 @@ const box = cva({
},
},
defaultVariants: {
asScreen: false,
variant: 'default',
size: 'default',
},

View File

@@ -0,0 +1,68 @@
import { ReactNode } from 'react'
import {
DialogProps,
DialogTrigger,
Popover as RACPopover,
Dialog,
OverlayArrow,
} from 'react-aria-components'
import { styled } from '@/styled-system/jsx'
import { Box } from './Box'
const StyledPopover = styled(RACPopover, {
base: {
'&[data-placement="bottom"]': {
marginTop: 0.25,
},
},
})
const StyledOverlayArrow = styled(OverlayArrow, {
base: {
display: 'block',
fill: 'box.bg',
stroke: 'box.border',
strokeWidth: 1,
'&[data-placement="bottom"] svg': {
transform: 'rotate(180deg) translateY(-1px)',
},
},
})
/**
* a Popover is a tuple of a trigger component (most usually a Button) that toggles some interactive content in a tooltip around the trigger
*/
export const Popover = ({
children,
...dialogProps
}: {
children: [
trigger: ReactNode,
popoverContent:
| (({ close }: { close: () => void }) => ReactNode)
| ReactNode,
]
} & DialogProps) => {
const [trigger, popoverContent] = children
return (
<DialogTrigger>
{trigger}
<StyledPopover>
<StyledOverlayArrow>
<svg width={12} height={12} viewBox="0 0 12 12">
<path d="M0 0 L6 6 L12 0" />
</svg>
</StyledOverlayArrow>
<Dialog {...dialogProps}>
{({ close }) => (
<Box size="sm" type="popover">
{typeof popoverContent === 'function'
? popoverContent({ close })
: popoverContent}
</Box>
)}
</Dialog>
</StyledPopover>
</DialogTrigger>
)
}

View File

@@ -9,4 +9,6 @@ export { Hr } from './Hr'
export { Italic } from './Italic'
export { Link } from './Link'
export { P } from './P'
export { Popover } from './Popover'
export { PopoverList } from './PopoverList'
export { Text } from './Text'