Skip to content

Commit

Permalink
feat(tooltip): enhance tooltip functionality with open state manageme…
Browse files Browse the repository at this point in the history
…nt across components
  • Loading branch information
DarthGigi committed Feb 22, 2025
1 parent ff0d1bb commit ce0f0c1
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 42 deletions.
66 changes: 37 additions & 29 deletions src/lib/components/AdditionStat.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,54 @@
import { RARITY_COLORS } from "$lib/shared/constants/items";
import { cn, flyAndScale } from "$lib/shared/utils";
import { Tooltip } from "bits-ui";
import type { Snippet } from "svelte";
export let text: string;
export let data: string | number;
export let subData: string | undefined = undefined;
export let asterisk: boolean = false;
export let maxed: boolean = false;
export let dataMaxed: boolean = false;
export let textRarityColor: string | undefined = undefined;
export let dataRarityColor: string | undefined = undefined;
export let subDataRarityColor: string | undefined = undefined;
type Props = {
text: string;
data: string | number;
subData?: string | undefined;
asterisk?: boolean;
maxed?: boolean;
dataMaxed?: boolean;
textRarityColor?: string | undefined;
dataRarityColor?: string | undefined;
subDataRarityColor?: string | undefined;
class?: string | null | undefined;
children?: Snippet;
};
let className: string | null | undefined = undefined;
export { className as class };
let { text, data, subData = undefined, asterisk = false, maxed = false, dataMaxed = false, textRarityColor = undefined, dataRarityColor = undefined, subDataRarityColor = undefined, class: className = undefined, children }: Props = $props();
let open = $state(false);
</script>

<Tooltip.Root group="additional-stats" openDelay={0} closeDelay={0}>
<Tooltip.Trigger asChild={!asterisk} class={cn(`text-text/60 my-0 flex items-center gap-1 font-bold data-[is-tooltip=false]:cursor-default`, { "text-maxed": maxed }, className)} data-is-tooltip={asterisk}>
<div class={!asterisk ? cn("text-text/60 my-0 flex items-center gap-1 font-bold data-[is-tooltip=false]:cursor-default", { "text-maxed": maxed }, className) : "contents"}>
<div style={textRarityColor ? `color: var(--§${RARITY_COLORS[textRarityColor]})` : ""} class="capitalize">
{text}:
</div>
<Tooltip.Root bind:open group="additional-stats" openDelay={0} closeDelay={0}>
<Tooltip.Trigger asChild let:builder>
<button use:builder.action {...builder} class={cn(`text-text/60 my-0 flex items-center gap-1 font-bold data-[is-tooltip=false]:cursor-default`, { "text-maxed": maxed }, className)} data-is-tooltip={asterisk} onpointerdown={() => (open = !open)}>
<div class={!asterisk ? cn("text-text/60 my-0 flex items-center gap-1 font-bold data-[is-tooltip=false]:cursor-default", { "text-maxed": maxed }, className) : "contents"}>
<div style={textRarityColor ? `color: var(--§${RARITY_COLORS[textRarityColor]})` : ""} class="capitalize">
{text}:
</div>

<span class={cn("-mr-0.5", maxed || dataMaxed ? "text-gold" : "text-text")}>
<span style={dataRarityColor ? `color: var(--§${RARITY_COLORS[dataRarityColor]})` : ""}>
{data}
</span>

