Skip to content

Commit

Permalink
feat(core/application-header): hide toggle menu if header used outsid…
Browse files Browse the repository at this point in the history
…e of application frame (#1449)
  • Loading branch information
danielleroux authored Sep 3, 2024
1 parent 6da25df commit f91b0a5
Show file tree
Hide file tree
Showing 22 changed files with 247 additions and 60 deletions.
5 changes: 5 additions & 0 deletions .changeset/wicked-glasses-pump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@siemens/ix': minor
---

feat(core/application-header): hide toggle menu if header used outside of application frame
12 changes: 9 additions & 3 deletions packages/angular/src/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,31 @@ export declare interface IxApplication extends Components.IxApplication {}


@ProxyCmp({
inputs: ['name']
inputs: ['name', 'showMenu']
})
@Component({
selector: 'ix-application-header',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['name'],
inputs: ['name', 'showMenu'],
})
export class IxApplicationHeader {
protected el: HTMLElement;
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
c.detach();
this.el = r.nativeElement;
proxyOutputs(this, this.el, ['menuToggle']);
}
}


export declare interface IxApplicationHeader extends Components.IxApplicationHeader {}
export declare interface IxApplicationHeader extends Components.IxApplicationHeader {
/**
* Event emitted when the menu toggle button is clicked @since 2.5.0
*/
menuToggle: EventEmitter<CustomEvent<boolean>>;
}


