Allow TooltipController to use HTML content target

This follows the same approach we already have in DropdownController
pull/12185/head
Sage Abdullah 2024-06-26 11:33:43 +01:00 zatwierdzone przez Thibaud Colas
rodzic 54f12e6354
commit 0277467dac
2 zmienionych plików z 51 dodań i 3 usunięć

Wyświetl plik

@ -5,7 +5,7 @@ describe('TooltipController', () => {
let application;
beforeEach(async () => {
document.body.innerHTML = `
document.body.innerHTML = /* html */ `
<section>
<button
type="button"
@ -25,6 +25,16 @@ describe('TooltipController', () => {
>
CONTENT
</button>
<button
type="button"
id="tooltip-html"
data-controller="w-tooltip"
>
<div class="custom-style" data-w-tooltip-target="content" hidden>
<strong>Rich</strong> tooltip
</div>
CONTENT
</button>
</section>`;
application = Application.start();
@ -105,6 +115,34 @@ describe('TooltipController', () => {
expect(tooltip.dataset.placement).toEqual('top');
});
it('should allow HTML via content target', async () => {
const tooltipTrigger = document.getElementById('tooltip-html');
// on init, Tippy will immediately unmount the content from the DOM
// to be shown later when triggered
expect(tooltipTrigger.textContent.trim()).toEqual('CONTENT');
expect(tooltipTrigger.querySelector('strong')).toBeNull();
expect(document.querySelectorAll('[role="tooltip"]')).toHaveLength(0);
tooltipTrigger.dispatchEvent(new Event('mouseenter'));
await Promise.resolve();
const tooltip = document.querySelector('[role="tooltip"]');
expect(tooltip.textContent.trim()).toEqual('Rich tooltip');
// Should contain the div and it should not be hidden
const placedDiv = tooltip.querySelector('.custom-style');
expect(placedDiv).toBeTruthy();
expect(placedDiv.hidden).toBe(false);
// Should retain the rich content as HTML
const strong = tooltip.querySelector('strong');
expect(strong).toBeTruthy();
expect(strong.textContent).toEqual('Rich');
});
it('should destroy the tippy instance on disconnect', async () => {
const tooltipTrigger = document.getElementById('tooltip-default');

Wyświetl plik

@ -1,5 +1,5 @@
import { Controller } from '@hotwired/stimulus';
import tippy, { Placement, Props, Instance } from 'tippy.js';
import tippy, { Placement, Props, Instance, Content } from 'tippy.js';
import { domReady } from '../utils/domReady';
/**
@ -41,11 +41,15 @@ export class TooltipController extends Controller<HTMLElement> {
placement: { default: 'bottom', type: String },
};
static targets = ['content'];
declare contentValue: string;
declare offsetValue: [number, number];
declare placementValue: Placement;
declare contentTarget: HTMLElement;
declare readonly hasOffsetValue: boolean;
declare readonly hasContentTarget: boolean;
tippy?: Instance<Props>;
@ -72,8 +76,14 @@ export class TooltipController extends Controller<HTMLElement> {
}
get options(): Partial<Props> {
let content: Content = this.contentValue;
if (this.hasContentTarget) {
this.contentTarget.hidden = false;
content = this.contentTarget;
}
return {
content: this.contentValue,
content,
placement: this.placementValue,
plugins: this.plugins,
...(this.hasOffsetValue && { offset: this.offsetValue }),