kopia lustrzana https://github.com/wagtail/wagtail
Allow TooltipController to use HTML content target
This follows the same approach we already have in DropdownControllerpull/12185/head
rodzic
54f12e6354
commit
0277467dac
|
@ -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');
|
||||
|
||||
|
|
|
@ -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 }),
|
||||
|
|
Ładowanie…
Reference in New Issue