Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
63 changes: 20 additions & 43 deletions src/components/tooltip/tooltip.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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;

Expand All @@ -103,7 +99,6 @@ describe('Tooltip', () => {
>
<div part="base">
<slot></slot>
<div id="arrow"></div>
</div>
</igc-popover>`
);
Expand All @@ -120,7 +115,6 @@ describe('Tooltip', () => {
>
<div part="base">
<slot></slot>
<div id="arrow"></div>
</div>
</igc-popover>`
);
Expand Down Expand Up @@ -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`
<div>
<button>Hover</button>
<igc-tooltip disable-arrow>I am a tooltip</igc-tooltip>
<igc-tooltip with-arrow>I am a tooltip</igc-tooltip>
</div>
`;
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 () => {
Expand Down Expand Up @@ -305,7 +299,6 @@ describe('Tooltip', () => {
name="input_clear"
></igc-icon>
</slot>
<div id="arrow"></div>
</div>
</igc-popover>`
);
Expand Down Expand Up @@ -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 });
});
});

Expand Down Expand Up @@ -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 }
);
};

Expand Down Expand Up @@ -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();

Expand All @@ -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 () => {
Expand All @@ -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 });
});
});

Expand Down
65 changes: 41 additions & 24 deletions src/components/tooltip/tooltip.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
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';
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';
Expand All @@ -21,14 +20,10 @@ import { all } from './themes/themes.js';
import { styles } from './themes/tooltip.base.css.js';

export interface IgcTooltipComponentEventMap {
/* blazorAlternateType: CustomEvent<void> */
igcOpening: CustomEvent<Element | null>;
/* blazorAlternateType: CustomEvent<void> */
igcOpened: CustomEvent<Element | null>;
/* blazorAlternateType: CustomEvent<void> */
igcClosing: CustomEvent<Element | null>;
/* blazorAlternateType: CustomEvent<void> */
igcClosed: CustomEvent<Element | null>;
igcOpening: CustomEvent<void>;
igcOpened: CustomEvent<void>;
igcClosing: CustomEvent<void>;
igcClosed: CustomEvent<void>;
}

type TooltipStateOptions = {
Expand Down Expand Up @@ -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.
Expand All @@ -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()
Expand Down Expand Up @@ -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<this>): 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,
});
}

Expand Down Expand Up @@ -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}
Expand All @@ -436,7 +453,7 @@ export default class IgcTooltipComponent extends EventEmitterMixin<
</slot>
`
: nothing}
${this.disableArrow ? nothing : html`<div id="arrow"></div>`}
${this.withArrow ? html`<div id="arrow"></div>` : nothing}
</div>
</igc-popover>
`;
Expand Down