component Tooltip { outputs { toggle(payload: { open: boolean; reason: string; sourceEvent: Event }) open(payload: { reason: string; sourceEvent: Event }) close(payload: { reason: string; sourceEvent: Event }) } props { id: string = "" open: boolean = false defaultOpen: boolean = false title: string = "" description: string = "" content: string = "Tooltip" trigger: string = "hover" placement: string = "top" size: string = "default" color: string = "primary" variant: string = "dark" maxWidth: string = "18rem" offset: number = 10 showArrow: boolean = true interactive: boolean = false disabled: boolean = false class: string = "" } state visible = defaultOpen functions { shared function isOpen() { return open || visible } client function showTooltip(reason, sourceEvent) { if (disabled || trigger === "manual") { return } visible = true output.open({ reason: reason, sourceEvent: sourceEvent }) output.toggle({ open: true, reason: reason, sourceEvent: sourceEvent }) } client function hideTooltip(reason, sourceEvent) { if (trigger === "manual") { return } visible = false output.close({ reason: reason, sourceEvent: sourceEvent }) output.toggle({ open: false, reason: reason, sourceEvent: sourceEvent }) } client function toggleTooltip(sourceEvent) { if (isOpen()) { hideTooltip("click", sourceEvent) } else { showTooltip("click", sourceEvent) } } client function handleKeydown(sourceEvent) { if (sourceEvent.key === "Escape") { sourceEvent.preventDefault() hideTooltip("escape", sourceEvent) } } } view { {#if showArrow} {/if} {#if title} {title} {/if} {#if description} {description} {:else if content} {content} {/if} } style { .wrn-tooltip { --tooltip-accent: var(--wrn-color-primary); --tooltip-soft: var(--wrn-color-primary-soft); position: relative; display: inline-flex; max-width: 100%; } .wrn-tooltip[data-color="secondary"] { --tooltip-accent: var(--wrn-color-secondary); --tooltip-soft: var(--wrn-color-secondary-soft); } .wrn-tooltip[data-color="info"] { --tooltip-accent: var(--wrn-color-info); --tooltip-soft: var(--wrn-color-info-soft); } .wrn-tooltip[data-color="success"] { --tooltip-accent: var(--wrn-color-success); --tooltip-soft: var(--wrn-color-success-soft); } .wrn-tooltip[data-color="warning"] { --tooltip-accent: var(--wrn-color-warning); --tooltip-soft: var(--wrn-color-warning-soft); } .wrn-tooltip[data-color="danger"] { --tooltip-accent: var(--wrn-color-danger); --tooltip-soft: var(--wrn-color-danger-soft); } .wrn-tooltip__trigger { display: inline-flex; max-width: 100%; outline: none; } .wrn-tooltip__trigger:focus-visible { border-radius: 0.4rem; outline: 2px solid var(--wrn-color-focus); outline-offset: 3px; } .wrn-tooltip__content { position: absolute; z-index: 1300; left: 50%; bottom: calc(100% + var(--wrn-tooltip-offset)); display: grid; gap: 0.22rem; width: max-content; max-width: min(var(--wrn-tooltip-max-width), calc(100vw - 1rem)); padding: 0.58rem 0.72rem; color: white; background: color-mix(in srgb, black 88%, var(--tooltip-accent) 12%); border: 1px solid color-mix(in srgb, white 12%, transparent); border-radius: 0.65rem; box-shadow: 0 14px 38px color-mix(in srgb, black 28%, transparent); font-size: 0.73rem; line-height: 1.45; text-align: left; transform: translateX(-50%); pointer-events: none; } .wrn-tooltip[data-interactive="true"] .wrn-tooltip__content { pointer-events: auto; } .wrn-tooltip[data-variant="soft"] .wrn-tooltip__content { color: var(--wrn-color-text); background: var(--tooltip-soft); border-color: color-mix(in srgb, var(--tooltip-accent) 24%, var(--wrn-color-border)); } .wrn-tooltip[data-variant="light"] .wrn-tooltip__content { color: var(--wrn-color-text); background: var(--wrn-color-surface-raised); border-color: var(--wrn-color-border); } .wrn-tooltip[data-variant="solid"] .wrn-tooltip__content { color: var(--wrn-color-primary-contrast); background: var(--tooltip-accent); border-color: color-mix(in srgb, white 18%, transparent); } .wrn-tooltip__content strong { font-size: 0.75rem; font-weight: 650; } .wrn-tooltip__description { color: color-mix(in srgb, currentColor 82%, transparent); } .wrn-tooltip__arrow { position: absolute; left: 50%; bottom: -0.32rem; width: 0.62rem; height: 0.62rem; background: inherit; border-right: 1px solid color-mix(in srgb, white 10%, transparent); border-bottom: 1px solid color-mix(in srgb, white 10%, transparent); transform: translateX(-50%) rotate(45deg); } .wrn-tooltip[data-placement="bottom"] .wrn-tooltip__content { top: calc(100% + var(--wrn-tooltip-offset)); bottom: auto; } .wrn-tooltip[data-placement="bottom"] .wrn-tooltip__arrow { top: -0.32rem; bottom: auto; transform: translateX(-50%) rotate(225deg); } .wrn-tooltip[data-placement="left"] .wrn-tooltip__content { top: 50%; right: calc(100% + var(--wrn-tooltip-offset)); bottom: auto; left: auto; transform: translateY(-50%); } .wrn-tooltip[data-placement="left"] .wrn-tooltip__arrow { top: 50%; right: -0.32rem; bottom: auto; left: auto; transform: translateY(-50%) rotate(-45deg); } .wrn-tooltip[data-placement="right"] .wrn-tooltip__content { top: 50%; bottom: auto; left: calc(100% + var(--wrn-tooltip-offset)); transform: translateY(-50%); } .wrn-tooltip[data-placement="right"] .wrn-tooltip__arrow { top: 50%; bottom: auto; left: -0.32rem; transform: translateY(-50%) rotate(135deg); } .wrn-tooltip[data-placement="top-start"] .wrn-tooltip__content, .wrn-tooltip[data-placement="bottom-start"] .wrn-tooltip__content { left: 0; transform: none; } .wrn-tooltip[data-placement="top-start"] .wrn-tooltip__arrow, .wrn-tooltip[data-placement="bottom-start"] .wrn-tooltip__arrow { left: 1rem; transform: rotate(45deg); } .wrn-tooltip[data-placement="bottom-start"] .wrn-tooltip__arrow { transform: rotate(225deg); } .wrn-tooltip[data-placement="top-end"] .wrn-tooltip__content, .wrn-tooltip[data-placement="bottom-end"] .wrn-tooltip__content { right: 0; left: auto; transform: none; } .wrn-tooltip[data-placement="top-end"] .wrn-tooltip__arrow, .wrn-tooltip[data-placement="bottom-end"] .wrn-tooltip__arrow { right: 1rem; left: auto; transform: rotate(45deg); } .wrn-tooltip[data-placement="bottom-end"] .wrn-tooltip__arrow { transform: rotate(225deg); } .wrn-tooltip[data-size="sm"] .wrn-tooltip__content { padding: 0.45rem 0.58rem; font-size: 0.68rem; } .wrn-tooltip[data-size="lg"] .wrn-tooltip__content { padding: 0.72rem 0.85rem; font-size: 0.8rem; } @media (max-width: 639px) { .wrn-tooltip__content { position: fixed; right: 0.75rem; bottom: 0.75rem; left: 0.75rem; top: auto; width: auto; max-width: none; transform: none; } .wrn-tooltip__arrow { display: none; } } } }