diff --git a/CHANGELOG.md b/CHANGELOG.md index 5295ad655..6ef28c973 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,29 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [Unreleased] +## [6.1.0] - 2025-06-11 +### Added +- Date Range Picker + +### Changed +- #### Tooltip + - **Behavioral change**: Tooltip default `placement` is 'bottom' now. + - **Behavioral change**: Tooltip will not render an arrow indicator by default unless `with-arrow` is set. + - **Breaking change**: Tooltip events will no longer return its `anchor` target in its `detail` property. + + You can still access it at `event.target.anchor`. + +### Deprecated +- #### Tooltip + - `disableArrow` is deprecated. Use `withArrow | with-arrow` to render an arrow indicator. + ### Fixed - - #### Calendar & Date picker - - Incorrect date rollover for in certain scenarios [#1710](https://github.com/IgniteUI/igniteui-webcomponents/issues/1710) +- #### Calendar & Date Picker + - Incorrect date rollover for in certain scenarios [#1710](https://github.com/IgniteUI/igniteui-webcomponents/issues/1710) +- #### Combo + - Case insensitive icon styles in themes [#1728](https://github.com/IgniteUI/igniteui-webcomponents/pull/1728) +- #### Textarea + - Label height and component height override [#1715](https://github.com/IgniteUI/igniteui-webcomponents/pull/1715) ## [6.0.1] - 2025-05-28 ### Added @@ -898,6 +917,7 @@ Initial release of Ignite UI Web Components - Ripple component - Switch component +[6.1.0]: https://github.com/IgniteUI/igniteui-webcomponents/compare/6.0.1...6.1.0 [6.0.1]: https://github.com/IgniteUI/igniteui-webcomponents/compare/6.0.0...6.0.1 [6.0.0]: https://github.com/IgniteUI/igniteui-webcomponents/compare/5.4.1...6.0.0 [5.4.1]: https://github.com/IgniteUI/igniteui-webcomponents/compare/5.4.0...5.4.1 diff --git a/src/components/tooltip/tooltip.spec.ts b/src/components/tooltip/tooltip.spec.ts index f6fdfd2a5..8705ba261 100644 --- a/src/components/tooltip/tooltip.spec.ts +++ b/src/components/tooltip/tooltip.spec.ts @@ -75,9 +75,10 @@ describe('Tooltip', () => { it('is correctly initialized with its default component state', () => { expect(tooltip.dir).to.be.empty; expect(tooltip.open).to.be.false; - expect(tooltip.disableArrow).to.be.false; + expect(tooltip.disableArrow).to.be.true; + expect(tooltip.withArrow).to.be.false; expect(tooltip.offset).to.equal(6); - expect(tooltip.placement).to.equal('top'); + expect(tooltip.placement).to.equal('bottom'); expect(tooltip.anchor).to.be.undefined; expect(tooltip.showTriggers).to.equal('pointerenter'); expect(tooltip.hideTriggers).to.equal('pointerleave,click'); @@ -86,11 +87,6 @@ describe('Tooltip', () => { expect(tooltip.message).to.equal(''); }); - it('should render a default arrow', () => { - const arrow = tooltip.shadowRoot!.querySelector('#arrow'); - expect(arrow).not.to.be.null; - }); - it('is correctly rendered both in shown/hidden states', async () => { expect(tooltip.open).to.be.false; @@ -103,7 +99,6 @@ describe('Tooltip', () => { >
-
` ); @@ -120,7 +115,6 @@ describe('Tooltip', () => { >
-
` ); @@ -212,29 +206,29 @@ describe('Tooltip', () => { expect(tooltip.open).to.be.true; }); - it('should show/hide the arrow via the `disableArrow` property', async () => { - expect(tooltip.disableArrow).to.be.false; - expect(tooltip.shadowRoot!.querySelector('#arrow')).to.exist; + it('should show/hide the arrow via the `withArrow` property', async () => { + expect(tooltip.withArrow).to.be.false; + expect(tooltip.renderRoot.querySelector('#arrow')).to.be.null; - tooltip.disableArrow = true; + tooltip.withArrow = true; await elementUpdated(tooltip); - expect(tooltip.disableArrow).to.be.true; - expect(tooltip.shadowRoot!.querySelector('#arrow')).to.be.null; + expect(tooltip.withArrow).to.be.true; + expect(tooltip.renderRoot.querySelector('#arrow')).not.to.be.null; }); - it('should show/hide the arrow via the `disable-arrow` attribute', async () => { + it('should show/hide the arrow via the `with-arrow` attribute', async () => { const template = html`
- I am a tooltip + I am a tooltip
`; const container = await fixture(template); tooltip = container.querySelector(IgcTooltipComponent.tagName)!; - expect(tooltip.disableArrow).to.be.true; - expect(tooltip.shadowRoot!.querySelector('#arrow')).to.be.null; + expect(tooltip.withArrow).to.be.true; + expect(tooltip.renderRoot.querySelector('#arrow')).not.to.be.null; }); it('should provide content via the `message` property', async () => { @@ -305,7 +299,6 @@ describe('Tooltip', () => { name="input_clear" > -
` ); @@ -534,15 +527,8 @@ describe('Tooltip', () => { await showComplete(); expect(tooltip.open).to.be.true; - expect(eventSpy).calledWith('igcOpening', { - cancelable: true, - detail: defaultAnchor, - }); - - expect(eventSpy).calledWith('igcOpened', { - cancelable: false, - detail: defaultAnchor, - }); + expect(eventSpy).calledWith('igcOpening', { cancelable: true }); + expect(eventSpy).calledWith('igcOpened', { cancelable: false }); }); }); @@ -698,11 +684,11 @@ describe('Tooltip', () => { expect(eventSpy.callCount).to.equal(2); expect(eventSpy.firstCall).calledWith( state.open ? 'igcOpening' : 'igcClosing', - { cancelable: true, detail: anchor } + { cancelable: true } ); expect(eventSpy.secondCall).calledWith( state.open ? 'igcOpened' : 'igcClosed', - { cancelable: false, detail: anchor } + { cancelable: false } ); }; @@ -730,10 +716,7 @@ describe('Tooltip', () => { await showComplete(tooltip); expect(tooltip.open).to.be.false; - expect(eventSpy).calledOnceWith('igcOpening', { - cancelable: true, - detail: anchor, - }); + expect(eventSpy).calledOnceWith('igcOpening', { cancelable: true }); eventSpy.resetHistory(); @@ -749,10 +732,7 @@ describe('Tooltip', () => { await hideComplete(tooltip); expect(tooltip.open).to.be.true; - expect(eventSpy).calledOnceWith('igcClosing', { - cancelable: true, - detail: anchor, - }); + expect(eventSpy).calledOnceWith('igcClosing', { cancelable: true }); }); it('fires `igcClosed` when tooltip is hidden via Escape key', async () => { @@ -775,10 +755,7 @@ describe('Tooltip', () => { expect(tooltip.open).to.be.false; expect(eventSpy.callCount).to.equal(1); - expect(eventSpy.firstCall).calledWith('igcClosed', { - cancelable: false, - detail: anchor, - }); + expect(eventSpy.firstCall).calledWith('igcClosed', { cancelable: false }); }); }); diff --git a/src/components/tooltip/tooltip.ts b/src/components/tooltip/tooltip.ts index baac767d5..f32e5482a 100644 --- a/src/components/tooltip/tooltip.ts +++ b/src/components/tooltip/tooltip.ts @@ -1,4 +1,4 @@ -import { LitElement, html, nothing } from 'lit'; +import { LitElement, type PropertyValues, html, nothing } from 'lit'; import { property, query } from 'lit/decorators.js'; import { createRef, ref } from 'lit/directives/ref.js'; import { EaseOut } from '../../animations/easings.js'; @@ -6,7 +6,6 @@ import { addAnimationController } from '../../animations/player.js'; import { fadeOut } from '../../animations/presets/fade/index.js'; import { scaleInCenter } from '../../animations/presets/scale/index.js'; import { themes } from '../../theming/theming-decorator.js'; -import { watch } from '../common/decorators/watch.js'; import { registerComponent } from '../common/definitions/register.js'; import type { Constructor } from '../common/mixins/constructor.js'; import { EventEmitterMixin } from '../common/mixins/event-emitter.js'; @@ -21,14 +20,10 @@ import { all } from './themes/themes.js'; import { styles } from './themes/tooltip.base.css.js'; export interface IgcTooltipComponentEventMap { - /* blazorAlternateType: CustomEvent */ - igcOpening: CustomEvent; - /* blazorAlternateType: CustomEvent */ - igcOpened: CustomEvent; - /* blazorAlternateType: CustomEvent */ - igcClosing: CustomEvent; - /* blazorAlternateType: CustomEvent */ - igcClosed: CustomEvent; + igcOpening: CustomEvent; + igcOpened: CustomEvent; + igcClosing: CustomEvent; + igcClosed: CustomEvent; } type TooltipStateOptions = { @@ -143,11 +138,30 @@ export default class IgcTooltipComponent extends EventEmitterMixin< /** * Whether to disable the rendering of the arrow indicator for the tooltip. * + * @deprecated since 6.1.0. Use `with-arrow` to control the behavior of the tooltip arrow. * @attr disable-arrow * @default false */ - @property({ attribute: 'disable-arrow', type: Boolean, reflect: true }) - public disableArrow = false; + @property({ type: Boolean, attribute: 'disable-arrow' }) + public set disableArrow(value: boolean) { + this.withArrow = !value; + } + + /** + * @deprecated since 6.1.0. Use `with-arrow` to control the behavior of the tooltip arrow. + */ + public get disableArrow(): boolean { + return !this.withArrow; + } + + /** + * Whether to render an arrow indicator for the tooltip. + * + * @attr with-arrow + * @default false + */ + @property({ type: Boolean, reflect: true, attribute: 'with-arrow' }) + public withArrow = false; /** * The offset of the tooltip from the anchor in pixels. @@ -162,14 +176,18 @@ export default class IgcTooltipComponent extends EventEmitterMixin< * Where to place the floating element relative to the parent anchor element. * * @attr placement - * @default top + * @default bottom */ @property() - public placement: PopoverPlacement = 'top'; + public placement: PopoverPlacement = 'bottom'; /** * An element instance or an IDREF to use as the anchor for the tooltip. * + * @remarks + * Trying to bind to an IDREF that does not exist in the current DOM root at will not work. + * In such scenarios, it is better to get a DOM reference and pass it to the tooltip instance. + * * @attr anchor */ @property() @@ -272,20 +290,19 @@ export default class IgcTooltipComponent extends EventEmitterMixin< } } - @watch('anchor') - protected _onAnchorChange(): void { - this._controller.resolveAnchor(this.anchor); - } + protected override willUpdate(changedProperties: PropertyValues): void { + if (changedProperties.has('anchor')) { + this._controller.resolveAnchor(this.anchor); + } - @watch('sticky') - protected _onStickyChange(): void { - this._internals.role = this.sticky ? 'status' : 'tooltip'; + if (changedProperties.has('sticky')) { + this._internals.role = this.sticky ? 'status' : 'tooltip'; + } } private _emitEvent(name: keyof IgcTooltipComponentEventMap): boolean { return this.emitEvent(name, { cancelable: name === 'igcOpening' || name === 'igcClosing', - detail: this._controller.anchor, }); } @@ -416,7 +433,7 @@ export default class IgcTooltipComponent extends EventEmitterMixin< .placement=${this.placement} .offset=${this.offset} .anchor=${this._controller.anchor ?? undefined} - .arrow=${this.disableArrow ? null : this._arrowElement} + .arrow=${this.withArrow ? this._arrowElement : null} .arrowOffset=${this._arrowOffset} .shiftPadding=${8} ?open=${this.open} @@ -436,7 +453,7 @@ export default class IgcTooltipComponent extends EventEmitterMixin< ` : nothing} - ${this.disableArrow ? nothing : html`
`} + ${this.withArrow ? html`
` : nothing} `;