Skip to content

Commit

Permalink
Merge branch 'dev' into pr/13700
Browse files Browse the repository at this point in the history
  • Loading branch information
wackerow committed Aug 26, 2024
2 parents f7a8a47 + 9e4a8c9 commit 15d77f6
Show file tree
Hide file tree
Showing 14 changed files with 772 additions and 715 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"@radix-ui/react-radio-group": "^1.2.0",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-switch": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.2",
"@radix-ui/react-visually-hidden": "^1.1.0",
"@sentry/nextjs": "^8.19.0",
"@socialgouv/matomo-next": "^1.8.0",
Expand All @@ -63,7 +64,6 @@
"lodash.merge": "^4.6.2",
"lodash.shuffle": "^4.2.0",
"lodash.union": "^4.6.0",
"lucide-react": "^0.400.0",
"next": "^14.2.3",
"next-i18next": "^14.0.3",
"next-mdx-remote": "^3.0.8",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Center } from "@chakra-ui/react"
import { Meta, StoryObj } from "@storybook/react"

import { TooltipProvider } from "@/components/ui/tooltip"

import GlossaryTooltipComponent from "."

const meta = {
Expand All @@ -13,7 +15,9 @@ const meta = {
decorators: [
(Story) => (
<Center boxSize="md">
<Story />
<TooltipProvider>
<Story />
</TooltipProvider>
</Center>
),
],
Expand All @@ -28,6 +32,6 @@ export const Basic: Story = {}
// for chromatic story snapshot showing the rendered popover
export const OnOpen: Story = {
args: {
isOpen: true,
open: true,
},
}
31 changes: 10 additions & 21 deletions src/components/Glossary/GlossaryTooltip/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import React, { ReactNode } from "react"
import { useRouter } from "next/router"
import { Box, Text, VStack } from "@chakra-ui/react"

import Heading from "@/components/Heading"
import InlineLink from "@/components/Link"
import Tooltip, { type TooltipProps } from "@/components/Tooltip"
import Translation from "@/components/Translation"
Expand All @@ -23,36 +21,36 @@ const GlossaryTooltip = ({
const { asPath } = useRouter()

return (
<Box as="span" display="inline-block">
<span className="inline-block">
<Tooltip
{...props}
content={
<VStack spacing={2} align="stretch" textAlign="start">
<Heading as="h6">
<div className="flex flex-col items-stretch gap-2 text-start">
<h6>
<Translation
id={termKey + "-term"}
options={{ ns: "glossary-tooltip" }}
// Override the default `a` tag transformation to avoid circular
// dependency issues
transform={{ a: InlineLink }}
/>
</Heading>
</h6>
{/**
* `as="span"` prevents hydration warnings for strings that contain
* elements that cannot be nested inside `p` tags, like `ul` tags
* (found in some Glossary definition).
* TODO: Develop a better solution to handle this case.
*/}
<Text as="span">
<span>
<Translation
id={termKey + "-definition"}
options={{ ns: "glossary-tooltip" }}
// Override the default `a` tag transformation to avoid circular
// dependency issues
transform={{ a: InlineLink }}
/>
</Text>
</VStack>
</span>
</div>
}
onBeforeOpen={() => {
trackCustomEvent({
Expand All @@ -62,20 +60,11 @@ const GlossaryTooltip = ({
})
}}
>
<Text
as="u"
textDecorationStyle="dotted"
textUnderlineOffset="3px"
_hover={{
textDecorationColor: "primary.hover",
color: "primary.hover",
}}
cursor="help"
>
<u className="cursor-help decoration-dotted underline-offset-3 hover:text-primary-hover hover:decoration-primary-hover">
{children}
</Text>
</u>
</Tooltip>
</Box>
</span>
)
}

Expand Down
7 changes: 5 additions & 2 deletions src/components/Tooltip/Tooltip.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Meta, StoryObj } from "@storybook/react"

import InlineLink from "../Link"
import Translation from "../Translation"
import { TooltipProvider } from "../ui/tooltip"

// TODO: remove `index` when we delete the old tooltip
import TooltipComponent from "./index"
Expand Down Expand Up @@ -46,7 +47,9 @@ const meta = {
decorators: [
(Story) => (
<Center boxSize="md">
<Story />
<TooltipProvider>
<Story />
</TooltipProvider>
</Center>
),
],
Expand All @@ -61,6 +64,6 @@ export const Basic: Story = {}
// for chromatic story snapshot showing the rendered popover
export const OnOpen: Story = {
args: {
isOpen: true,
open: true,
},
}
76 changes: 46 additions & 30 deletions src/components/Tooltip/index.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import React, { ReactNode, useEffect } from "react"
import {
Popover,
PopoverArrow,
PopoverBody,
PopoverContent,
PopoverProps,
PopoverTrigger,
Portal,
useDisclosure,
} from "@chakra-ui/react"
import React, { ComponentProps, ReactNode, useEffect } from "react"

import { isMobile } from "@/lib/utils/isMobile"

export interface TooltipProps extends PopoverProps {
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover"
import {
Tooltip as Tooltipcomponent,
TooltipContent,
TooltipTrigger,
} from "../ui/tooltip"

import { useDisclosure } from "@/hooks/useDisclosure"
import { useIsClient } from "@/hooks/useIsClient"

export type TooltipProps = ComponentProps<typeof Popover> & {
content: ReactNode
children?: ReactNode
onBeforeOpen?: () => void
Expand All @@ -22,9 +22,10 @@ const Tooltip = ({
content,
children,
onBeforeOpen,
...rest
...props
}: TooltipProps) => {
const { isOpen, onOpen, onClose } = useDisclosure()
const isClient = useIsClient()

// Close the popover when the user scrolls.
// This is useful for mobile devices where the popover is open by clicking the
Expand Down Expand Up @@ -57,24 +58,39 @@ const Tooltip = ({
onOpen()
}

const handleOpenChange = (open: boolean) => {
if (open) {
handleOpen()
} else {
onClose()
}
}

// Avoid rendering on the server since the user can't interact with it and we
// need to use different components depending on the device
if (!isClient) {
return null
}

// Use Popover on mobile devices since the user can't hover
const Component = isMobile() ? Popover : Tooltipcomponent
const Trigger = isMobile() ? PopoverTrigger : TooltipTrigger
const Content = isMobile() ? PopoverContent : TooltipContent

return (
<Popover
isOpen={isOpen}
onOpen={handleOpen}
onClose={onClose}
placement="top"
trigger={isMobile() ? "click" : "hover"}
gutter={8}
{...rest}
>
<PopoverTrigger>{children}</PopoverTrigger>
<Portal>
<PopoverContent data-testid="tooltip-popover">
<PopoverArrow />
<PopoverBody>{content}</PopoverBody>
</PopoverContent>
</Portal>
</Popover>
<Component open={isOpen} onOpenChange={handleOpenChange} {...props}>
<Trigger className="focus-visible:rounded-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-hover">
{children}
</Trigger>
<Content
side="top"
sideOffset={2}
className="w-80 px-5 text-sm"
data-testid="tooltip-popover"
>
{content}
</Content>
</Component>
)
}

Expand Down
33 changes: 26 additions & 7 deletions src/components/ui/buttons/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,21 +108,40 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
)
Button.displayName = "Button"

type ButtonLinkProps = Omit<LinkProps, "onClick"> & {
buttonProps?: ButtonProps
customEventOptions?: MatomoEventOptions
}
type ButtonLinkProps = Omit<LinkProps, "onClick"> &
Pick<ButtonProps, "size" | "variant" | "isSecondary"> & {
buttonProps?: Omit<ButtonProps, "size" | "variant">
customEventOptions?: MatomoEventOptions
}

const ButtonLink = React.forwardRef<HTMLAnchorElement, ButtonLinkProps>(
({ buttonProps, customEventOptions, children, ...linkProps }, ref) => {
(
{
size,
variant,
isSecondary,
buttonProps,
customEventOptions,
children,
className,
...linkProps
},
ref
) => {
const handleClick = () => {
customEventOptions && trackCustomEvent(customEventOptions)
}
return (
<Button asChild {...buttonProps}>
<Button
asChild
size={size}
variant={variant}
isSecondary={isSecondary}
{...buttonProps}
>
<BaseLink
ref={ref}
className="no-underline hover:no-underline"
className={cn("no-underline hover:no-underline", className)}
activeClassName=""
{...linkProps}
onClick={handleClick}
Expand Down
4 changes: 2 additions & 2 deletions src/components/ui/dialog.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from "react"
import { X } from "lucide-react"
import { MdClose } from "react-icons/md"
import * as DialogPrimitive from "@radix-ui/react-dialog"

import { cn } from "@/lib/utils/cn"
Expand Down Expand Up @@ -43,7 +43,7 @@ const DialogContent = React.forwardRef<
>
{children}
<DialogPrimitive.Close className="focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none">
<X className="h-4 w-4" />
<MdClose className="h-4 w-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
</DialogPrimitive.Content>
Expand Down
36 changes: 22 additions & 14 deletions src/components/ui/popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,28 @@ const PopoverTrigger = PopoverPrimitive.Trigger
const PopoverContent = React.forwardRef<
React.ElementRef<typeof PopoverPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
ref={ref}
align={align}
sideOffset={sideOffset}
className={cn(
"text-popover-foreground z-popover w-72 rounded-md border bg-background p-4 shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
)}
{...props}
/>
</PopoverPrimitive.Portal>
))
>(
(
{ className, children, align = "center", sideOffset = 4, ...props },
ref
) => (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
ref={ref}
align={align}
sideOffset={sideOffset}
className={cn(
"text-popover-foreground z-popover w-72 rounded border border-background-highlight bg-background-highlight p-4 shadow-lg outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
)}
{...props}
>
{children}
<PopoverPrimitive.Arrow className="z-popover fill-background-highlight" />
</PopoverPrimitive.Content>
</PopoverPrimitive.Portal>
)
)
PopoverContent.displayName = PopoverPrimitive.Content.displayName

const PopoverClose = PopoverPrimitive.Close
Expand Down
31 changes: 31 additions & 0 deletions src/components/ui/tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as React from "react"
import * as TooltipPrimitive from "@radix-ui/react-tooltip"

import { cn } from "@/lib/utils/cn"

const TooltipProvider = TooltipPrimitive.Provider

const Tooltip = TooltipPrimitive.Root

const TooltipTrigger = TooltipPrimitive.Trigger

const TooltipContent = React.forwardRef<
React.ElementRef<typeof TooltipPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
>(({ children, className, sideOffset = 4, ...props }, ref) => (
<TooltipPrimitive.Content
ref={ref}
sideOffset={sideOffset}
className={cn(
"z-popover overflow-hidden rounded-md border border-background-highlight bg-background-highlight p-4 text-sm text-body shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
)}
{...props}
>
{children}
<TooltipPrimitive.Arrow className="z-popover fill-background-highlight" />
</TooltipPrimitive.Content>
))
TooltipContent.displayName = TooltipPrimitive.Content.displayName

export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger }
Loading

0 comments on commit 15d77f6

Please sign in to comment.