Improve tooltips more by ensuring they follow the target smoothly

This commit is contained in:
Andrew Kingston 2023-07-07 16:03:25 +01:00
parent 62e452dfe7
commit 06876b0ea2
2 changed files with 25 additions and 17 deletions

View File

@ -17,6 +17,7 @@
import Portal from "svelte-portal" import Portal from "svelte-portal"
import { fade } from "svelte/transition" import { fade } from "svelte/transition"
import "@spectrum-css/tooltip/dist/index-vars.css" import "@spectrum-css/tooltip/dist/index-vars.css"
import { onDestroy } from "svelte"
export let position = TooltipPosition.Top export let position = TooltipPosition.Top
export let type = TooltipType.Default export let type = TooltipType.Default
@ -30,20 +31,21 @@
let top = 0 let top = 0
let visible = false let visible = false
let timeout let timeout
let interval
$: { $: {
if (hovered || fixed) { if (hovered || fixed) {
// Debounce showing by 200ms to avoid flashing tooltip
timeout = setTimeout(show, 200) timeout = setTimeout(show, 200)
} else { } else {
clearTimeout(timeout)
hide() hide()
} }
} }
$: tooltipStyle = color ? `background:${color};` : null $: tooltipStyle = color ? `background:${color};` : null
$: tipStyle = color ? `border-top-color:${color};` : null $: tipStyle = color ? `border-top-color:${color};` : null
// Computes the position of the tooltip then shows it // Computes the position of the tooltip
const show = () => { const updateTooltipPosition = () => {
const node = wrapper?.children?.[0] const node = wrapper?.children?.[0]
if (!node) { if (!node) {
return return
@ -63,17 +65,27 @@
} else if (position === TooltipPosition.Left) { } else if (position === TooltipPosition.Left) {
left = bounds.left left = bounds.left
top = bounds.top + bounds.height / 2 top = bounds.top + bounds.height / 2
} else {
return
} }
}
// Computes the position of the tooltip then shows it.
// We set up a poll to frequently update the position of the tooltip in case
// the target moves.
const show = () => {
updateTooltipPosition()
interval = setInterval(updateTooltipPosition, 100)
visible = true visible = true
} }
// Hides the tooltip // Hides the tooltip
const hide = () => { const hide = () => {
clearTimeout(timeout)
clearInterval(interval)
visible = false visible = false
} }
// Ensure we clean up interval and timeout
onDestroy(hide)
</script> </script>
<div <div
@ -109,6 +121,7 @@
pointer-events: none; pointer-events: none;
margin: 0; margin: 0;
max-width: 280px; max-width: 280px;
transition: top 130ms ease-out, left 130ms ease-out;
} }
.spectrum-Tooltip-label { .spectrum-Tooltip-label {
text-overflow: ellipsis; text-overflow: ellipsis;
@ -126,7 +139,7 @@
border-top-color: var(--spectrum-global-color-gray-500); border-top-color: var(--spectrum-global-color-gray-500);
} }
/* Direction styles */ /* Position styles */
.spectrum-Tooltip--top { .spectrum-Tooltip--top {
transform: translateX(-50%) translateY(calc(-100% - 8px)); transform: translateX(-50%) translateY(calc(-100% - 8px));
} }

View File

@ -2,12 +2,7 @@
import { getContext } from "svelte" import { getContext } from "svelte"
import GridScrollWrapper from "./GridScrollWrapper.svelte" import GridScrollWrapper from "./GridScrollWrapper.svelte"
import HeaderCell from "../cells/HeaderCell.svelte" import HeaderCell from "../cells/HeaderCell.svelte"
import { import { Icon, TempTooltip, TooltipType } from "@budibase/bbui"
Icon,
TempTooltip,
TooltipType,
TooltipPosition,
} from "@budibase/bbui"
const { const {
renderedColumns, renderedColumns,
@ -17,6 +12,8 @@
width, width,
config, config,
hasNonAutoColumn, hasNonAutoColumn,
tableId,
loading,
} = getContext("grid") } = getContext("grid")
$: columnsWidth = $renderedColumns.reduce( $: columnsWidth = $renderedColumns.reduce(
@ -36,17 +33,15 @@
</div> </div>
</GridScrollWrapper> </GridScrollWrapper>
{#if $config.allowSchemaChanges} {#if $config.allowSchemaChanges}
{#key left} {#key $tableId}
<TempTooltip <TempTooltip
text="Click here to create your first column" text="Click here to create your first column"
position={TooltipPosition.Top}
type={TooltipType.Info} type={TooltipType.Info}
duration={3000} condition={!$hasNonAutoColumn && !$loading}
condition={!$hasNonAutoColumn}
> >
<div <div
class="add" class="add"
style="left:{left}px" style="left:{left}px;"
on:click={() => dispatch("add-column")} on:click={() => dispatch("add-column")}
> >
<Icon name="Add" /> <Icon name="Add" />