✨(frontend) add a Popover primitive
easily use buttons toggling styled RAC popovers
This commit is contained in:
@@ -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}' },
|
||||
|
||||
@@ -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 && (
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
|
||||
68
src/frontend/src/primitives/Popover.tsx
Normal file
68
src/frontend/src/primitives/Popover.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user