|
| 1 | +import { |
| 2 | + Arrow, |
| 3 | + Content, |
| 4 | + Portal, |
| 5 | + Root, |
| 6 | + Trigger, |
| 7 | +} from '@radix-ui/react-hover-card' |
| 8 | +import React, { ComponentProps, ElementRef, FC, forwardRef } from 'react' |
| 9 | +import type { CSSProps } from '../../stitches.config' |
| 10 | +import { styled } from '../../stitches.config' |
| 11 | +import { ConditionalWrapper } from '../../utils' |
| 12 | +import { overlayAnimationStyles } from '../Overlay' |
| 13 | +import { paperStyles } from '../Paper' |
| 14 | + |
| 15 | +const StyledContent = styled( |
| 16 | + Content, |
| 17 | + paperStyles, |
| 18 | + { |
| 19 | + borderRadius: '$default', |
| 20 | + |
| 21 | + width: '$11', |
| 22 | + |
| 23 | + '@md': { width: '$12' }, |
| 24 | + '@lg': { width: '$13' }, |
| 25 | + |
| 26 | + display: 'flex', |
| 27 | + flexDirection: 'column', |
| 28 | + gap: '$2', |
| 29 | + |
| 30 | + '&::before': { |
| 31 | + boxShadow: 'none', |
| 32 | + }, |
| 33 | + filter: |
| 34 | + 'drop-shadow(0px 3px 2.5px rgba(0,0,0,0.2)) drop-shadow(0px 6px 5px rgba(0,0,0,0.14)) drop-shadow(0px 1px 9px rgba(0,0,0,0.12))', |
| 35 | + }, |
| 36 | + overlayAnimationStyles |
| 37 | +) |
| 38 | + |
| 39 | +const StyledArrow = styled(Arrow, { |
| 40 | + fill: '$paper', |
| 41 | +}) |
| 42 | + |
| 43 | +type HoverCardContentProps = CSSProps & |
| 44 | + ComponentProps<typeof Content> & { |
| 45 | + /** By default, portals your content parts into the body, set false to add at dom location. */ |
| 46 | + portalled?: boolean |
| 47 | + /** Specify a container element to portal the content into. */ |
| 48 | + container?: ComponentProps<typeof Portal>['container'] |
| 49 | + } |
| 50 | + |
| 51 | +export const HoverCardContent = forwardRef< |
| 52 | + ElementRef<typeof StyledContent>, |
| 53 | + HoverCardContentProps |
| 54 | +>(({ portalled = true, container, children, ...props }, forwardedRef) => ( |
| 55 | + <ConditionalWrapper |
| 56 | + condition={portalled} |
| 57 | + wrapper={(child) => <Portal container={container}>{child}</Portal>} |
| 58 | + > |
| 59 | + <StyledContent {...props} ref={forwardedRef}> |
| 60 | + <StyledArrow offset={-1} /> |
| 61 | + {children} |
| 62 | + </StyledContent> |
| 63 | + </ConditionalWrapper> |
| 64 | +)) |
| 65 | +HoverCardContent.toString = () => `.${StyledContent.className}` |
| 66 | + |
| 67 | +const HOVER_CARD_TRIGGER_CLASS_NAME = 'c-hover-card-trigger' |
| 68 | + |
| 69 | +export const HoverCardTrigger = forwardRef< |
| 70 | + ElementRef<typeof Trigger>, |
| 71 | + Omit<ComponentProps<typeof Trigger>, 'asChild'> |
| 72 | +>(({ children, ...props }, forwardedRef) => ( |
| 73 | + <Trigger |
| 74 | + className={HOVER_CARD_TRIGGER_CLASS_NAME} |
| 75 | + asChild |
| 76 | + {...props} |
| 77 | + ref={forwardedRef} |
| 78 | + > |
| 79 | + {children} |
| 80 | + </Trigger> |
| 81 | +)) |
| 82 | +HoverCardTrigger.toString = () => `.${HOVER_CARD_TRIGGER_CLASS_NAME}` |
| 83 | + |
| 84 | +/** |
| 85 | + * |
| 86 | + * HoverCards display extra information when users hover over a link. |
| 87 | + * Intended for sighted users to preview or see additional information. |
| 88 | + * |
| 89 | + * Built using [Radix HoverCard](https://radix-ui.com/primitives/docs/components/hover-card) |
| 90 | + */ |
| 91 | +export const HoverCard: FC<React.ComponentProps<typeof Root>> = Root |
0 commit comments