Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
5736d8f
update animation logic and fix focus and trigger style delay
myrta2302 Nov 3, 2025
137d4fc
add animation prop to breadcrumbs
myrta2302 Nov 3, 2025
12c1ebe
update documentation examples
myrta2302 Nov 3, 2025
49b054d
Merge branch 'main' into 6538-bug-fix-post-menu-animation
myrta2302 Nov 3, 2025
7d49eb2
restore toggleMenu emit
myrta2302 Nov 3, 2025
acc0a7e
revert test
myrta2302 Nov 3, 2025
69c496a
Merge branch 'main' into 6538-bug-fix-post-menu-animation
myrta2302 Nov 4, 2025
7eb2f39
Merge branch 'main' into 6538-bug-fix-post-menu-animation
myrta2302 Nov 4, 2025
c82051b
update animation props logic
myrta2302 Nov 4, 2025
013d70d
revert file
myrta2302 Nov 4, 2025
e39b70d
emit events also for no animation case
myrta2302 Nov 4, 2025
698b33b
show control only for menu variant
myrta2302 Nov 4, 2025
799d860
fix e2e error
myrta2302 Nov 4, 2025
aec4869
add changeset
myrta2302 Nov 4, 2025
eab4e5f
review comments update
myrta2302 Nov 6, 2025
46ba2f7
changeset update
myrta2302 Nov 6, 2025
947679b
minor
myrta2302 Nov 6, 2025
f5dac59
generalize animation run
myrta2302 Nov 6, 2025
6f2e62f
fix e2e error
myrta2302 Nov 6, 2025
7328a02
minor
myrta2302 Nov 6, 2025
ad74696
fix e2e error
myrta2302 Nov 6, 2025
46d9592
minor
myrta2302 Nov 6, 2025
a7d1ca4
update
myrta2302 Nov 6, 2025
87ab0af
identation error
myrta2302 Nov 6, 2025
3e79ea0
Merge branch 'main' into 6538-bug-fix-post-menu-animation
myrta2302 Nov 6, 2025
00b54f1
fix tooltip misync
myrta2302 Nov 7, 2025
1fad5bc
tooltip fix and obsolete focus logic removal
myrta2302 Nov 7, 2025
53c41f5
fix e2e test error
myrta2302 Nov 7, 2025
afe29ae
revert console logs
myrta2302 Nov 7, 2025
c855b0b
lint error again
myrta2302 Nov 7, 2025
68fd70c
Merge branch 'main' into 6538-bug-fix-post-menu-animation
myrta2302 Nov 10, 2025
64d07bb
remove obsolete logic
myrta2302 Nov 10, 2025
3feb44f
revert file
myrta2302 Nov 10, 2025
5370cf2
revert adding props in language switch and breadcrumbs
myrta2302 Nov 13, 2025
17ec978
Update seven-breads-press.md
myrta2302 Nov 13, 2025
29bac1c
revert files
myrta2302 Nov 13, 2025
1ce729a
Merge branch 'main' into 6538-bug-fix-post-menu-animation
myrta2302 Nov 13, 2025
c2857ce
update post-menu animation
myrta2302 Nov 13, 2025
877f53a
updated popovercontainer
myrta2302 Nov 13, 2025
010d01d
lint error
myrta2302 Nov 13, 2025
31c0035
update
myrta2302 Nov 13, 2025
2251b43
lint error
myrta2302 Nov 13, 2025
6b991e2
Merge branch 'main' into 6538-bug-fix-post-menu-animation
myrta2302 Nov 21, 2025
b401d79
update animation type check
myrta2302 Nov 24, 2025
a522200
update check
myrta2302 Nov 24, 2025
9e4859c
add validattion calls
myrta2302 Nov 24, 2025
5b47f20
Merge branch 'main' into 6538-bug-fix-post-menu-animation
myrta2302 Nov 24, 2025
cc818b3
remove animation prop from menu-button
myrta2302 Nov 27, 2025
a4d874c
Merge branch 'main' into 6538-bug-fix-post-menu-animation
myrta2302 Dec 8, 2025
526bbbd
Update post-popovercontainer.tsx
myrta2302 Dec 8, 2025
e984179
Update post-popovercontainer.tsx
myrta2302 Dec 8, 2025
73e82c4
Apply suggestion from @alizedebray
myrta2302 Dec 8, 2025
60af7f7
remove animation prop from popovercontainer
myrta2302 Dec 8, 2025
15a1115
remove tooltip animation prop
myrta2302 Dec 8, 2025
c6e4130
update read.me
myrta2302 Dec 8, 2025
63a5391
revert files
myrta2302 Dec 8, 2025
0e21e37
Merge branch 'main' into 6538-bug-fix-post-menu-animation
myrta2302 Dec 8, 2025
5333219
components.d.ts
myrta2302 Dec 8, 2025
f6eacb9
Merge branch 'main' into 6538-bug-fix-post-menu-animation
myrta2302 Dec 8, 2025
bef878a
Merge branch 'main' into 6538-bug-fix-post-menu-animation
myrta2302 Dec 9, 2025
836306e
enable tooltip animation
myrta2302 Dec 9, 2025
7880fb5
add changeset
myrta2302 Dec 9, 2025
93da67d
Merge branch 'main' into 6617-animation-not-actually-applied-to-post-โ€ฆ
myrta2302 Dec 9, 2025
c19a101
Merge branch '6538-bug-fix-post-menu-animation' into 6617-animation-nโ€ฆ
myrta2302 Dec 9, 2025
64e2f00
Merge branch 'main' into 6617-animation-not-actually-applied-to-post-โ€ฆ
myrta2302 Dec 9, 2025
de27e1d
Merge branch '6617-animation-not-actually-applied-to-post-tooltip-andโ€ฆ
myrta2302 Dec 9, 2025
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
5 changes: 5 additions & 0 deletions .changeset/salty-papers-share.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@swisspost/design-system-components': minor
---

