| <script lang="ts"> |
| import { getters, type ComponentProps, type Extracted } from "melt"; |
| import { Tooltip, type TooltipProps } from "melt/builders"; |
| import type { Snippet } from "svelte"; |
|
|
| type FloatingConfig = NonNullable<Extracted<TooltipProps["floatingConfig"]>>; |
|
|
| interface Props extends Omit<ComponentProps<TooltipProps>, "floatingConfig"> { |
| children: Snippet; |
| trigger: Snippet<[Tooltip]>; |
| placement?: NonNullable<FloatingConfig["computePosition"]>["placement"]; |
| openDelay?: ComponentProps<TooltipProps>["openDelay"]; |
| disabled?: boolean; |
| } |
| const { children, trigger, placement = "top", openDelay = 500, disabled, ...rest }: Props = $props(); |
|
|
| let open = $state(false); |
| const tooltip = new Tooltip({ |
| forceVisible: true, |
| floatingConfig: () => ({ |
| computePosition: { placement }, |
| flip: { |
| fallbackPlacements: ["bottom"], |
| padding: 10, |
| }, |
| }), |
| open: () => open, |
| onOpenChange(v) { |
| if (disabled) open = false; |
| else open = v; |
| }, |
| openDelay: () => openDelay, |
| ...getters(rest), |
| }); |
| </script> |
|
|
| {@render trigger(tooltip)} |
|
|
| <div {...tooltip.content} class="rounded-xl bg-white p-0 shadow-xl dark:bg-gray-700"> |
| <div {...tooltip.arrow} class="size-2 rounded-tl"></div> |
| <p class="px-4 py-1 text-gray-700 dark:text-white">{@render children()}</p> |
| </div> |
|
|
| <style> |
| [data-melt-tooltip-content] { |
| border: 0; |
|
|
| pointer-events: none; |
| opacity: 0; |
|
|
| transform: scale(0.9); |
|
|
| transition: 0.3s; |
| transition-property: opacity, transform; |
| } |
|
|
| [data-melt-tooltip-content][data-open] { |
| pointer-events: auto; |
| opacity: 1; |
|
|
| transform: scale(1); |
| } |
| </style> |
|
|