Skip to content

Commit 10957ea

Browse files
committed
add shadcn tooltip and refactor custom tooltip component
1 parent 78614e4 commit 10957ea

File tree

6 files changed

+90
-39
lines changed

6 files changed

+90
-39
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"@radix-ui/react-radio-group": "^1.2.0",
4444
"@radix-ui/react-slot": "^1.1.0",
4545
"@radix-ui/react-switch": "^1.1.0",
46+
"@radix-ui/react-tooltip": "^1.1.2",
4647
"@radix-ui/react-visually-hidden": "^1.1.0",
4748
"@sentry/nextjs": "^8.19.0",
4849
"@socialgouv/matomo-next": "^1.8.0",

src/components/Tooltip/index.tsx

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import React, { ReactNode, useEffect } from "react"
2-
import {
3-
Popover,
4-
PopoverArrow,
5-
PopoverBody,
6-
PopoverContent,
7-
PopoverProps,
8-
PopoverTrigger,
9-
Portal,
10-
useDisclosure,
11-
} from "@chakra-ui/react"
2+
import { PopoverProps } from "@chakra-ui/react"
123

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

6+
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover"
7+
import {
8+
Tooltip as RootTooltip,
9+
TooltipContent,
10+
TooltipTrigger,
11+
} from "../ui/tooltip"
12+
13+
import { useDisclosure } from "@/hooks/useDisclosure"
14+
1515
export interface TooltipProps extends PopoverProps {
1616
content: ReactNode
1717
children?: ReactNode
@@ -22,7 +22,7 @@ const Tooltip = ({
2222
content,
2323
children,
2424
onBeforeOpen,
25-
...rest
25+
// ...rest
2626
}: TooltipProps) => {
2727
const { isOpen, onOpen, onClose } = useDisclosure()
2828

@@ -57,24 +57,32 @@ const Tooltip = ({
5757
onOpen()
5858
}
5959

60+
const handleOpenChange = (open: boolean) => {
61+
if (open) {
62+
handleOpen()
63+
} else {
64+
onClose()
65+
}
66+
}
67+
68+
// Mobile devices use the Popover component because it supports click/touch
69+
// events
70+
if (isMobile()) {
71+
return (
72+
<Popover open={isOpen} onOpenChange={handleOpenChange}>
73+
<PopoverTrigger>{children}</PopoverTrigger>
74+
<PopoverContent data-testid="tooltip-popover">{content}</PopoverContent>
75+
</Popover>
76+
)
77+
}
78+
79+
// Desktop devices use the Tooltip component because it is desined for hover
80+
// and focus events
6081
return (
61-
<Popover
62-
isOpen={isOpen}
63-
onOpen={handleOpen}
64-
onClose={onClose}
65-
placement="top"
66-
trigger={isMobile() ? "click" : "hover"}
67-
gutter={8}
68-
{...rest}
69-
>
70-
<PopoverTrigger>{children}</PopoverTrigger>
71-
<Portal>
72-
<PopoverContent data-testid="tooltip-popover">
73-
<PopoverArrow />
74-
<PopoverBody>{content}</PopoverBody>
75-
</PopoverContent>
76-
</Portal>
77-
</Popover>
82+
<RootTooltip open={isOpen} onOpenChange={handleOpenChange}>
83+
<TooltipTrigger>{children}</TooltipTrigger>
84+
<TooltipContent data-testid="tooltip-popover">{content}</TooltipContent>
85+
</RootTooltip>
7886
)
7987
}
8088

src/components/ui/popover.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const PopoverContent = React.forwardRef<
1717
align={align}
1818
sideOffset={sideOffset}
1919
className={cn(
20-
"bg-popover text-popover-foreground z-50 w-72 rounded-md border 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",
20+
"text-popover-foreground z-popover w-72 rounded-md border bg-background-highlight 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",
2121
className
2222
)}
2323
{...props}

src/components/ui/tooltip.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import * as React from "react"
2+
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
3+
4+
import { cn } from "@/lib/utils/cn"
5+
6+
const TooltipProvider = TooltipPrimitive.Provider
7+
8+
const Tooltip = TooltipPrimitive.Root
9+
10+
const TooltipTrigger = TooltipPrimitive.Trigger
11+
12+
const TooltipContent = React.forwardRef<
13+
React.ElementRef<typeof TooltipPrimitive.Content>,
14+
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
15+
>(({ className, sideOffset = 4, ...props }, ref) => (
16+
<TooltipPrimitive.Content
17+
ref={ref}
18+
sideOffset={sideOffset}
19+
className={cn(
20+
"z-tooltip max-w-[320px] overflow-hidden rounded-md border 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",
21+
className
22+
)}
23+
{...props}
24+
/>
25+
))
26+
TooltipContent.displayName = TooltipPrimitive.Content.displayName
27+
28+
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger }

src/pages/_app.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { init } from "@socialgouv/matomo-next"
55
import { AppPropsWithLayout } from "@/lib/types"
66

77
import ThemeProvider from "@/components/ThemeProvider"
8+
import { TooltipProvider } from "@/components/ui/tooltip"
89

910
import "@/styles/global.css"
1011
import "@/styles/fonts.css"
@@ -26,17 +27,17 @@ const App = ({ Component, pageProps }: AppPropsWithLayout) => {
2627
const getLayout = Component.getLayout ?? ((page) => page)
2728

2829
return (
29-
<>
30-
<ThemeProvider>
30+
<ThemeProvider>
31+
<TooltipProvider>
3132
<BaseLayout
3233
contentIsOutdated={!!pageProps.frontmatter?.isOutdated}
3334
contentNotTranslated={pageProps.contentNotTranslated}
3435
lastDeployLocaleTimestamp={pageProps.lastDeployLocaleTimestamp}
3536
>
3637
{getLayout(<Component {...pageProps} />)}
3738
</BaseLayout>
38-
</ThemeProvider>
39-
</>
39+
</TooltipProvider>
40+
</ThemeProvider>
4041
)
4142
}
4243

yarn.lock

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4493,6 +4493,24 @@
44934493
"@radix-ui/react-use-previous" "1.1.0"
44944494
"@radix-ui/react-use-size" "1.1.0"
44954495

4496+
"@radix-ui/react-tooltip@^1.1.2":
4497+
version "1.1.2"
4498+
resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-1.1.2.tgz#c42db2ffd7dcc6ff3d65407c8cb70490288f518d"
4499+
integrity sha512-9XRsLwe6Yb9B/tlnYCPVUd/TFS4J7HuOZW345DCeC6vKIxQGMZdx21RK4VoZauPD5frgkXTYVS5y90L+3YBn4w==
4500+
dependencies:
4501+
"@radix-ui/primitive" "1.1.0"
4502+
"@radix-ui/react-compose-refs" "1.1.0"
4503+
"@radix-ui/react-context" "1.1.0"
4504+
"@radix-ui/react-dismissable-layer" "1.1.0"
4505+
"@radix-ui/react-id" "1.1.0"
4506+
"@radix-ui/react-popper" "1.2.0"
4507+
"@radix-ui/react-portal" "1.1.1"
4508+
"@radix-ui/react-presence" "1.1.0"
4509+
"@radix-ui/react-primitive" "2.0.0"
4510+
"@radix-ui/react-slot" "1.1.0"
4511+
"@radix-ui/react-use-controllable-state" "1.1.0"
4512+
"@radix-ui/react-visually-hidden" "1.1.0"
4513+
44964514
"@radix-ui/[email protected]":
44974515
version "1.0.1"
44984516
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz#f4bb1f27f2023c984e6534317ebc411fc181107a"
@@ -13068,7 +13086,7 @@ prelude-ls@^1.2.1:
1306813086
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
1306913087
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
1307013088

13071-
"prettier-fallback@npm:prettier@^3":
13089+
"prettier-fallback@npm:prettier@^3", prettier@^3.1.1:
1307213090
version "3.3.2"
1307313091
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.2.tgz#03ff86dc7c835f2d2559ee76876a3914cec4a90a"
1307413092
integrity sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==
@@ -13083,11 +13101,6 @@ prettier@^2.0.5, prettier@^2.8.8:
1308313101
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da"
1308413102
integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==
1308513103

13086-
prettier@^3.1.1:
13087-
version "3.3.2"
13088-
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.2.tgz#03ff86dc7c835f2d2559ee76876a3914cec4a90a"
13089-
integrity sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==
13090-
1309113104
prettier@^3.3.3:
1309213105
version "3.3.3"
1309313106
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105"

0 commit comments

Comments
 (0)