<span class={cn("-mr-0.5", maxed || dataMaxed ? "text-gold" : "text-text")}>
<span style={dataRarityColor ? `color: var(--§${RARITY_COLORS[dataRarityColor]})` : ""}>
{data}
{#if subData}
<span class="text-text/80" style={subDataRarityColor ? `color: var(--§${RARITY_COLORS[subDataRarityColor]})` : ""}> {subData}</span>
{/if}
</span>

{#if subData}
<span class="text-text/80" style={subDataRarityColor ? `color: var(--§${RARITY_COLORS[subDataRarityColor]})` : ""}> {subData}</span>
{#if asterisk}
*
{/if}
</span>

{#if asterisk}
*
{/if}
</div>
</div>
</button>
</Tooltip.Trigger>
{#if asterisk}
<Tooltip.Content class="bg-background-grey z-50 rounded-lg p-4" transition={flyAndScale} transitionConfig={{ y: 8, duration: 150 }} sideOffset={6} side="top" align="center">
<slot />
{@render children?.()}
<Tooltip.Arrow />
</Tooltip.Content>
{/if}
Expand Down
3 changes: 2 additions & 1 deletion src/lib/components/Chip.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
let targetNode = $state<HTMLDivElement>()!;
let hasBeenInViewport = $state(false);
let open = $state(false);
const inViewport = new IsInViewport(() => targetNode, { rootMargin: "200px 0px", threshold: 0 });
Expand All @@ -48,7 +49,7 @@

<Tooltip.Root group="chip" openDelay={0} closeDelay={0}>
<Tooltip.Trigger asChild let:builder>
<div bind:this={targetNode} class={cn("bg-background/30 flex w-full max-w-fit items-center gap-2 rounded-lg py-2", classNames)} use:builder.action {...builder} in:fade|global={{ duration: animationOptions.animate ? 300 : 0, delay: animationOptions.animate ? 25 * (animationOptions.index + 1) : 0 }} out:fade|global={{ duration: animationOptions.animate ? 300 : 0, delay: animationOptions.animate ? 25 * (animationOptions.amountOfItems - animationOptions.index) : 0 }}>
<div bind:this={targetNode} class={cn("bg-background/30 flex w-full max-w-fit items-center gap-2 rounded-lg py-2", classNames)} use:builder.action {...builder} onpointerdown={() => (open = !open)} in:fade|global={{ duration: animationOptions.animate ? 300 : 0, delay: animationOptions.animate ? 25 * (animationOptions.index + 1) : 0 }} out:fade|global={{ duration: animationOptions.animate ? 300 : 0, delay: animationOptions.animate ? 25 * (animationOptions.amountOfItems - animationOptions.index) : 0 }}>
<div class="flex items-center gap-2 px-2">
{#if hasBeenInViewport}
<Avatar.Root class="aspect-square size-12">
Expand Down
6 changes: 4 additions & 2 deletions src/lib/components/Skillbar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@
let { skill, skillData, apiEnabled = true, class: className }: Props = $props();
let open = $state(false);
const { hoverAction, isHovered } = createHover();
const isMaxed = $derived(skillData.maxed);
</script>

<div class={cn("group relative flex grow basis-full flex-col sm:basis-1/3 sm:last:grow-0 sm:last:basis-1/2", !apiEnabled && "opacity-50 grayscale", className)} data-hover={$isHovered} data-maxed={isMaxed} use:hoverAction>
<Tooltip.Root group="skills" openDelay={0} closeDelay={0}>
<Tooltip.Trigger class={cn("group-data-[maxed=true]:shine group-data-[maxed=false]:bg-icon group-data-[maxed=true]:bg-maxed absolute bottom-0 left-0 z-10 flex size-9 items-center justify-center rounded-full p-1 drop-shadow-sm", apiEnabled ? "" : "bg-gray-600")}>
<Tooltip.Root bind:open group="skills" openDelay={0} closeDelay={0}>
<Tooltip.Trigger class={cn("group-data-[maxed=true]:shine group-data-[maxed=false]:bg-icon group-data-[maxed=true]:bg-maxed absolute bottom-0 left-0 z-10 flex size-9 items-center justify-center rounded-full p-1 drop-shadow-sm", apiEnabled ? "" : "bg-gray-600")} onpointerdown={() => (open = !open)}>
<Avatar.Root class="select-none">
<Avatar.Image loading="lazy" class={cn("pointer-events-none size-[1.625rem]", !apiEnabled && "grayscale")} src={skillData.texture} alt={skill} />
<Avatar.Fallback>
Expand Down
20 changes: 12 additions & 8 deletions src/lib/components/Stat.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,23 @@
import { Tooltip } from "bits-ui";
import { format } from "numerable";
export let stat: string;
export let statData: {
[string: string]: number;
base: number;
type Props = {
stat: string;
statData: {
[string: string]: number;
base: number;
};
class?: string | null | undefined;
};
let className: string | null | undefined = undefined;
export { className as class };
let { stat, statData, class: className = undefined }: Props = $props();
let open = $state(false);
</script>

<div>
<Tooltip.Root group="stats" openDelay={0} closeDelay={0}>
<Tooltip.Trigger class={cn(`my-0 flex items-center gap-1 text-sm font-bold whitespace-nowrap ${STATS_DATA[stat].color}`, className)}>
<Tooltip.Root bind:open group="stats" openDelay={0} closeDelay={0}>
<Tooltip.Trigger class={cn(`my-0 flex items-center gap-1 text-sm font-bold whitespace-nowrap ${STATS_DATA[stat].color}`, className)} onpointerdown={() => (open = !open)}>
<div class="font-icomoon inline-block text-base">{STATS_DATA[stat].symbol}</div>
<span class="capitalize">{stat.replace(/_/g, " ")}</span>
<span class="text-text">
Expand Down
6 changes: 4 additions & 2 deletions src/lib/layouts/stats/PlayerProfile.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
let toastId: string | number = $state(0);
let showMore = $state(false);
let open = $state(false);
const ctx = getProfileCtx();
const profile = $derived(ctx.profile);
Expand Down Expand Up @@ -88,7 +89,7 @@
</div>

<div class="flex flex-wrap items-center gap-x-4 gap-y-2">
<Tooltip.Root openDelay={0} closeDelay={0} closeOnPointerDown={false}>
<Tooltip.Root bind:open openDelay={0} closeDelay={0} closeOnPointerDown={false}>
<Tooltip.Trigger asChild let:builder>
<button
use:builder.action
Expand All @@ -104,7 +105,8 @@
toast.dismiss(toastId);
toastId = toast.success(`Removed ${profile.username} from your favorites!`);
}
}}>
}}
onpointerdown={() => (open = !open)}>
{#if $favorites.includes(profile.uuid)}
<Star class="size-4 fill-white" />
{:else}
Expand Down

0 comments on commit ce0f0c1

Please sign in to comment.