@vaadin/tooltip 25.0.0-alpha2 → 25.0.0-alpha21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/tooltip",
3
- "version": "25.0.0-alpha2",
3
+ "version": "25.0.0-alpha21",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -21,7 +21,6 @@
21
21
  "type": "module",
22
22
  "files": [
23
23
  "src",
24
- "theme",
25
24
  "vaadin-*.d.ts",
26
25
  "vaadin-*.js",
27
26
  "web-types.json",
@@ -35,23 +34,24 @@
35
34
  ],
36
35
  "dependencies": {
37
36
  "@open-wc/dedupe-mixin": "^1.3.0",
38
- "@vaadin/a11y-base": "25.0.0-alpha2",
39
- "@vaadin/component-base": "25.0.0-alpha2",
40
- "@vaadin/overlay": "25.0.0-alpha2",
41
- "@vaadin/popover": "25.0.0-alpha2",
42
- "@vaadin/vaadin-lumo-styles": "25.0.0-alpha2",
43
- "@vaadin/vaadin-themable-mixin": "25.0.0-alpha2",
37
+ "@vaadin/a11y-base": "25.0.0-alpha21",
38
+ "@vaadin/component-base": "25.0.0-alpha21",
39
+ "@vaadin/markdown": "25.0.0-alpha21",
40
+ "@vaadin/overlay": "25.0.0-alpha21",
41
+ "@vaadin/popover": "25.0.0-alpha21",
42
+ "@vaadin/vaadin-themable-mixin": "25.0.0-alpha21",
44
43
  "lit": "^3.0.0"
45
44
  },
46
45
  "devDependencies": {
47
- "@vaadin/chai-plugins": "25.0.0-alpha2",
48
- "@vaadin/test-runner-commands": "25.0.0-alpha2",
46
+ "@vaadin/chai-plugins": "25.0.0-alpha21",
47
+ "@vaadin/test-runner-commands": "25.0.0-alpha21",
49
48
  "@vaadin/testing-helpers": "^2.0.0",
50
- "sinon": "^18.0.0"
49
+ "@vaadin/vaadin-lumo-styles": "25.0.0-alpha21",
50
+ "sinon": "^21.0.0"
51
51
  },
52
52
  "web-types": [
53
53
  "web-types.json",
54
54
  "web-types.lit.json"
55
55
  ],
56
- "gitHead": "67ffcd5355cf21ce1b5039c598525109fc4c164b"
56
+ "gitHead": "8fb9e9710c01449edf623a1aaac4655cdc11a933"
57
57
  }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2022 - 2025 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import '@vaadin/component-base/src/styles/style-props.js';
7
+ import { css } from 'lit';
8
+
9
+ export const tooltipOverlayStyles = css`
10
+ :host {
11
+ --_vaadin-tooltip-default-offset: 4px;
12
+ line-height: normal;
13
+ }
14
+
15
+ [part='overlay'] {
16
+ max-width: var(--vaadin-tooltip-max-width, 40ch);
17
+ padding: var(--vaadin-tooltip-padding, var(--vaadin-padding-container));
18
+ border-radius: var(--vaadin-tooltip-border-radius, var(--vaadin-radius-m));
19
+ background: var(--vaadin-tooltip-background, var(--vaadin-background-color));
20
+ color: var(--vaadin-tooltip-color, inherit);
21
+ font-size: var(--vaadin-tooltip-font-size, 0.9em);
22
+ font-weight: var(--vaadin-tooltip-font-weight, inherit);
23
+ line-height: var(--vaadin-tooltip-line-height, inherit);
24
+ border: 0;
25
+ box-shadow:
26
+ 0 0 0 var(--vaadin-tooltip-border-width, 1px)
27
+ var(--vaadin-tooltip-border-color, var(--vaadin-border-color-secondary)),
28
+ var(--vaadin-tooltip-shadow, 0 3px 8px -1px rgba(0, 0, 0, 0.2));
29
+ }
30
+
31
+ :host(:not([markdown])) [part='content'] {
32
+ white-space: pre-wrap;
33
+ }
34
+
35
+ :host([position^='top'][top-aligned]) [part='overlay'],
36
+ :host([position^='bottom'][top-aligned]) [part='overlay'] {
37
+ margin-top: var(--vaadin-tooltip-offset-top, var(--_vaadin-tooltip-default-offset));
38
+ }
39
+
40
+ :host([position^='top'][bottom-aligned]) [part='overlay'],
41
+ :host([position^='bottom'][bottom-aligned]) [part='overlay'] {
42
+ margin-bottom: var(--vaadin-tooltip-offset-bottom, var(--_vaadin-tooltip-default-offset));
43
+ }
44
+
45
+ :host([position^='start'][start-aligned]) [part='overlay'],
46
+ :host([position^='end'][start-aligned]) [part='overlay'] {
47
+ margin-inline-start: var(--vaadin-tooltip-offset-start, var(--_vaadin-tooltip-default-offset));
48
+ }
49
+
50
+ :host([position^='start'][end-aligned]) [part='overlay'],
51
+ :host([position^='end'][end-aligned]) [part='overlay'] {
52
+ margin-inline-end: var(--vaadin-tooltip-offset-end, var(--_vaadin-tooltip-default-offset));
53
+ }
54
+
55
+ @media (forced-colors: active) {
56
+ [part='overlay'] {
57
+ border: 1px dashed !important;
58
+ }
59
+ }
60
+ `;
@@ -4,7 +4,6 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import type { Constructor } from '@open-wc/dedupe-mixin';
7
- import type { OverlayClassMixinClass } from '@vaadin/component-base/src/overlay-class-mixin.js';
8
7
  import type { PopoverPositionMixinClass } from '@vaadin/popover/src/vaadin-popover-position-mixin.js';
9
8
  import type { PopoverTargetMixinClass } from '@vaadin/popover/src/vaadin-popover-target-mixin.js';
10
9
 
