Skip to content

Commit

Permalink
fix(core/menu-item): update title when slot changes (#539)
Browse files Browse the repository at this point in the history
Co-authored-by: Daniel Leroux <daniel.leroux@siemens.com>
  • Loading branch information
goncalosard and danielleroux committed May 23, 2023
1 parent 2b7a170 commit a36e82a
Show file tree
Hide file tree
Showing 18 changed files with 208 additions and 97 deletions.
14 changes: 11 additions & 3 deletions packages/core/component-doc.json
Original file line number Diff line number Diff line change
Expand Up @@ -4818,6 +4818,9 @@
"ix-burger-menu",
"ix-menu-item",
"ix-dropdown"
],
"ix-menu-item": [
"ix-icon"
]
},
"props": [
Expand Down Expand Up @@ -5695,12 +5698,17 @@
"usage": {},
"docs": "",
"docsTags": [],
"encapsulation": "scoped",
"encapsulation": "shadow",
"dependents": [
"ix-menu"
],
"dependencies": [],
"dependencies": [
"ix-icon"
],
"dependencyGraph": {
"ix-menu-item": [
"ix-icon"
],
"ix-menu": [
"ix-menu-item"
]
Expand Down Expand Up @@ -5784,7 +5792,7 @@
"mutable": false,
"attr": "notifications",
"reflectToAttr": false,
"docs": "Show notification cound on tab",
"docs": "Show notification count on tab",
"docsTags": [],
"values": [
{
Expand Down
19 changes: 19 additions & 0 deletions packages/core/scss/mixins/shadow-dom/_hover.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* SPDX-FileCopyrightText: 2023 Siemens AG
*
* SPDX-License-Identifier: MIT
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
@mixin ghost-hover-pressed {
:host:not(.disabled):not(:disabled).hover,
:host:not(.disabled):not(:disabled):hover {
background-color: var(--theme-ghost--background--hover);
}

:host:not(.disabled):not(:disabled).active,
:host:not(.disabled):not(:disabled):active {
background-color: var(--theme-ghost--background--active);
}
}
4 changes: 2 additions & 2 deletions packages/core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1031,7 +1031,7 @@ export namespace Components {
*/
"home": boolean;
/**
* Show notification cound on tab
* Show notification count on tab
*/
"notifications": number;
/**
Expand Down Expand Up @@ -3521,7 +3521,7 @@ declare namespace LocalJSX {
*/
"home"?: boolean;
/**
* Show notification cound on tab
* Show notification count on tab
*/
"notifications"?: number;
/**
Expand Down
124 changes: 68 additions & 56 deletions packages/core/src/components/menu-item/menu-item.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
position: relative;
display: block;
cursor: pointer;
@include ghost-hover-pressed;

height: 3rem;
min-height: 3rem;
max-height: 3rem;

.tab {
display: flex;
Expand All @@ -24,6 +27,8 @@
height: 3rem;
z-index: 500;
padding-left: 0.875rem;

@include ghost-hover-pressed;
}

i.glyph {
Expand All @@ -46,14 +51,14 @@
.notification {
display: inline-flex;
position: absolute;
top: -$small-space;
right: -50%;
top: 0.25rem;
left: 1.75rem;

.pill {
display: inline-flex;
justify-content: center;
align-items: center;
height: 1rem;
height: 0.5rem;
min-width: 1rem;
position: relative;
border-radius: 6.25rem;
Expand All @@ -74,74 +79,81 @@
margin: 0 1.25rem;
user-select: none;
}
}

&.active,
&.selected {
.tab {
background-color: var(--theme-nav-item-primary--background--selected);
}

.tab::before {
content: '';
background-color: var(--theme-nav-item-primary--border-color--selected);
height: 3rem;
width: 0.25rem;
left: 0;
position: absolute;
}
:host(.active),
:host(.selected) {
.tab {
background-color: var(--theme-nav-item-primary--background--selected);
}

.tab > .glyph {
color: var(--theme-nav-item-primary-icon--color--selected);
}
.tab::before {
content: '';
background-color: var(--theme-nav-item-primary--border-color--selected);
height: 3rem;
width: 0.25rem;
left: 0;
position: absolute;
}

&.disabled {
color: var(--theme-color-weak-text);
pointer-events: none;
cursor: default;
.tab > .glyph {
color: var(--theme-nav-item-primary-icon--color--selected);
}
}

.tab > .glyph {
color: var(--theme-color-weak-text);
}
:host(.disabled) {
color: var(--theme-color-weak-text);
pointer-events: none;
cursor: default;

.tab-text {
color: var(--theme-color-weak-text);
}
.tab > .glyph {
color: var(--theme-color-weak-text);
}

&.home-tab,
&[slot='home'] {
margin-bottom: 1.5rem;
.tab-text {
color: var(--theme-color-weak-text);
}
}

&.bottom-tab,
&[slot='bottom'] {
$bottom-height: 2.25rem;
:host(.home-tab),
:host([slot='home']) {
margin-bottom: 1.5rem;
}

height: $bottom-height;
:host(.bottom-tab),
:host([slot='bottom']) {
$bottom-height: 2.25rem;

.tab {
height: $bottom-height;
}
min-height: $bottom-height;
height: $bottom-height;
max-height: $bottom-height;

.tab::before {
height: $bottom-height;
background-color: transparent;
}
.tab {
height: $bottom-height;
}

&.active,
&.selected {
.tab {
background-color: var(--theme-nav-item-secondary--background--selected);
}
.tab::before {
height: $bottom-height;
background-color: transparent;
}

&:hover {
background-color: var(--theme-nav-item-secondary--background--selected);
}
&.active,
&.selected {
&:hover {
background-color: var(--theme-nav-item-secondary--background--selected);
}

&:active {
background-color: var(--theme-nav-item-secondary--background--selected);
}
&:active {
background-color: var(--theme-nav-item-secondary--background--selected);
}
}
}

:host(.bottom-tab.active),
:host(.bottom-tab.selected),
:host(.active[slot='bottom']),
:host(.selected[slot='bottom']) {
.tab {
background-color: var(--theme-nav-item-secondary--background--selected);
}
}
44 changes: 28 additions & 16 deletions packages/core/src/components/menu-item/menu-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
*/

import { Component, Element, h, Host, Prop, State } from '@stencil/core';
import { createMutationObserver } from '../utils/mutation-observer';

@Component({
tag: 'ix-menu-item',
styleUrl: 'menu-item.scss',
scoped: true,
shadow: true,
})
export class MenuItem {
/**
Expand All @@ -35,7 +36,7 @@ export class MenuItem {
@Prop() tabIcon = 'document';

/**
* Show notification cound on tab
* Show notification count on tab
*/
@Prop() notifications: number;

Expand All @@ -53,15 +54,27 @@ export class MenuItem {

@State() title: string;

get tabLabel() {
return this.hostElement.querySelector('.tab-text');
private observer: MutationObserver;

componentWillRender() {
this.title = this.hostElement.innerText;
}

connectedCallback() {
this.observer = createMutationObserver(() => {
this.title = this.hostElement.innerText;
});

this.observer.observe(this.hostElement, {
subtree: true,
childList: true,
characterData: true,
});
}

componentDidRender() {
const spanElement = this.tabLabel;
const newTitle = spanElement.innerHTML.replace('&amp;', '&');
if (this.title !== newTitle) {
this.title = newTitle;
disconnectedCallback() {
if (this.observer) {
this.observer.disconnect();
}
}

Expand All @@ -76,13 +89,12 @@ export class MenuItem {
}}
>
<li class="tab" title={this.title}>
<i class={`glyph glyph-${this.tabIcon}`}>
<div class="notification">
{this.notifications ? (
<div class="pill">{this.notifications}</div>
) : null}
</div>
</i>
<ix-icon name={this.tabIcon}></ix-icon>
<div class="notification">
{this.notifications ? (
<div class="pill">{this.notifications}</div>
) : null}
</div>
<span class="tab-text text-default">
<slot></slot>
</span>
Expand Down
64 changes: 64 additions & 0 deletions packages/core/src/components/menu-item/test/menu-item.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* SPDX-FileCopyrightText: 2023 Siemens AG
*
* SPDX-License-Identifier: MIT
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { newSpecPage } from '@stencil/core/testing';
import { MenuItem } from '../menu-item';

import { createMutationObserver } from '../../utils/mutation-observer';
jest.mock('../../utils/mutation-observer');

describe('ix-menu-item', () => {
beforeEach(() => {
//@ts-ignore
createMutationObserver = jest.fn(() => ({
observe: jest.fn(),
}));
});
it('should have a title', async () => {
const page = await newSpecPage({
components: [MenuItem],
html: `<ix-menu-item>Example Title</ix-menu-item>`,
});

await page.waitForChanges();

const item = page.doc.querySelector('ix-menu-item');

const li = item.shadowRoot.querySelector('li');

expect(li.title).toBe('Example Title');
});

it('should have a title from innerText', async () => {
const page = await newSpecPage({
components: [MenuItem],
html: `<ix-menu-item><span>Example Title</span></ix-menu-item>`,
});

await page.waitForChanges();

const item = page.doc.querySelector('ix-menu-item');

const li = item.shadowRoot.querySelector('li');

expect(li.title).toBe('Example Title');
});

it('should change title after content change', async () => {
const page = await newSpecPage({
components: [MenuItem],
html: `<ix-menu-item>Example Title</ix-menu-item>`,
});

await page.waitForChanges();
const item = page.doc.querySelector('ix-menu-item');
item.innerText = 'Updated Title';
const li = item.shadowRoot.querySelector('li');
expect(li.title).toStrictEqual('Example Title');
});
});
Loading

0 comments on commit a36e82a

Please sign in to comment.