Enabled the open animation for the `<post-tooltip>` component.
5 changes: 5 additions & 0 deletions .changeset/seven-breads-press.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@swisspost/design-system-components': minor
---

Enabled pop-in animations for the concatenated `post-breadcrumbs`, the `post-language-menu`, and the header's user menu components.
20 changes: 1 addition & 19 deletions packages/components/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -445,11 +445,6 @@ export namespace Components {
"for"?: string;
}
interface PostPopovercontainer {
/**
* Animation style
* @default null
*/
"animation"?: 'pop-in' | null;
/**
* Whether or not to display a little pointer arrow
* @default false
Expand All @@ -475,7 +470,7 @@ export namespace Components {
"safeSpace"?: 'triangle' | 'trapezoid';
/**
* Programmatically display the popovercontainer
* @param target A focusable element inside the <post-popover-trigger> component that controls the popover
* @param target A focusable element inside the trigger component that controls the popover
*/
"show": (target: HTMLElement) => Promise<void>;
/**
Expand Down Expand Up @@ -566,10 +561,6 @@ export namespace Components {
"toggled": boolean;
}
interface PostTooltip {
/**
* Choose a tooltip animation
*/
"animation"?: 'pop-in';
/**
* Whether or not to display a little pointer arrow
* @default false
Expand Down Expand Up @@ -1431,11 +1422,6 @@ declare namespace LocalJSX {
"for"?: string;
}
interface PostPopovercontainer {
/**
* Animation style
* @default null
*/
"animation"?: 'pop-in' | null;
/**
* Whether or not to display a little pointer arrow
* @default false
Expand Down Expand Up @@ -1565,10 +1551,6 @@ declare namespace LocalJSX {
"toggled"?: boolean;
}
interface PostTooltip {
/**
* Choose a tooltip animation
*/
"animation"?: 'pop-in';
/**
* Whether or not to display a little pointer arrow
* @default false
Expand Down
9 changes: 4 additions & 5 deletions packages/components/src/components/post-menu/post-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export class PostMenu {

@EventFrom('post-popovercontainer')
private readonly handlePostShown = (event: CustomEvent<{ first?: boolean }>) => {
// Only for the first open
// Only for the first open
if (event.detail.first) {
// Add "menu" and "menuitem" aria roles and aria-label
this.host.setAttribute('role', 'menu');
Expand All @@ -164,10 +164,9 @@ export class PostMenu {
};

@EventFrom('post-popovercontainer')
private readonly handlePostToggled = (event: CustomEvent<{ isOpen: boolean }>) => {
this.isVisible = event.detail.isOpen;
private readonly handlePostBeforeToggle = (event: CustomEvent<{ willOpen: boolean }>) => {
this.isVisible = event.detail.willOpen;
this.toggleMenu.emit(this.isVisible);

if (this.isVisible) {
this.lastFocusedElement = this.root?.activeElement as HTMLElement;
requestAnimationFrame(() => {
Expand Down Expand Up @@ -249,7 +248,7 @@ export class PostMenu {
<Host data-version={version}>
<post-popovercontainer
onPostShow={this.handlePostShown}
onPostToggle={this.handlePostToggled}
onPostBeforeToggle={this.handlePostBeforeToggle}
placement={this.placement}
ref={e => (this.popoverRef = e)}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ export class PostPopover {
*/
@Method()
async show(target: HTMLElement) {
this.popoverRef.show(target);
await this.popoverRef.show(target);
this.focusFirstEl();
}

/**
Expand All @@ -75,10 +76,13 @@ export class PostPopover {
@Method()
async toggle(target: HTMLElement, force?: boolean) {
await this.popoverRef.toggle(target, force);
this.focusFirstEl();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we avoid calling this function when we toggle to false?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I 'm not sure. I had already thought about it, but currently post-menu toggle() calls it like this - without the force: this.popoverRef.toggle(target). Would you prefer updating the post-menu?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, that was not my intention, but it would be good if it does the exact same thing.

I just had a look into your PR and I think we can do the following to optimize this functionality:

async toggle(target: HTMLElement, force?: boolean) {
  // you can expect the popoverRef.toggle function to return the current state (after toggling), no matter if we call it with a `force` parameter or not ;) 
  const isOpen = await this.popoverRef.toggle(target, force);
  if (isOpen) this.focusFirstEl();
}

This is only a micro improvement reguarding performance, but it could save us from unwanted side-effects.

}

private focusFirstEl() {
const focusableChildren = getDeepFocusableChildren(this.host);

// find first focusable element
// Find first focusable element
const firstFocusable = focusableChildren[0];

if (firstFocusable) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ interface PopoverElement {
togglePopover: (force?: boolean) => boolean;
}

const ANIMATIONS = {
'pop-in': popIn,
} as const;

export type AnimationName = keyof typeof ANIMATIONS;

export type PostPopoverElement = HTMLElement & PopoverElement;

/**
Expand Down Expand Up @@ -115,11 +121,6 @@ export class PostPopovercontainer {
*/
@Prop() readonly edgeGap?: number = 8;

/**
* Animation style
*/
@Prop() readonly animation?: 'pop-in' | null = null;

/**
* Whether or not to display a little pointer arrow
*/
Expand All @@ -130,6 +131,7 @@ export class PostPopovercontainer {
* Enables a safespace through which the cursor can be moved without the popover being disabled
*/
@Prop({ reflect: true }) readonly safeSpace?: 'triangle' | 'trapezoid';

@Watch('placement')
validatePlacement() {
checkEmptyOrOneOf(this, 'placement', PLACEMENT_TYPES);
Expand All @@ -145,6 +147,11 @@ export class PostPopovercontainer {
checkEmptyOrOneOf(this, 'safeSpace', ['triangle', 'trapezoid']);
}

/**
* Animation style
*/
private readonly animation: AnimationName = 'pop-in';

/**
* Updates cursor position for safe space feature when popover is open.
* Sets CSS custom properties for dynamic styling of safe area.
Expand All @@ -164,6 +171,9 @@ export class PostPopovercontainer {
}

componentDidLoad() {
this.validatePlacement();
this.validateEdgeGap();
this.validateSafeSpace();
this.host.addEventListener('beforetoggle', this.handleToggle.bind(this));
}

Expand All @@ -176,7 +186,7 @@ export class PostPopovercontainer {

/**
* Programmatically display the popovercontainer
* @param target A focusable element inside the <post-popover-trigger> component that controls the popover
* @param target A focusable element inside the trigger component that controls the popover
*/
@Method()
async show(target: HTMLElement) {
Expand Down Expand Up @@ -224,16 +234,18 @@ export class PostPopovercontainer {
this.startAutoupdates();

if (content) {
// Only run animation and emit related events if animation is defined
if (this.animation === null) {
const animationFn = ANIMATIONS[this.animation];

// Only run the animation if it corresponds to a valid, registered animation function
if (typeof animationFn === 'function') {
this.runOpenAnimation(animationFn, content);
} else {
// No animation case
this.postBeforeToggle.emit({ willOpen: true });
this.postBeforeShow.emit({ first: this.hasOpenedOnce });
this.postToggle.emit({ isOpen: true });
this.postShow.emit({ first: this.hasOpenedOnce });
if (this.hasOpenedOnce) this.hasOpenedOnce = false;
} else {
this.runOpenAnimation(content);
}
}

Expand All @@ -254,12 +266,6 @@ export class PostPopovercontainer {
window.removeEventListener('mousemove', this.mouseTrackingHandler.bind(this));
}

// Cancel any running animation
if (this.animation !== null && this.currentAnimation) {
this.currentAnimation.cancel();
this.currentAnimation = null;
}

this.postBeforeToggle.emit({ willOpen: false });
this.postToggle.emit({ isOpen: false });
this.postHide.emit();
Expand All @@ -269,11 +275,23 @@ export class PostPopovercontainer {
* Runs the animation and emits the toggle/show/hide events in the correct timing
*/

private async runOpenAnimation(element: HTMLElement) {
private async runOpenAnimation(
animationFn: (el: HTMLElement) => Animation | undefined,
element: HTMLElement,
) {
let animation: Animation | undefined;

try {
animation = popIn(element);
animation = animationFn(element);
if (!animation) {
// Fallback: no animation, just emit open events directly
this.postBeforeToggle.emit({ willOpen: true });
this.postBeforeShow.emit({ first: this.hasOpenedOnce });
this.postToggle.emit({ isOpen: true });
this.postShow.emit({ first: this.hasOpenedOnce });

return;
}

this.currentAnimation = animation;

Expand Down Expand Up @@ -323,6 +341,7 @@ export class PostPopovercontainer {
* an influence on popovercontainer positioning
*/
private startAutoupdates() {
if (!this.eventTarget || !this.host) return;
this.clearAutoUpdate = autoUpdate(
this.eventTarget,
this.host,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

| Property | Attribute | Description | Type | Default |
| ----------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| `animation` | `animation` | Animation style | `"pop-in"` | `null` |
| `arrow` | `arrow` | Whether or not to display a little pointer arrow | `boolean` | `false` |
| `edgeGap` | `edge-gap` | Gap between the edge of the page and the popovercontainer | `number` | `8` |
| `placement` | `placement` | Defines the placement of the popovercontainer according to the floating-ui options available at https://floating-ui.com/docs/computePosition#placement. Popovercontainers are automatically flipped to the opposite side if there is not enough available space and are shifted towards the viewport if they would overlap edge boundaries. | `"bottom" \| "bottom-end" \| "bottom-start" \| "left" \| "left-end" \| "left-start" \| "right" \| "right-end" \| "right-start" \| "top" \| "top-end" \| "top-start"` | `'top'` |
Expand Down Expand Up @@ -43,9 +42,9 @@ Programmatically display the popovercontainer

#### Parameters

| Name | Type | Description |
| -------- | ------------- | ----------------------------------------------------------------------------------------- |
| `target` | `HTMLElement` | A focusable element inside the <post-popover-trigger> component that controls the popover |
| Name | Type | Description |
| -------- | ------------- | -------------------------------------------------------------------------- |
| `target` | `HTMLElement` | A focusable element inside the trigger component that controls the popover |

#### Returns

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,7 @@ export class PostTooltip {
* Whether or not to display a little pointer arrow
*/
@Prop() readonly arrow?: boolean = false;
/**
* Choose a tooltip animation
*/
@Prop() readonly animation?: 'pop-in';

/**
* Indicates the open state of the tooltip
*/
Expand All @@ -60,7 +57,7 @@ export class PostTooltip {
@Method()
async show(target: HTMLElement) {
if (this.open) return;
this.popoverRef.show(target);
await this.popoverRef.show(target);
}

/**
Expand All @@ -85,8 +82,10 @@ export class PostTooltip {
* Set the open state based on the toggle event.
* @param e Popovercontainer toggle event
*/
private handleToggle(e: PostPopovercontainerCustomEvent<{ isOpen: boolean; first?: boolean }>) {
this.open = e.detail.isOpen;
private handleBeforeToggle(
e: PostPopovercontainerCustomEvent<{ willOpen: boolean; first?: boolean }>,
) {
this.open = e.detail.willOpen;
}

render() {
Expand All @@ -98,9 +97,8 @@ export class PostTooltip {
class={popoverClass}
role="tooltip"
arrow={this.arrow}
animation={this.animation}
placement={this.placement}
onPostToggle={e => this.handleToggle(e)}
onPostBeforeToggle={e => this.handleBeforeToggle(e)}
ref={(el: HTMLPostPopovercontainerElement) => (this.popoverRef = el)}
>
<slot></slot>
Expand Down
Loading
Loading