@@ -15,11 +14,7 @@ export type { PopoverPosition as TooltipPosition } from '@vaadin/popover/src/vaa
15
14
  */
16
15
  export declare function TooltipMixin<T extends Constructor<HTMLElement>>(
17
16
  base: T,
18
- ): Constructor<OverlayClassMixinClass> &
19
- Constructor<PopoverPositionMixinClass> &
20
- Constructor<PopoverTargetMixinClass> &
21
- Constructor<TooltipMixinClass> &
22
- T;
17
+ ): Constructor<PopoverPositionMixinClass> & Constructor<PopoverTargetMixinClass> & Constructor<TooltipMixinClass> & T;
23
18
 
24
19
  export declare class TooltipMixinClass {
25
20
  /**
@@ -27,7 +22,7 @@ export declare class TooltipMixinClass {
27
22
  * attribute. Supports array of multiple elements.
28
23
  * When not set, defaults to `target`.
29
24
  */
30
- ariaTarget: HTMLElement | HTMLElement[] | undefined;
25
+ ariaTarget: HTMLElement | HTMLElement[] | null | undefined;
31
26
 
32
27
  /**
33
28
  * Object with properties passed to `generator` and
@@ -73,8 +68,9 @@ export declare class TooltipMixinClass {
73
68
  manual: boolean;
74
69
 
75
70
  /**
76
- * When true, the tooltip is opened programmatically.
77
- * Only works if `manual` is set to `true`.
71
+ * When true, the tooltip is opened.
72
+ * In manual mode, this can be set programmatically.
73
+ * In automatic mode, this is set automatically by internal logic.
78
74
  */
79
75
  opened: boolean;
80
76
 
@@ -91,4 +87,13 @@ export declare class TooltipMixinClass {
91
87
  * String used as a tooltip content.
92
88
  */
93
89
  text: string | null | undefined;
90
+
91
+ /**
92
+ * When enabled, the tooltip text is rendered as Markdown.
93
+ *
94
+ * **Note:** Using Markdown is discouraged if accessibility of the tooltip
95
+ * content is essential, as semantics of the rendered HTML content
96
+ * (headers, lists, ...) will not be conveyed to assistive technologies.
97
+ */
98
+ markdown: boolean;
94
99
  }
@@ -5,7 +5,6 @@
5
5
  */
6
6
  import { isKeyboardActive } from '@vaadin/a11y-base/src/focus-utils.js';
7
7
  import { addValueToAttribute, removeValueFromAttribute } from '@vaadin/component-base/src/dom-utils.js';
8
- import { OverlayClassMixin } from '@vaadin/component-base/src/overlay-class-mixin.js';
9
8
  import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
10
9
  import { generateUniqueId } from '@vaadin/component-base/src/unique-id-utils.js';
11
10
  import { PopoverPositionMixin } from '@vaadin/popover/src/vaadin-popover-position-mixin.js';
@@ -45,11 +44,6 @@ class TooltipStateController {
45
44
  this.host = host;
46
45
  }
47
46
 
48
- /** @private */
49
- get openedProp() {
50
- return this.host.manual ? 'opened' : '_autoOpened';
51
- }
52
-
53
47
  /** @private */
54
48
  get focusDelay() {
55
49
  const tooltip = this.host;
@@ -115,12 +109,12 @@ class TooltipStateController {
115
109
 
116
110
  /** @private */
117
111
  _isOpened() {
118
- return this.host[this.openedProp];
112
+ return this.host.opened;
119
113
  }
120
114
 
121
115
  /** @private */
122
116
  _setOpened(opened) {
123
- this.host[this.openedProp] = opened;
117
+ this.host.opened = opened;
124
118
  }
125
119
 
126
120
  /** @private */
@@ -224,12 +218,11 @@ class TooltipStateController {
224
218
  * A mixin providing common tooltip functionality.
225
219
  *
226
220
  * @polymerMixin
227
- * @mixes OverlayClassMixin
228
221
  * @mixes PopoverPositionMixin
229
222
  * @mixes PopoverTargetMixin
230
223
  */
231
224
  export const TooltipMixin = (superClass) =>
232
- class TooltipMixinClass extends PopoverPositionMixin(PopoverTargetMixin(OverlayClassMixin(superClass))) {
225
+ class TooltipMixinClass extends PopoverPositionMixin(PopoverTargetMixin(superClass)) {
233
226
  static get properties() {
234
227
  return {
235
228
  /**
@@ -302,12 +295,15 @@ export const TooltipMixin = (superClass) =>
302
295
  },
303
296
 
304
297
  /**
305
- * When true, the tooltip is opened programmatically.
306
- * Only works if `manual` is set to `true`.
298
+ * When true, the tooltip is opened.
299
+ * In manual mode, this can be set programmatically.
300
+ * In automatic mode, this is set automatically by internal logic.
307
301
  */
308
302
  opened: {
309
303
  type: Boolean,
310
304
  value: false,
305
+ reflectToAttribute: true,
306
+ observer: '__openedChanged',
311
307
  sync: true,
312
308
  },
313
309
 
@@ -330,18 +326,19 @@ export const TooltipMixin = (superClass) =>
330
326
  */
331
327
  text: {
332
328
  type: String,
333
- observer: '__textChanged',
334
329
  },
335
330
 
336
331
  /**
337
- * Set to true when the overlay is opened using auto-added
338
- * event listeners: mouseenter and focusin (keyboard only).
339
- * @protected
332
+ * When enabled, the tooltip text is rendered as Markdown.
333
+ *
334
+ * **Note:** Using Markdown is discouraged if accessibility of the tooltip
335
+ * content is essential, as semantics of the rendered HTML content
336
+ * (headers, lists, ...) will not be conveyed to assistive technologies.
340
337
  */
341
- _autoOpened: {
338
+ markdown: {
342
339
  type: Boolean,
343
- observer: '__autoOpenedChanged',
344
- sync: true,
340
+ value: false,
341
+ reflectToAttribute: true,
345
342
  },
346
343
 
347
344
  /**
@@ -366,26 +363,9 @@ export const TooltipMixin = (superClass) =>
366
363
  type: Boolean,
367
364
  sync: true,
368
365
  },
369
-
370
- /** @private */
371
- _srLabel: {
372
- type: Object,
373
- },
374
-
375
- /** @private */
376
- _overlayContent: {
377
- type: String,
378
- },
379
366
  };
380
367
  }
381
368
 
382
- static get observers() {
383
- return [
384
- '__generatorChanged(_overlayElement, generator, context)',
385
- '__updateSrLabelText(_srLabel, _overlayContent)',
386
- ];
387
- }
388
-
389
369
  /**
390
370
  * Sets the default focus delay to be used by all tooltip instances,
391
371
  * except for those that have focus delay configured using property.
@@ -420,7 +400,6 @@ export const TooltipMixin = (superClass) =>
420
400
  super();
421
401
 
422
402
  this._uniqueId = `vaadin-tooltip-${generateUniqueId()}`;
423
- this._renderer = this.__tooltipRenderer.bind(this);
424
403
 
425
404
  this.__onFocusin = this.__onFocusin.bind(this);
426
405
  this.__onFocusout = this.__onFocusout.bind(this);
@@ -453,7 +432,7 @@ export const TooltipMixin = (superClass) =>
453
432
  disconnectedCallback() {
454
433
  super.disconnectedCallback();
455
434
 
456
- if (this._autoOpened) {
435
+ if (this.opened && !this.manual) {
457
436
  this._stateController.close(true);
458
437
  }
459
438
  this._isConnected = false;
@@ -467,23 +446,27 @@ export const TooltipMixin = (superClass) =>
467
446
 
468
447
  this._overlayElement = this.$.overlay;
469
448
 
470
- this._srLabelController = new SlotController(this, 'sr-label', 'div', {
449
+ this.__contentController = new SlotController(this, 'overlay', 'div', {
471
450
  initializer: (element) => {
472
451
  element.id = this._uniqueId;
473
452
  element.setAttribute('role', 'tooltip');
474
- this._srLabel = element;
453
+ this.__contentNode = element;
475
454
  },
476
455
  });
477
- this.addController(this._srLabelController);
456
+ this.addController(this.__contentController);
478
457
  }
479
458
 
480
- /** @private */
481
- __computeOpened(manual, opened, autoOpened, connected) {
482
- return connected && (manual ? opened : autoOpened);
459
+ /** @protected */
460
+ updated(props) {
461
+ super.updated(props);
462
+
463
+ if (props.has('text') || props.has('generator') || props.has('context') || props.has('markdown')) {
464
+ this.__updateContent();
465
+ }
483
466
  }
484
467
 
485
468
  /** @private */
486
- __autoOpenedChanged(opened, oldOpened) {
469
+ __openedChanged(opened, oldOpened) {
487
470
  if (opened) {
488
471
  document.addEventListener('keydown', this.__onKeyDown, true);
489
472
  } else if (oldOpened) {
@@ -546,7 +529,7 @@ export const TooltipMixin = (superClass) =>
546
529
 
547
530
  this.__focusInside = true;
548
531
 
549
- if (!this.__isTargetHidden && (!this.__hoverInside || !this._autoOpened)) {
532
+ if (!this.__isTargetHidden && (!this.__hoverInside || !this.opened)) {
550
533
  this._stateController.open({ focus: true });
551
534
  }
552
535
  }
@@ -571,6 +554,10 @@ export const TooltipMixin = (superClass) =>
571
554
 
572
555
  /** @private */
573
556
  __onKeyDown(event) {
557
+ if (this.manual) {
558
+ return;
559
+ }
560
+
574
561
  if (event.key === 'Escape') {
575
562
  event.stopPropagation();
576
563
  this._stateController.close(true);
@@ -603,7 +590,7 @@ export const TooltipMixin = (superClass) =>
603
590
 
604
591
  this.__hoverInside = true;
605
592
 
606
- if (!this.__isTargetHidden && (!this.__focusInside || !this._autoOpened)) {
593
+ if (!this.__isTargetHidden && (!this.__focusInside || !this.opened)) {
607
594
  this._stateController.open({ hover: true });
608
595
  }
609
596
  }
@@ -617,6 +604,9 @@ export const TooltipMixin = (superClass) =>
617
604
 
618
605
  /** @protected */
619
606
  __onOverlayMouseEnter() {
607
+ if (this.manual) {
608
+ return;
609
+ }
620
610
  // Retain opened state when moving pointer over the overlay.
621
611
  // Closing can start due to an offset between the target and
622
612
  // the overlay itself. If that's the case, re-open overlay.
@@ -633,6 +623,20 @@ export const TooltipMixin = (superClass) =>
633
623
  }
634
624
  }
635
625
 
626
+ /** @protected */
627
+ __onOverlayMouseDown(event) {
628
+ // Prevent mousedown listeners from being called when
629
+ // the tooltip is slotted into the target element
630
+ event.stopPropagation();
631
+ }
632
+
633
+ /** @protected */
634
+ __onOverlayClick(event) {
635
+ // Prevent click listeners from being called when
636
+ // the tooltip is slotted into the target element
637
+ event.stopPropagation();
638
+ }
639
+
636
640
  /** @private */
637
641
  __handleMouseLeave() {
638
642
  if (this.manual) {
@@ -660,6 +664,10 @@ export const TooltipMixin = (superClass) =>
660
664
 
661
665
  /** @private */
662
666
  __onTargetVisibilityChange(isVisible) {
667
+ if (this.manual) {
668
+ return;
669
+ }
670
+
663
671
  const oldHidden = this.__isTargetHidden;
664
672
  this.__isTargetHidden = !isVisible;
665
673
 
@@ -670,7 +678,7 @@ export const TooltipMixin = (superClass) =>
670
678
  }
671
679
 
672
680
  // Close the overlay when the target is no longer fully visible.
673
- if (!isVisible && this._autoOpened) {
681
+ if (!isVisible && this.opened) {
674
682
  this._stateController.close(true);
675
683
  }
676
684
  }
@@ -685,25 +693,25 @@ export const TooltipMixin = (superClass) =>
685
693
  }
686
694
 
687
695
  /** @private */
688
- __textChanged(text, oldText) {
689
- if (this._overlayElement && (text || oldText)) {
690
- this._overlayElement.requestContentUpdate();
691
- }
692
- }
696
+ async __updateContent() {
697
+ const content = typeof this.generator === 'function' ? this.generator(this.context) : this.text;
693
698
 
694
- /** @private */
695
- __tooltipRenderer(root) {
696
- root.textContent = typeof this.generator === 'function' ? this.generator(this.context) : this.text;
699
+ if (this.markdown && content) {
700
+ const helpers = await this.constructor.__importMarkdownHelpers();
701
+ helpers.renderMarkdownToElement(this.__contentNode, content);
702
+ } else {
703
+ this.__contentNode.textContent = content || '';
704
+ }
697
705
 
698
- // Update the sr-only label text content
699
- this._overlayContent = root.textContent;
706
+ this.$.overlay.toggleAttribute('hidden', this.__contentNode.textContent.trim() === '');
707
+ this.dispatchEvent(new CustomEvent('content-changed', { detail: { content: this.__contentNode.textContent } }));
700
708
  }
701
709
 
702
710
  /** @private */
703
711
  __computeAriaTarget(ariaTarget, target) {
704
712
  const isElementNode = (el) => el && el.nodeType === Node.ELEMENT_NODE;
705
713
  const isAriaTargetSet = Array.isArray(ariaTarget) ? ariaTarget.some(isElementNode) : ariaTarget;
706
- return isAriaTargetSet ? ariaTarget : target;
714
+ return ariaTarget === null || isAriaTargetSet ? ariaTarget : target;
707
715
  }
708
716
 
709
717
  /** @private */
@@ -721,22 +729,17 @@ export const TooltipMixin = (superClass) =>
721
729
  }
722
730
  }
723
731
 
724
- /** @private */
725
- __generatorChanged(overlayElement, generator, context) {
726
- if (overlayElement) {
727
- if (generator !== this.__oldTextGenerator || context !== this.__oldContext) {
728
- overlayElement.requestContentUpdate();
729
- }
730
-
731
- this.__oldTextGenerator = generator;
732
- this.__oldContext = context;
732
+ /** @private **/
733
+ static __importMarkdownHelpers() {
734
+ if (!this.__markdownHelpers) {
735
+ this.__markdownHelpers = import('@vaadin/markdown/src/markdown-helpers.js');
733
736
  }
737
+ return this.__markdownHelpers;
734
738
  }
735
739
 
736
- /** @private */
737
- __updateSrLabelText(srLabel, textContent) {
738
- if (srLabel) {
739
- srLabel.textContent = textContent;
740
- }
741
- }
740
+ /**
741
+ * Fired when the tooltip text content is changed.
742
+ *
743
+ * @event content-changed
744
+ */
742
745
  };
@@ -7,10 +7,11 @@ import { html, LitElement } from 'lit';
7
7
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
8
8
  import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
9
9
  import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
10
- import { overlayStyles } from '@vaadin/overlay/src/vaadin-overlay-styles.js';
10
+ import { overlayStyles } from '@vaadin/overlay/src/styles/vaadin-overlay-base-styles.js';
11
11
  import { PopoverOverlayMixin } from '@vaadin/popover/src/vaadin-popover-overlay-mixin.js';
12
+ import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
12
13
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
13
- import { tooltipOverlayStyles } from './vaadin-tooltip-overlay-styles.js';
14
+ import { tooltipOverlayStyles } from './styles/vaadin-tooltip-overlay-base-styles.js';
14
15
 
15
16
  /**
16
17
  * An element used internally by `<vaadin-tooltip>`. Not intended to be used separately.
@@ -22,7 +23,9 @@ import { tooltipOverlayStyles } from './vaadin-tooltip-overlay-styles.js';
22
23
  * @mixes PopoverOverlayMixin
23
24
  * @private
24
25
  */
25
- class TooltipOverlay extends PopoverOverlayMixin(DirMixin(ThemableMixin(PolylitMixin(LitElement)))) {
26
+ class TooltipOverlay extends PopoverOverlayMixin(
27
+ DirMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement)))),
28
+ ) {
26
29
  static get is() {
27
30
  return 'vaadin-tooltip-overlay';
28
31
  }
@@ -31,30 +34,14 @@ class TooltipOverlay extends PopoverOverlayMixin(DirMixin(ThemableMixin(PolylitM
31
34
  return [overlayStyles, tooltipOverlayStyles];
32
35
  }
33
36
 
34
- /**
35
- * Tag name prefix used by custom properties.
36
- * @protected
37
- * @return {string}
38
- */
39
- get _tagNamePrefix() {
40
- return 'vaadin-tooltip';
41
- }
42
-
43
37
  /** @protected */
44
38
  render() {
45
39
  return html`
46
- <div id="backdrop" part="backdrop" hidden></div>
47
40
  <div part="overlay" id="overlay">
48
41
  <div part="content" id="content"><slot></slot></div>
49
42
  </div>
50
43
  `;
51
44
  }
52
-
53
- requestContentUpdate() {
54
- super.requestContentUpdate();
55
-
56
- this.toggleAttribute('hidden', this.textContent.trim() === '');
57
- }
58
45
  }
59
46
 
60
47
  defineCustomElement(TooltipOverlay);
@@ -9,6 +9,17 @@ import { TooltipMixin } from './vaadin-tooltip-mixin.js';
9
9
 
10
10
  export { TooltipPosition } from './vaadin-tooltip-mixin.js';
11
11
 
12
+ /**
13
+ * Fired when the tooltip text content is changed.
14
+ */
15
+ export type TooltipContentChangedEvent = CustomEvent<{ content: string }>;
16
+
17
+ export interface TooltipCustomEventMap {
18
+ 'content-changed': TooltipContentChangedEvent;
19
+ }
20
+
21
+ export interface TooltipEventMap extends HTMLElementEventMap, TooltipCustomEventMap {}
22
+
12
23
  /**
13
24
  * `<vaadin-tooltip>` is a Web Component for creating tooltips.
14
25
  *
@@ -17,23 +28,35 @@ export { TooltipPosition } from './vaadin-tooltip-mixin.js';
17
28
  * <vaadin-tooltip text="Click to save changes" for="confirm"></vaadin-tooltip>
18
29
  * ```
19
30
  *
31
+ * ### Markdown Support
32
+ *
33
+ * The tooltip supports rendering Markdown content by setting the `markdown` property:
34
+ *
35
+ * ```html
36
+ * <button id="info">Info</button>
37
+ * <vaadin-tooltip
38
+ * text="**Important:** Click to view *detailed* information"
39
+ * markdown
40
+ * for="info">
41
+ * </vaadin-tooltip>
42
+ * ```
43
+ *
20
44
  * ### Styling
21
45
  *
22
- * `<vaadin-tooltip>` uses `<vaadin-tooltip-overlay>` internal
23
- * themable component as the actual visible overlay.
46
+ * The following shadow DOM parts are available for styling:
24
47
  *
25
- * See [`<vaadin-overlay>`](#/elements/vaadin-overlay) documentation
26
- * for `<vaadin-tooltip-overlay>` parts.
48
+ * Part name | Description
49
+ * ----------- | ---------------
50
+ * `overlay` | The overlay element
51
+ * `content` | The overlay content element
27
52
  *
28
53
  * The following state attributes are available for styling:
29
54
  *
30
55
  * Attribute | Description
31
56
  * -----------------|----------------------------------------
57
+ * `markdown` | Reflects the `markdown` property value.
32
58
  * `position` | Reflects the `position` property value.
33
59
  *
34
- * Note: the `theme` attribute value set on `<vaadin-tooltip>` is
35
- * propagated to the internal `<vaadin-tooltip-overlay>` component.
36
- *
37
60
  * ### Custom CSS Properties
38
61
  *
39
62
  * The following custom CSS properties are available on the `<vaadin-tooltip>` element:
@@ -46,6 +69,8 @@ export { TooltipPosition } from './vaadin-tooltip-mixin.js';
46
69
  * `--vaadin-tooltip-offset-end` | Used as an offset when the tooltip is aligned horizontally before the target
47
70
  *
48
71
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
72
+ *
73
+ * @fires {CustomEvent} content-changed - Fired when the tooltip text content is changed.
49
74
  */
50
75
  declare class Tooltip extends TooltipMixin(ThemePropertyMixin(ElementMixin(HTMLElement))) {
51
76
  /**
@@ -65,6 +90,18 @@ declare class Tooltip extends TooltipMixin(ThemePropertyMixin(ElementMixin(HTMLE
65
90
  * except for those that have hover delay configured using property.
66
91
  */
67
92
  static setDefaultHoverDelay(hoverDelay: number): void;
93
+
94
+ addEventListener<K extends keyof TooltipEventMap>(
95
+ type: K,
96
+ listener: (this: Tooltip, ev: TooltipEventMap[K]) => void,
97
+ options?: AddEventListenerOptions | boolean,
98
+ ): void;
99
+
100
+ removeEventListener<K extends keyof TooltipEventMap>(
101
+ type: K,
102
+ listener: (this: Tooltip, ev: TooltipEventMap[K]) => void,
103
+ options?: EventListenerOptions | boolean,
104
+ ): void;
68
105
  }
69
106
 
70
107
  declare global {
@@ -20,23 +20,35 @@ import { TooltipMixin } from './vaadin-tooltip-mixin.js';
20
20
  * <vaadin-tooltip text="Click to save changes" for="confirm"></vaadin-tooltip>
21
21
  * ```
22
22
  *
23
+ * ### Markdown Support
24
+ *
25
+ * The tooltip supports rendering Markdown content by setting the `markdown` property:
26
+ *
27
+ * ```html
28
+ * <button id="info">Info</button>
29
+ * <vaadin-tooltip
30
+ * text="**Important:** Click to view *detailed* information"
31
+ * markdown
32
+ * for="info">
33
+ * </vaadin-tooltip>
34
+ * ```
35
+ *
23
36
  * ### Styling
24
37
  *
25
- * `<vaadin-tooltip>` uses `<vaadin-tooltip-overlay>` internal
26
- * themable component as the actual visible overlay.
38
+ * The following shadow DOM parts are available for styling:
27
39
  *
28
- * See [`<vaadin-overlay>`](#/elements/vaadin-overlay) documentation
29
- * for `<vaadin-tooltip-overlay>` parts.
40
+ * Part name | Description
41
+ * ----------- | ---------------
42
+ * `overlay` | The overlay element
43
+ * `content` | The overlay content element
30
44
  *
31
45
  * The following state attributes are available for styling:
32
46
  *
33
47
  * Attribute | Description
34
48
  * -----------------|----------------------------------------
49
+ * `markdown` | Reflects the `markdown` property value.
35
50
  * `position` | Reflects the `position` property value.
36
51
  *
37
- * Note: the `theme` attribute value set on `<vaadin-tooltip>` is
38
- * propagated to the internal `<vaadin-tooltip-overlay>` component.
39
- *
40
52
  * ### Custom CSS Properties
41
53
  *
42
54
  * The following custom CSS properties are available on the `<vaadin-tooltip>` element:
@@ -50,6 +62,8 @@ import { TooltipMixin } from './vaadin-tooltip-mixin.js';
50
62
  *
51
63
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
52
64
  *
65
+ * @fires {CustomEvent} content-changed - Fired when the tooltip text content is changed.
66
+ *
53
67
  * @customElement
54
68
  * @extends HTMLElement
55
69
  * @mixes ElementMixin
@@ -64,7 +78,7 @@ class Tooltip extends TooltipMixin(ThemePropertyMixin(ElementMixin(PolylitMixin(
64
78
  static get styles() {
65
79
  return css`
66
80
  :host {
67
- display: none;
81
+ display: contents;
68
82
  }
69
83
  `;
70
84
  }
@@ -76,22 +90,24 @@ class Tooltip extends TooltipMixin(ThemePropertyMixin(ElementMixin(PolylitMixin(
76
90
  return html`
77
91
  <vaadin-tooltip-overlay
78
92
  id="overlay"
79
- .renderer="${this._renderer}"
80
93
  .owner="${this}"
81
94
  theme="${ifDefined(this._theme)}"
82
- .opened="${this._isConnected && (this.manual ? this.opened : this._autoOpened)}"
95
+ .opened="${this._isConnected && this.opened}"
83
96
  .positionTarget="${this.target}"
84
97
  .position="${effectivePosition}"
85
98
  ?no-horizontal-overlap="${this.__computeNoHorizontalOverlap(effectivePosition)}"
86
99
  ?no-vertical-overlap="${this.__computeNoVerticalOverlap(effectivePosition)}"
87
100
  .horizontalAlign="${this.__computeHorizontalAlign(effectivePosition)}"
88
101
  .verticalAlign="${this.__computeVerticalAlign(effectivePosition)}"
102
+ @click="${this.__onOverlayClick}"
103
+ @mousedown="${this.__onOverlayMouseDown}"
89
104
  @mouseenter="${this.__onOverlayMouseEnter}"
90
105
  @mouseleave="${this.__onOverlayMouseLeave}"
91
106
  modeless
107
+ ?markdown="${this.markdown}"
108
+ exportparts="overlay, content"
109
+ ><slot name="overlay"></slot
92
110
  ></vaadin-tooltip-overlay>
93
-
94
- <slot name="sr-label"></slot>
95
111
  `;
96
112
  }
97
113
  }
package/vaadin-tooltip.js CHANGED
@@ -1,3 +1,3 @@
1
- import './theme/lumo/vaadin-tooltip.js';
1
+ import './src/vaadin-tooltip.js';
2
2
 
3
3
  export * from './src/vaadin-tooltip.js';
package/web-types.json CHANGED
@@ -1,26 +1,15 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/tooltip",
4
- "version": "25.0.0-alpha2",
4
+ "version": "25.0.0-alpha21",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
8
8
  "elements": [
9
9
  {
10
10
  "name": "vaadin-tooltip",
11
- "description": "`<vaadin-tooltip>` is a Web Component for creating tooltips.\n\n```html\n<button id=\"confirm\">Confirm</button>\n<vaadin-tooltip text=\"Click to save changes\" for=\"confirm\"></vaadin-tooltip>\n```\n\n### Styling\n\n`<vaadin-tooltip>` uses `<vaadin-tooltip-overlay>` internal\nthemable component as the actual visible overlay.\n\nSee [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha2/#/elements/vaadin-overlay) documentation\nfor `<vaadin-tooltip-overlay>` parts.\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------|----------------------------------------\n`position` | Reflects the `position` property value.\n\nNote: the `theme` attribute value set on `<vaadin-tooltip>` is\npropagated to the internal `<vaadin-tooltip-overlay>` component.\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available on the `<vaadin-tooltip>` element:\n\nCustom CSS property | Description\n---------------------------------|-------------\n`--vaadin-tooltip-offset-top` | Used as an offset when the tooltip is aligned vertically below the target\n`--vaadin-tooltip-offset-bottom` | Used as an offset when the tooltip is aligned vertically above the target\n`--vaadin-tooltip-offset-start` | Used as an offset when the tooltip is aligned horizontally after the target\n`--vaadin-tooltip-offset-end` | Used as an offset when the tooltip is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
11
+ "description": "`<vaadin-tooltip>` is a Web Component for creating tooltips.\n\n```html\n<button id=\"confirm\">Confirm</button>\n<vaadin-tooltip text=\"Click to save changes\" for=\"confirm\"></vaadin-tooltip>\n```\n\n### Markdown Support\n\nThe tooltip supports rendering Markdown content by setting the `markdown` property:\n\n```html\n<button id=\"info\">Info</button>\n<vaadin-tooltip\n text=\"**Important:** Click to view *detailed* information\"\n markdown\n for=\"info\">\n</vaadin-tooltip>\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n----------- | ---------------\n`overlay` | The overlay element\n`content` | The overlay content element\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------|----------------------------------------\n`markdown` | Reflects the `markdown` property value.\n`position` | Reflects the `position` property value.\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available on the `<vaadin-tooltip>` element:\n\nCustom CSS property | Description\n---------------------------------|-------------\n`--vaadin-tooltip-offset-top` | Used as an offset when the tooltip is aligned vertically below the target\n`--vaadin-tooltip-offset-bottom` | Used as an offset when the tooltip is aligned vertically above the target\n`--vaadin-tooltip-offset-start` | Used as an offset when the tooltip is aligned horizontally after the target\n`--vaadin-tooltip-offset-end` | Used as an offset when the tooltip is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
12
12
  "attributes": [
13
- {
14
- "name": "overlay-class",
15
- "description": "A space-delimited list of CSS class names to set on the overlay element.\nThis property does not affect other CSS class names set manually via JS.\n\nNote, if the CSS class name was set with this property, clearing it will\nremove it from the overlay, even if the same class name was also added\nmanually, e.g. by using `classList.add()` in the `renderer` function.",
16
- "value": {
17
- "type": [
18
- "string",
19
- "null",
20
- "undefined"
21
- ]
22
- }
23
- },
24
13
  {
25
14
  "name": "position",
26
15
  "description": "Position of the overlay with respect to the target.\nSupported values: `top-start`, `top`, `top-end`,\n`bottom-start`, `bottom`, `bottom-end`, `start-top`,\n`start`, `start-bottom`, `end-top`, `end`, `end-bottom`.",
@@ -89,7 +78,7 @@
89
78
  },
90
79
  {
91
80
  "name": "opened",
92
- "description": "When true, the tooltip is opened programmatically.\nOnly works if `manual` is set to `true`.",
81
+ "description": "When true, the tooltip is opened.\nIn manual mode, this can be set programmatically.\nIn automatic mode, this is set automatically by internal logic.",
93
82
  "value": {
94
83
  "type": [
95
84
  "boolean",
@@ -109,6 +98,17 @@
109
98
  ]
110
99
  }
111
100
  },
101
+ {
102
+ "name": "markdown",
103
+ "description": "When enabled, the tooltip text is rendered as Markdown.\n\n**Note:** Using Markdown is discouraged if accessibility of the tooltip\ncontent is essential, as semantics of the rendered HTML content\n(headers, lists, ...) will not be conveyed to assistive technologies.",
104
+ "value": {
105
+ "type": [
106
+ "boolean",
107
+ "null",
108
+ "undefined"
109
+ ]
110
+ }
111
+ },
112
112
  {
113
113
  "name": "theme",
114
114
  "description": "The theme variants to apply to the component.",
@@ -123,17 +123,6 @@
123
123
  ],
124
124
  "js": {
125
125
  "properties": [
126
- {
127
- "name": "overlayClass",
128
- "description": "A space-delimited list of CSS class names to set on the overlay element.\nThis property does not affect other CSS class names set manually via JS.\n\nNote, if the CSS class name was set with this property, clearing it will\nremove it from the overlay, even if the same class name was also added\nmanually, e.g. by using `classList.add()` in the `renderer` function.",
129
- "value": {
130
- "type": [
131
- "string",
132
- "null",
133
- "undefined"
134
- ]
135
- }
136
- },
137
126
  {
138
127
  "name": "position",
139
128
  "description": "Position of the overlay with respect to the target.\nSupported values: `top-start`, `top`, `top-end`,\n`bottom-start`, `bottom`, `bottom-end`, `start-top`,\n`start`, `start-bottom`, `end-top`, `end`, `end-bottom`.",
@@ -246,7 +235,7 @@
246
235
  },
247
236
  {
248
237
  "name": "opened",
249
- "description": "When true, the tooltip is opened programmatically.\nOnly works if `manual` is set to `true`.",
238
+ "description": "When true, the tooltip is opened.\nIn manual mode, this can be set programmatically.\nIn automatic mode, this is set automatically by internal logic.",
250
239
  "value": {
251
240
  "type": [
252
241
  "boolean",
@@ -276,9 +265,25 @@
276
265
  "undefined"
277
266
  ]
278
267
  }
268
+ },
269
+ {
270
+ "name": "markdown",
271
+ "description": "When enabled, the tooltip text is rendered as Markdown.\n\n**Note:** Using Markdown is discouraged if accessibility of the tooltip\ncontent is essential, as semantics of the rendered HTML content\n(headers, lists, ...) will not be conveyed to assistive technologies.",
272
+ "value": {
273
+ "type": [
274
+ "boolean",
275
+ "null",
276
+ "undefined"
277
+ ]
278
+ }
279
279
  }
280
280
  ],
281
- "events": []
281
+ "events": [
282
+ {
283
+ "name": "content-changed",
284
+ "description": "Fired when the tooltip text content is changed."
285
+ }
286
+ ]
282
287
  }
283
288
  }
284
289
  ]
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/tooltip",
4
- "version": "25.0.0-alpha2",
4
+ "version": "25.0.0-alpha21",
5
5
  "description-markup": "markdown",
6
6
  "framework": "lit",
7
7
  "framework-config": {
@@ -16,7 +16,7 @@
16
16
  "elements": [
17
17
  {
18
18
  "name": "vaadin-tooltip",
19
- "description": "`<vaadin-tooltip>` is a Web Component for creating tooltips.\n\n```html\n<button id=\"confirm\">Confirm</button>\n<vaadin-tooltip text=\"Click to save changes\" for=\"confirm\"></vaadin-tooltip>\n```\n\n### Styling\n\n`<vaadin-tooltip>` uses `<vaadin-tooltip-overlay>` internal\nthemable component as the actual visible overlay.\n\nSee [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha2/#/elements/vaadin-overlay) documentation\nfor `<vaadin-tooltip-overlay>` parts.\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------|----------------------------------------\n`position` | Reflects the `position` property value.\n\nNote: the `theme` attribute value set on `<vaadin-tooltip>` is\npropagated to the internal `<vaadin-tooltip-overlay>` component.\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available on the `<vaadin-tooltip>` element:\n\nCustom CSS property | Description\n---------------------------------|-------------\n`--vaadin-tooltip-offset-top` | Used as an offset when the tooltip is aligned vertically below the target\n`--vaadin-tooltip-offset-bottom` | Used as an offset when the tooltip is aligned vertically above the target\n`--vaadin-tooltip-offset-start` | Used as an offset when the tooltip is aligned horizontally after the target\n`--vaadin-tooltip-offset-end` | Used as an offset when the tooltip is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
19
+ "description": "`<vaadin-tooltip>` is a Web Component for creating tooltips.\n\n```html\n<button id=\"confirm\">Confirm</button>\n<vaadin-tooltip text=\"Click to save changes\" for=\"confirm\"></vaadin-tooltip>\n```\n\n### Markdown Support\n\nThe tooltip supports rendering Markdown content by setting the `markdown` property:\n\n```html\n<button id=\"info\">Info</button>\n<vaadin-tooltip\n text=\"**Important:** Click to view *detailed* information\"\n markdown\n for=\"info\">\n</vaadin-tooltip>\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n----------- | ---------------\n`overlay` | The overlay element\n`content` | The overlay content element\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------|----------------------------------------\n`markdown` | Reflects the `markdown` property value.\n`position` | Reflects the `position` property value.\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available on the `<vaadin-tooltip>` element:\n\nCustom CSS property | Description\n---------------------------------|-------------\n`--vaadin-tooltip-offset-top` | Used as an offset when the tooltip is aligned vertically below the target\n`--vaadin-tooltip-offset-bottom` | Used as an offset when the tooltip is aligned vertically above the target\n`--vaadin-tooltip-offset-start` | Used as an offset when the tooltip is aligned horizontally after the target\n`--vaadin-tooltip-offset-end` | Used as an offset when the tooltip is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
20
20
  "extension": true,
21
21
  "attributes": [
22
22
  {
@@ -28,14 +28,14 @@
28
28
  },
29
29
  {
30
30
  "name": "?opened",
31
- "description": "When true, the tooltip is opened programmatically.\nOnly works if `manual` is set to `true`.",
31
+ "description": "When true, the tooltip is opened.\nIn manual mode, this can be set programmatically.\nIn automatic mode, this is set automatically by internal logic.",
32
32
  "value": {
33
33
  "kind": "expression"
34
34
  }
35
35
  },
36
36
  {
37
- "name": ".overlayClass",
38
- "description": "A space-delimited list of CSS class names to set on the overlay element.\nThis property does not affect other CSS class names set manually via JS.\n\nNote, if the CSS class name was set with this property, clearing it will\nremove it from the overlay, even if the same class name was also added\nmanually, e.g. by using `classList.add()` in the `renderer` function.",
37
+ "name": "?markdown",
38
+ "description": "When enabled, the tooltip text is rendered as Markdown.\n\n**Note:** Using Markdown is discouraged if accessibility of the tooltip\ncontent is essential, as semantics of the rendered HTML content\n(headers, lists, ...) will not be conveyed to assistive technologies.",
39
39
  "value": {
40
40
  "kind": "expression"
41
41
  }
@@ -116,6 +116,13 @@
116
116
  "value": {
117
117
  "kind": "expression"
118
118
  }
119
+ },
120
+ {
121
+ "name": "@content-changed",
122
+ "description": "Fired when the tooltip text content is changed.",
123
+ "value": {
124
+ "kind": "expression"
125
+ }
119
126
  }
120
127
  ]
121
128
  }
@@ -1,42 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright (c) 2022 - 2025 Vaadin Ltd.
4
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
- */
6
- import { css } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
7
-
8
- export const tooltipOverlayStyles = css`
9
- [part='overlay'] {
10
- max-width: 40ch;
11
- }
12
-
13
- [part='content'] {
14
- white-space: pre-wrap;
15
- }
16
-
17
- :host([position^='top'][top-aligned]) [part='overlay'],
18
- :host([position^='bottom'][top-aligned]) [part='overlay'] {
19
- margin-top: var(--vaadin-tooltip-offset-top, 0);
20
- }
21
-
22
- :host([position^='top'][bottom-aligned]) [part='overlay'],
23
- :host([position^='bottom'][bottom-aligned]) [part='overlay'] {
24
- margin-bottom: var(--vaadin-tooltip-offset-bottom, 0);
25
- }
26
-
27
- :host([position^='start'][start-aligned]) [part='overlay'],
28
- :host([position^='end'][start-aligned]) [part='overlay'] {
29
- margin-inline-start: var(--vaadin-tooltip-offset-start, 0);
30
- }
31
-
32
- :host([position^='start'][end-aligned]) [part='overlay'],
33
- :host([position^='end'][end-aligned]) [part='overlay'] {
34
- margin-inline-end: var(--vaadin-tooltip-offset-end, 0);
35
- }
36
-
37
- @media (forced-colors: active) {
38
- [part='overlay'] {
39
- outline: 1px dashed;
40
- }
41
- }
42
- `;
@@ -1,3 +0,0 @@
1
- import '@vaadin/vaadin-lumo-styles/color.js';
2
- import '@vaadin/vaadin-lumo-styles/style.js';
3
- import '@vaadin/vaadin-lumo-styles/typography.js';
@@ -1,27 +0,0 @@
1
- import '@vaadin/vaadin-lumo-styles/color.js';
2
- import '@vaadin/vaadin-lumo-styles/style.js';
3
- import '@vaadin/vaadin-lumo-styles/typography.js';
4
- import { overlay } from '@vaadin/vaadin-lumo-styles/mixins/overlay.js';
5
- import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
6
-
7
- const tooltipOverlay = css`
8
- :host {
9
- --vaadin-tooltip-offset-top: var(--lumo-space-xs);
10
- --vaadin-tooltip-offset-bottom: var(--lumo-space-xs);
11
- --vaadin-tooltip-offset-start: var(--lumo-space-xs);
12
- --vaadin-tooltip-offset-end: var(--lumo-space-xs);
13
- }
14
-
15
- [part='overlay'] {
16
- background: var(--lumo-base-color) linear-gradient(var(--lumo-contrast-5pct), var(--lumo-contrast-5pct));
17
- color: var(--lumo-body-text-color);
18
- font-size: var(--lumo-font-size-xs);
19
- line-height: var(--lumo-line-height-s);
20
- }
21
-
22
- [part='content'] {
23
- padding: var(--lumo-space-xs) var(--lumo-space-s);
24
- }
25
- `;
26
-
27
- registerStyles('vaadin-tooltip-overlay', [overlay, tooltipOverlay], { moduleId: 'lumo-tooltip-overlay' });
@@ -1,2 +0,0 @@
1
- import './vaadin-tooltip-styles.js';
2
- import '../../src/vaadin-tooltip.js';
@@ -1,2 +0,0 @@
1
- import './vaadin-tooltip-styles.js';
2
- import '../../src/vaadin-tooltip.js';