@ProxyCmp({
Expand Down
49 changes: 48 additions & 1 deletion packages/core/component-doc.json
Original file line number Diff line number Diff line change
Expand Up @@ -461,10 +461,57 @@
],
"optional": true,
"required": false
},
{
"name": "showMenu",
"type": "boolean",
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"mutable": true,
"attr": "show-menu",
"reflectToAttr": false,
"docs": "Controls the visibility of the menu toggle button based on the context of the application header.\n\nWhen the application header is utilized outside the application frame, the menu toggle button is displayed.\nConversely, if the header is within the application frame, this property is ineffective.",
"docsTags": [
{
"name": "since",
"text": "2.5.0"
}
],
"default": "false",
"values": [
{
"type": "boolean"
}
],
"optional": true,
"required": false
}
],
"methods": [],
"events": [],
"events": [
{
"event": "menuToggle",
"detail": "boolean",
"bubbles": true,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"cancelable": true,
"composed": true,
"docs": "Event emitted when the menu toggle button is clicked",
"docsTags": [
{
"name": "since",
"text": "2.5.0"
}
]
}
],
"styles": [],
"slots": [
{
Expand Down
30 changes: 30 additions & 0 deletions packages/core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ export namespace Components {
* Application name
*/
"name"?: string;
/**
* Controls the visibility of the menu toggle button based on the context of the application header. When the application header is utilized outside the application frame, the menu toggle button is displayed. Conversely, if the header is within the application frame, this property is ineffective.
* @since 2.5.0
*/
"showMenu"?: boolean;
}
interface IxApplicationSidebar {
}
Expand Down Expand Up @@ -2458,6 +2463,10 @@ export namespace Components {
"vertical": boolean;
}
}
export interface IxApplicationHeaderCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLIxApplicationHeaderElement;
}
export interface IxBlindCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLIxBlindElement;
Expand Down Expand Up @@ -2689,7 +2698,18 @@ declare global {
prototype: HTMLIxApplicationElement;
new (): HTMLIxApplicationElement;
};
interface HTMLIxApplicationHeaderElementEventMap {
"menuToggle": boolean;
}
interface HTMLIxApplicationHeaderElement extends Components.IxApplicationHeader, HTMLStencilElement {
addEventListener<K extends keyof HTMLIxApplicationHeaderElementEventMap>(type: K, listener: (this: HTMLIxApplicationHeaderElement, ev: IxApplicationHeaderCustomEvent<HTMLIxApplicationHeaderElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof HTMLIxApplicationHeaderElementEventMap>(type: K, listener: (this: HTMLIxApplicationHeaderElement, ev: IxApplicationHeaderCustomEvent<HTMLIxApplicationHeaderElementEventMap[K]>) => any, options?: boolean | EventListenerOptions): void;
removeEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
var HTMLIxApplicationHeaderElement: {
prototype: HTMLIxApplicationHeaderElement;
Expand Down Expand Up @@ -4169,6 +4189,16 @@ declare namespace LocalJSX {
* Application name
*/
"name"?: string;
/**
* Event emitted when the menu toggle button is clicked
* @since 2.5.0
*/
"onMenuToggle"?: (event: IxApplicationHeaderCustomEvent<boolean>) => void;
/**
* Controls the visibility of the menu toggle button based on the context of the application header. When the application header is utilized outside the application frame, the menu toggle button is displayed. Conversely, if the header is within the application frame, this property is ineffective.
* @since 2.5.0
*/
"showMenu"?: boolean;
}
interface IxApplicationSidebar {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@
import {
Component,
Element,
Event,
EventEmitter,
Fragment,
h,
Host,
Prop,
readTask,
State,
Watch,
} from '@stencil/core';
import { showAppSwitch } from '../utils/app-switch';
import { applicationLayoutService } from '../utils/application-layout';
Expand Down Expand Up @@ -45,6 +48,23 @@ export class ApplicationHeader {
*/
@Prop() name?: string;

/**
* Controls the visibility of the menu toggle button based on the context of the application header.
*
* When the application header is utilized outside the application frame, the menu toggle button is displayed.
* Conversely, if the header is within the application frame, this property is ineffective.
*
* @since 2.5.0
*/
@Prop({ mutable: true }) showMenu?: boolean = false;

/**
* Event emitted when the menu toggle button is clicked
*
* @since 2.5.0
*/
@Event() menuToggle!: EventEmitter<boolean>;

@State() breakpoint: Breakpoint = 'lg';
@State() menuExpanded = false;
@State() suppressResponsive = false;
Expand Down Expand Up @@ -90,7 +110,6 @@ export class ApplicationHeader {

this.modeDisposable = applicationLayoutService.onChange.on((mode) => {
if (this.suppressResponsive) {
this.breakpoint = 'md';
return;
}

Expand All @@ -109,6 +128,17 @@ export class ApplicationHeader {
this.modeDisposable?.dispose();
}

@Watch('applicationLayoutContext')
watchApplicationLayoutContext() {
if (this.applicationLayoutContext) {
this.showMenu = false;
}
}
@Watch('suppressResponsive')
watchSuppressResponsive() {
this.breakpoint = 'md';
}

private isLogoSlotted() {
const slotElement = this.hostElement.shadowRoot.querySelector(
'slot[name="logo"]'
Expand All @@ -131,7 +161,13 @@ export class ApplicationHeader {
}

private async onMenuClick() {
menuController.toggle();
if (this.applicationLayoutContext) {
menuController.toggle();
} else {
this.menuExpanded = !this.menuExpanded;
}

this.menuToggle.emit(this.menuExpanded);
}

private resolveContextMenuButton() {
Expand Down Expand Up @@ -176,28 +212,40 @@ export class ApplicationHeader {
}

render() {
const hasApplicationContextAvailable = !!this.applicationLayoutContext;

const showMenuByApplicationFrame =
this.breakpoint === 'sm' &&
this.suppressResponsive === false &&
hasApplicationContextAvailable;

const showApplicationSwitch =
this.applicationLayoutContext?.appSwitchConfig &&
this.breakpoint !== 'sm' &&
this.suppressResponsive === false;

return (
<Host
class={{ [`breakpoint-${this.breakpoint}`]: true }}
class={{
[`breakpoint-${this.breakpoint}`]: true,
}}
slot="application-header"
>
{this.breakpoint === 'sm' && this.suppressResponsive === false && (
{(this.showMenu || showMenuByApplicationFrame) && (
<ix-menu-expand-icon
onClick={() => this.onMenuClick()}
expanded={this.menuExpanded}
></ix-menu-expand-icon>
)}
{this.applicationLayoutContext?.appSwitchConfig &&
this.breakpoint !== 'sm' &&
this.suppressResponsive === false && (
<ix-icon-button
onClick={() => this.showAppSwitch()}
icon="apps"
ghost
class="app-switch"
></ix-icon-button>
)}
<div class="logo">
{showApplicationSwitch && (
<ix-icon-button
onClick={() => this.showAppSwitch()}
icon="apps"
ghost
class="app-switch"
></ix-icon-button>
)}
<div class={{ logo: true }}>
<slot name="logo"></slot>
</div>
<ix-typography format="body-lg" class="name">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,13 @@ regressionTest.describe('application header: basic', () => {
}
);
});

regressionTest.describe('application header: standalone', () => {
Object.keys(viewPorts).forEach((name: keyof typeof viewPorts) => {
regressionTest(`viewport ${name}`, async ({ page }) => {
await page.setViewportSize(viewPorts[name]);
await page.goto('application-header/standalone');
await expect(page).toHaveScreenshot();
});
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
57 changes: 30 additions & 27 deletions packages/core/src/tests/application-header/basic-svg/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,36 @@
<title>Stencil Component Starter</title>
</head>
<body>
<ix-application-header name="Test app name">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 184.567 138"
slot="logo"
>
<defs>
<linearGradient
id="x05mhzd7ga"
x1=".5"
x2=".5"
y2="1"
gradientUnits="objectBoundingBox"
>
<stop offset="0" stop-color="#00ffb9" />
<stop offset="1" stop-color="#0cc" />
</linearGradient>
</defs>
<path
data-name="Vereinigungsmenge 41"
d="M0 126c0-.337.014-.67.041-1H0V60a12 12 0 1 1 24 0v65h-.042c.027.329.042.663.042 1a12 12 0 0 1-24 0zm50.944 8.052a12 12 0 0 1 0-16.969L99.027 69 50.944 20.919A12 12 0 0 1 67.915 3.947L116 52.03l48.083-48.084a12 12 0 0 1 16.969 16.971L132.969 69l48.084 48.084a12 12 0 0 1-16.969 16.971L116 85.971l-48.085 48.082a12 12 0 0 1-16.971 0zM0 12a12 12 0 1 1 12 12A12 12 0 0 1 0 12z"
style="fill: url(#x05mhzd7ga)"
/>
</svg>
</ix-application-header>
<ix-application>
<ix-application-header name="Test app name">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 184.567 138"
slot="logo"
>
<defs>
<linearGradient
id="x05mhzd7ga"
x1=".5"
x2=".5"
y2="1"
gradientUnits="objectBoundingBox"
>
<stop offset="0" stop-color="#00ffb9" />
<stop offset="1" stop-color="#0cc" />
</linearGradient>
</defs>
<path
data-name="Vereinigungsmenge 41"
d="M0 126c0-.337.014-.67.041-1H0V60a12 12 0 1 1 24 0v65h-.042c.027.329.042.663.042 1a12 12 0 0 1-24 0zm50.944 8.052a12 12 0 0 1 0-16.969L99.027 69 50.944 20.919A12 12 0 0 1 67.915 3.947L116 52.03l48.083-48.084a12 12 0 0 1 16.969 16.971L132.969 69l48.084 48.084a12 12 0 0 1-16.969 16.971L116 85.971l-48.085 48.082a12 12 0 0 1-16.971 0zM0 12a12 12 0 1 1 12 12A12 12 0 0 1 0 12z"
style="fill: url(#x05mhzd7ga)"
/>
</svg>
</ix-application-header>
</ix-application>

<script src="http://127.0.0.1:8080/scripts/e2e/load-e2e-runtime.js"></script>
</body>
</html>
8 changes: 5 additions & 3 deletions packages/core/src/tests/application-header/basic/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
<title>Stencil Component Starter</title>
</head>
<body>
<ix-application-header name="Test app name">
<div slot="logo">Text Logo</div>
</ix-application-header>
<ix-application>
<ix-application-header name="Test app name">
<div slot="logo">Text Logo</div>
</ix-application-header>
</ix-application>
<script src="http://127.0.0.1:8080/scripts/e2e/load-e2e-runtime.js"></script>
</body>
</html>
Loading

0 comments on commit f91b0a5

Please sign in to comment.