From d6b5e9a50cfb2656c72f3b4c10420fab32ba4124 Mon Sep 17 00:00:00 2001 From: Emmanuel Pelletier Date: Sun, 21 Jul 2024 16:00:37 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(frontend)=20add=20a=20Popover=20primi?= =?UTF-8?q?tive?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit easily use buttons toggling styled RAC popovers --- src/frontend/panda.config.ts | 3 +- src/frontend/src/layout/Box.tsx | 2 +- src/frontend/src/primitives/Box.tsx | 9 ++-- src/frontend/src/primitives/Popover.tsx | 68 +++++++++++++++++++++++++ src/frontend/src/primitives/index.ts | 2 + 5 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 src/frontend/src/primitives/Popover.tsx diff --git a/src/frontend/panda.config.ts b/src/frontend/panda.config.ts index e46a9dab..d99ddf52 100644 --- a/src/frontend/panda.config.ts +++ b/src/frontend/panda.config.ts @@ -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}' }, diff --git a/src/frontend/src/layout/Box.tsx b/src/frontend/src/layout/Box.tsx index de70b1c5..48f16be5 100644 --- a/src/frontend/src/layout/Box.tsx +++ b/src/frontend/src/layout/Box.tsx @@ -15,7 +15,7 @@ export const Box = ({ }: BoxProps) => { const { t } = useTranslation() return ( - + {!!title && {title}} {children} {!!withBackButton && ( diff --git a/src/frontend/src/primitives/Box.tsx b/src/frontend/src/primitives/Box.tsx index a59486b0..d774949f 100644 --- a/src/frontend/src/primitives/Box.tsx +++ b/src/frontend/src/primitives/Box.tsx @@ -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', }, diff --git a/src/frontend/src/primitives/Popover.tsx b/src/frontend/src/primitives/Popover.tsx new file mode 100644 index 00000000..0ba738a7 --- /dev/null +++ b/src/frontend/src/primitives/Popover.tsx @@ -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 ( + + {trigger} + + + + + + + + {({ close }) => ( + + {typeof popoverContent === 'function' + ? popoverContent({ close }) + : popoverContent} + + )} + + + + ) +} diff --git a/src/frontend/src/primitives/index.ts b/src/frontend/src/primitives/index.ts index a13a55e1..ff90427d 100644 --- a/src/frontend/src/primitives/index.ts +++ b/src/frontend/src/primitives/index.ts @@ -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'