mirror of
https://github.com/FranP-code/classify_saved_videos_yt.git
synced 2025-10-13 00:32:25 +00:00
Update tooltip implementation and add TooltipContent and TooltipTrigger components
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/mdx": "^4.3.0",
|
"@astrojs/mdx": "^4.3.0",
|
||||||
"@astrojs/react": "^4.3.0",
|
"@astrojs/react": "^4.3.0",
|
||||||
|
"@base-ui-components/react": "1.0.0-beta.1",
|
||||||
"@radix-ui/react-slot": "^1.2.3",
|
"@radix-ui/react-slot": "^1.2.3",
|
||||||
"@tailwindcss/vite": "^4.1.3",
|
"@tailwindcss/vite": "^4.1.3",
|
||||||
"@tanstack/react-virtual": "^3.13.12",
|
"@tanstack/react-virtual": "^3.13.12",
|
||||||
|
|||||||
84
web/pnpm-lock.yaml
generated
84
web/pnpm-lock.yaml
generated
@@ -14,6 +14,9 @@ importers:
|
|||||||
'@astrojs/react':
|
'@astrojs/react':
|
||||||
specifier: ^4.3.0
|
specifier: ^4.3.0
|
||||||
version: 4.3.0(@types/node@24.0.13)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(jiti@2.4.2)(lightningcss@1.30.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
version: 4.3.0(@types/node@24.0.13)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(jiti@2.4.2)(lightningcss@1.30.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
|
'@base-ui-components/react':
|
||||||
|
specifier: 1.0.0-beta.1
|
||||||
|
version: 1.0.0-beta.1(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
'@radix-ui/react-slot':
|
'@radix-ui/react-slot':
|
||||||
specifier: ^1.2.3
|
specifier: ^1.2.3
|
||||||
version: 1.2.3(@types/react@19.1.8)(react@19.1.0)
|
version: 1.2.3(@types/react@19.1.8)(react@19.1.0)
|
||||||
@@ -182,6 +185,10 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@babel/core': ^7.0.0-0
|
'@babel/core': ^7.0.0-0
|
||||||
|
|
||||||
|
'@babel/runtime@7.27.6':
|
||||||
|
resolution: {integrity: sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
'@babel/template@7.27.2':
|
'@babel/template@7.27.2':
|
||||||
resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
|
resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -194,6 +201,17 @@ packages:
|
|||||||
resolution: {integrity: sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==}
|
resolution: {integrity: sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
|
'@base-ui-components/react@1.0.0-beta.1':
|
||||||
|
resolution: {integrity: sha512-7zmGiz4/+HKnv99lWftItoSMqnj2PdSvt2krh0/GP+Rj0xK0NMnFI/gIVvP7CB2G+k0JPUrRWXjXa3y08oiakg==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': ^17 || ^18 || ^19
|
||||||
|
react: ^17 || ^18 || ^19
|
||||||
|
react-dom: ^17 || ^18 || ^19
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@capsizecss/unpack@2.4.0':
|
'@capsizecss/unpack@2.4.0':
|
||||||
resolution: {integrity: sha512-GrSU71meACqcmIUxPYOJvGKF0yryjN/L1aCuE9DViCTJI7bfkjgYDPD1zbNDcINJwSSP6UaBZY9GAbYDO7re0Q==}
|
resolution: {integrity: sha512-GrSU71meACqcmIUxPYOJvGKF0yryjN/L1aCuE9DViCTJI7bfkjgYDPD1zbNDcINJwSSP6UaBZY9GAbYDO7re0Q==}
|
||||||
|
|
||||||
@@ -356,6 +374,21 @@ packages:
|
|||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
|
'@floating-ui/core@1.7.2':
|
||||||
|
resolution: {integrity: sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw==}
|
||||||
|
|
||||||
|
'@floating-ui/dom@1.7.2':
|
||||||
|
resolution: {integrity: sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA==}
|
||||||
|
|
||||||
|
'@floating-ui/react-dom@2.1.4':
|
||||||
|
resolution: {integrity: sha512-JbbpPhp38UmXDDAu60RJmbeme37Jbgsm7NrHGgzYYFKmblzRUh6Pa641dII6LsjwF4XlScDrde2UAzDo/b9KPw==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=16.8.0'
|
||||||
|
react-dom: '>=16.8.0'
|
||||||
|
|
||||||
|
'@floating-ui/utils@0.2.10':
|
||||||
|
resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==}
|
||||||
|
|
||||||
'@img/sharp-darwin-arm64@0.33.5':
|
'@img/sharp-darwin-arm64@0.33.5':
|
||||||
resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==}
|
resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==}
|
||||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||||
@@ -1729,6 +1762,9 @@ packages:
|
|||||||
remark-stringify@11.0.0:
|
remark-stringify@11.0.0:
|
||||||
resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
|
resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
|
||||||
|
|
||||||
|
reselect@5.1.1:
|
||||||
|
resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==}
|
||||||
|
|
||||||
restructure@3.0.2:
|
restructure@3.0.2:
|
||||||
resolution: {integrity: sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==}
|
resolution: {integrity: sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==}
|
||||||
|
|
||||||
@@ -1814,6 +1850,9 @@ packages:
|
|||||||
style-to-object@1.0.9:
|
style-to-object@1.0.9:
|
||||||
resolution: {integrity: sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==}
|
resolution: {integrity: sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==}
|
||||||
|
|
||||||
|
tabbable@6.2.0:
|
||||||
|
resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==}
|
||||||
|
|
||||||
tailwind-merge@3.3.1:
|
tailwind-merge@3.3.1:
|
||||||
resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==}
|
resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==}
|
||||||
|
|
||||||
@@ -1991,6 +2030,11 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
browserslist: '>= 4.21.0'
|
browserslist: '>= 4.21.0'
|
||||||
|
|
||||||
|
use-sync-external-store@1.5.0:
|
||||||
|
resolution: {integrity: sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||||
|
|
||||||
vfile-location@5.0.3:
|
vfile-location@5.0.3:
|
||||||
resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==}
|
resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==}
|
||||||
|
|
||||||
@@ -2296,6 +2340,8 @@ snapshots:
|
|||||||
'@babel/core': 7.28.0
|
'@babel/core': 7.28.0
|
||||||
'@babel/helper-plugin-utils': 7.27.1
|
'@babel/helper-plugin-utils': 7.27.1
|
||||||
|
|
||||||
|
'@babel/runtime@7.27.6': {}
|
||||||
|
|
||||||
'@babel/template@7.27.2':
|
'@babel/template@7.27.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/code-frame': 7.27.1
|
'@babel/code-frame': 7.27.1
|
||||||
@@ -2319,6 +2365,19 @@ snapshots:
|
|||||||
'@babel/helper-string-parser': 7.27.1
|
'@babel/helper-string-parser': 7.27.1
|
||||||
'@babel/helper-validator-identifier': 7.27.1
|
'@babel/helper-validator-identifier': 7.27.1
|
||||||
|
|
||||||
|
'@base-ui-components/react@1.0.0-beta.1(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.27.6
|
||||||
|
'@floating-ui/react-dom': 2.1.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
|
'@floating-ui/utils': 0.2.10
|
||||||
|
react: 19.1.0
|
||||||
|
react-dom: 19.1.0(react@19.1.0)
|
||||||
|
reselect: 5.1.1
|
||||||
|
tabbable: 6.2.0
|
||||||
|
use-sync-external-store: 1.5.0(react@19.1.0)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.1.8
|
||||||
|
|
||||||
'@capsizecss/unpack@2.4.0':
|
'@capsizecss/unpack@2.4.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
blob-to-buffer: 1.2.9
|
blob-to-buffer: 1.2.9
|
||||||
@@ -2410,6 +2469,23 @@ snapshots:
|
|||||||
'@esbuild/win32-x64@0.25.6':
|
'@esbuild/win32-x64@0.25.6':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@floating-ui/core@1.7.2':
|
||||||
|
dependencies:
|
||||||
|
'@floating-ui/utils': 0.2.10
|
||||||
|
|
||||||
|
'@floating-ui/dom@1.7.2':
|
||||||
|
dependencies:
|
||||||
|
'@floating-ui/core': 1.7.2
|
||||||
|
'@floating-ui/utils': 0.2.10
|
||||||
|
|
||||||
|
'@floating-ui/react-dom@2.1.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||||
|
dependencies:
|
||||||
|
'@floating-ui/dom': 1.7.2
|
||||||
|
react: 19.1.0
|
||||||
|
react-dom: 19.1.0(react@19.1.0)
|
||||||
|
|
||||||
|
'@floating-ui/utils@0.2.10': {}
|
||||||
|
|
||||||
'@img/sharp-darwin-arm64@0.33.5':
|
'@img/sharp-darwin-arm64@0.33.5':
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@img/sharp-libvips-darwin-arm64': 1.0.4
|
'@img/sharp-libvips-darwin-arm64': 1.0.4
|
||||||
@@ -4190,6 +4266,8 @@ snapshots:
|
|||||||
mdast-util-to-markdown: 2.1.2
|
mdast-util-to-markdown: 2.1.2
|
||||||
unified: 11.0.5
|
unified: 11.0.5
|
||||||
|
|
||||||
|
reselect@5.1.1: {}
|
||||||
|
|
||||||
restructure@3.0.2: {}
|
restructure@3.0.2: {}
|
||||||
|
|
||||||
retext-latin@4.0.0:
|
retext-latin@4.0.0:
|
||||||
@@ -4335,6 +4413,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
inline-style-parser: 0.2.4
|
inline-style-parser: 0.2.4
|
||||||
|
|
||||||
|
tabbable@6.2.0: {}
|
||||||
|
|
||||||
tailwind-merge@3.3.1: {}
|
tailwind-merge@3.3.1: {}
|
||||||
|
|
||||||
tailwindcss@4.1.11: {}
|
tailwindcss@4.1.11: {}
|
||||||
@@ -4474,6 +4554,10 @@ snapshots:
|
|||||||
escalade: 3.2.0
|
escalade: 3.2.0
|
||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
|
|
||||||
|
use-sync-external-store@1.5.0(react@19.1.0):
|
||||||
|
dependencies:
|
||||||
|
react: 19.1.0
|
||||||
|
|
||||||
vfile-location@5.0.3:
|
vfile-location@5.0.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/unist': 3.0.3
|
'@types/unist': 3.0.3
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import type { VideoData } from '../types/video';
|
|||||||
import { formatDuration, formatDate } from '../utils/csvParser';
|
import { formatDuration, formatDate } from '../utils/csvParser';
|
||||||
import { Badge } from './ui/badge';
|
import { Badge } from './ui/badge';
|
||||||
import { Button } from './ui/button';
|
import { Button } from './ui/button';
|
||||||
import { Tooltip } from './ui/tooltip';
|
import { Tooltip,TooltipContent, TooltipTrigger } from './ui/tooltip';
|
||||||
|
|
||||||
interface VirtualTableProps {
|
interface VirtualTableProps {
|
||||||
data: VideoData[];
|
data: VideoData[];
|
||||||
@@ -74,24 +74,32 @@ export function VirtualTable({ data }: VirtualTableProps) {
|
|||||||
<div className="grid grid-cols-12 gap-3 px-4 py-3 items-center min-h-[80px]">
|
<div className="grid grid-cols-12 gap-3 px-4 py-3 items-center min-h-[80px]">
|
||||||
{/* Video Info */}
|
{/* Video Info */}
|
||||||
<div className="col-span-3 space-y-2 min-w-0">
|
<div className="col-span-3 space-y-2 min-w-0">
|
||||||
<Tooltip content={video.video_title}>
|
<Tooltip>
|
||||||
<h3 className="font-medium text-sm leading-tight truncate">
|
<TooltipContent>
|
||||||
|
{video.video_title}
|
||||||
|
</TooltipContent>
|
||||||
|
<TooltipTrigger>
|
||||||
|
<h3 className="text-start font-medium text-sm leading-tight truncate sm:w-[150px] lg:w-[200px] xl:w-[250px] 2xl:w-[300px]">
|
||||||
{video.video_title}
|
{video.video_title}
|
||||||
</h3>
|
</h3>
|
||||||
|
</TooltipTrigger>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<div className="flex flex-wrap gap-1">
|
<div className="flex flex-wrap gap-1">
|
||||||
{video.detailed_subtags.split(',').slice(0, 2).map((tag, i) => (
|
{video.detailed_subtags.split(',').slice(0, 2).map((tag, i) => (
|
||||||
<Tooltip key={i} content={tag.trim()}>
|
|
||||||
<Badge variant="secondary" className="text-xs max-w-20 truncate">
|
<Badge variant="secondary" className="text-xs max-w-20 truncate">
|
||||||
{tag.trim()}
|
{tag.trim()}
|
||||||
</Badge>
|
</Badge>
|
||||||
</Tooltip>
|
|
||||||
))}
|
))}
|
||||||
{video.detailed_subtags.split(',').length > 2 && (
|
{video.detailed_subtags.split(',').length > 2 && (
|
||||||
<Tooltip content={`+${video.detailed_subtags.split(',').length - 2} more tags`}>
|
<Tooltip>
|
||||||
|
<TooltipContent>
|
||||||
|
{video.detailed_subtags.split(',').slice(2).join(', ')}
|
||||||
|
</TooltipContent>
|
||||||
|
<TooltipTrigger>
|
||||||
<Badge variant="outline" className="text-xs">
|
<Badge variant="outline" className="text-xs">
|
||||||
+{video.detailed_subtags.split(',').length - 2}
|
+{video.detailed_subtags.split(',').length - 2}
|
||||||
</Badge>
|
</Badge>
|
||||||
|
</TooltipTrigger>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,36 +1,103 @@
|
|||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
import { Tooltip as BaseTooltip } from "@base-ui-components/react/tooltip"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
interface TooltipProps {
|
function TooltipProvider({
|
||||||
content: string
|
delay = 0,
|
||||||
children: React.ReactNode
|
closeDelay = 0,
|
||||||
className?: string
|
...props
|
||||||
|
}: React.ComponentProps<typeof BaseTooltip.Provider>) {
|
||||||
|
return (
|
||||||
|
<BaseTooltip.Provider
|
||||||
|
data-slot="tooltip-provider"
|
||||||
|
delay={delay}
|
||||||
|
closeDelay={closeDelay}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Tooltip({ content, children, className }: TooltipProps) {
|
function Tooltip({ ...props }: React.ComponentProps<typeof BaseTooltip.Root>) {
|
||||||
const [isVisible, setIsVisible] = React.useState(false)
|
return (
|
||||||
|
<TooltipProvider>
|
||||||
|
<BaseTooltip.Root data-slot="tooltip" {...props} />
|
||||||
|
</TooltipProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
function TooltipTrigger({
|
||||||
<div className="relative inline-block">
|
...props
|
||||||
<div
|
}: React.ComponentProps<typeof BaseTooltip.Trigger>) {
|
||||||
onMouseEnter={() => setIsVisible(true)}
|
return <BaseTooltip.Trigger data-slot="tooltip-trigger" {...props} />
|
||||||
onMouseLeave={() => setIsVisible(false)}
|
}
|
||||||
className="cursor-help"
|
|
||||||
>
|
function TooltipPortal({
|
||||||
{children}
|
...props
|
||||||
</div>
|
}: React.ComponentProps<typeof BaseTooltip.Portal>) {
|
||||||
{isVisible && (
|
return <BaseTooltip.Portal data-slot="tooltip-portal" {...props} />
|
||||||
<div className={cn(
|
}
|
||||||
"absolute z-50 px-3 py-2 text-sm text-white bg-gray-900 dark:bg-gray-700 rounded-lg shadow-lg",
|
|
||||||
"bottom-full left-1/2 transform -translate-x-1/2 mb-2",
|
function TooltipPositioner({
|
||||||
"max-w-xs break-words",
|
...props
|
||||||
"before:content-[''] before:absolute before:top-full before:left-1/2 before:transform before:-translate-x-1/2",
|
}: React.ComponentProps<typeof BaseTooltip.Positioner>) {
|
||||||
"before:border-4 before:border-transparent before:border-t-gray-900 dark:before:border-t-gray-700",
|
return <BaseTooltip.Positioner data-slot="tooltip-positioner" {...props} />
|
||||||
className
|
}
|
||||||
)}>
|
|
||||||
{content}
|
function TooltipArrow({
|
||||||
</div>
|
...props
|
||||||
)}
|
}: React.ComponentProps<typeof BaseTooltip.Arrow>) {
|
||||||
</div>
|
return <BaseTooltip.Arrow data-slot="tooltip-arrow" {...props} />
|
||||||
)
|
}
|
||||||
}
|
|
||||||
|
function TooltipContent({
|
||||||
|
className,
|
||||||
|
align = "center",
|
||||||
|
sideOffset = 8,
|
||||||
|
side = "top",
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof BaseTooltip.Popup> & {
|
||||||
|
align?: BaseTooltip.Positioner.Props["align"]
|
||||||
|
side?: BaseTooltip.Positioner.Props["side"]
|
||||||
|
sideOffset?: BaseTooltip.Positioner.Props["sideOffset"]
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<TooltipPortal>
|
||||||
|
<TooltipPositioner sideOffset={sideOffset} align={align} side={side}>
|
||||||
|
<BaseTooltip.Popup
|
||||||
|
data-slot="tooltip-content"
|
||||||
|
className={cn(
|
||||||
|
"bg-popover text-popover-foreground outline-border z-50 w-fit origin-[var(--transform-origin)] rounded-md px-3 py-1.5 text-xs text-balance shadow-sm outline -outline-offset-1 transition-[transform,scale,opacity] data-[ending-style]:scale-95 data-[ending-style]:opacity-0 data-[starting-style]:scale-95 data-[starting-style]:opacity-0",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<TooltipArrow className="data-[side=bottom]:top-[-8px] data-[side=left]:right-[-13px] data-[side=left]:rotate-90 data-[side=right]:left-[-13px] data-[side=right]:-rotate-90 data-[side=top]:bottom-[-8px] data-[side=top]:rotate-180">
|
||||||
|
<svg width="20" height="10" viewBox="0 0 20 10" fill="none">
|
||||||
|
<path
|
||||||
|
d="M9.66437 2.60207L4.80758 6.97318C4.07308 7.63423 3.11989 8 2.13172 8H0V9H20V8H18.5349C17.5468 8 16.5936 7.63423 15.8591 6.97318L11.0023 2.60207C10.622 2.2598 10.0447 2.25979 9.66437 2.60207Z"
|
||||||
|
className="fill-popover"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M10.3333 3.34539L5.47654 7.71648C4.55842 8.54279 3.36693 9 2.13172 9H0V8H2.13172C3.11989 8 4.07308 7.63423 4.80758 6.97318L9.66437 2.60207C10.0447 2.25979 10.622 2.2598 11.0023 2.60207L15.8591 6.97318C16.5936 7.63423 17.5468 8 18.5349 8H20V9H18.5349C17.2998 9 16.1083 8.54278 15.1901 7.71648L10.3333 3.34539Z"
|
||||||
|
className="fill-border"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</TooltipArrow>
|
||||||
|
</BaseTooltip.Popup>
|
||||||
|
</TooltipPositioner>
|
||||||
|
</TooltipPortal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
Tooltip,
|
||||||
|
TooltipTrigger,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipPortal,
|
||||||
|
TooltipPositioner,
|
||||||
|
TooltipArrow,
|
||||||
|
TooltipProvider,
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user