fix: Fix z-index rendering issue when card is expanded (#2274)

- Closes #2155
This commit is contained in:
Dermot Duffy
2025-12-09 23:45:07 -08:00
committed by GitHub
parent 252ead62dc
commit 639c5c3e4b
4 changed files with 51 additions and 6 deletions
+6
View File
@@ -1,3 +1,4 @@
import { setOrRemoveAttribute } from '../utils/basic';
import { CardExpandAPI } from './types'; import { CardExpandAPI } from './types';
export class ExpandManager { export class ExpandManager {
@@ -28,6 +29,11 @@ export class ExpandManager {
this._expanded = expanded; this._expanded = expanded;
this._setConditionState(); this._setConditionState();
setOrRemoveAttribute(
this._api.getCardElementManager().getElement(),
expanded,
'expanded',
);
this._api.getCardElementManager().update(); this._api.getCardElementManager().update();
} }
+6 -2
View File
@@ -36,8 +36,12 @@
// from other cards. Tip: Best way to test this is with multiple Advanced Camera // from other cards. Tip: Best way to test this is with multiple Advanced Camera
// Cards, opening a submenu on the 1st (e.g. media players) and verifying the // Cards, opening a submenu on the 1st (e.g. media players) and verifying the
// menu of the 2nd card is not visible through the opened submenu on the 1st. // menu of the 2nd card is not visible through the opened submenu on the 1st.
:host(:not(:hover)) { :host(:not(:hover):not([expanded])) {
z-index: #{$z-index-card-flatten}; z-index: auto;
// Create a new stacking context to prevent z-index issues with children
// "breaking out" of the card.
isolation: isolate;
} }
advanced-camera-card-loading { advanced-camera-card-loading {
-3
View File
@@ -18,6 +18,3 @@ $z-index-submenu: 5;
$z-index-menu: 4; $z-index-menu: 4;
$z-index-drawer: 3; $z-index-drawer: 3;
$z-index-status-bar: 2; $z-index-status-bar: 2;
// The base z-index when the card is not hovered over. See note in card.scss .
$z-index-card-flatten: 0;
+39 -1
View File
@@ -1,7 +1,8 @@
import { describe, expect, it, vi } from 'vitest'; import { describe, expect, it, vi } from 'vitest';
import { ExpandManager } from '../../src/card-controller/expand-manager'; import { ExpandManager } from '../../src/card-controller/expand-manager';
import { createCardAPI } from '../test-utils'; import { createCardAPI, createLitElement } from '../test-utils';
// @vitest-environment jsdom
describe('ExpandManager', () => { describe('ExpandManager', () => {
it('should construct', () => { it('should construct', () => {
const api = createCardAPI(); const api = createCardAPI();
@@ -19,6 +20,8 @@ describe('ExpandManager', () => {
it('should set expanded', () => { it('should set expanded', () => {
const api = createCardAPI(); const api = createCardAPI();
const element = createLitElement();
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
vi.mocked(api.getFullscreenManager().isInFullscreen).mockReturnValue(true); vi.mocked(api.getFullscreenManager().isInFullscreen).mockReturnValue(true);
const manager = new ExpandManager(api); const manager = new ExpandManager(api);
@@ -28,10 +31,13 @@ describe('ExpandManager', () => {
expect(api.getFullscreenManager().setFullscreen).toBeCalledWith(false); expect(api.getFullscreenManager().setFullscreen).toBeCalledWith(false);
expect(api.getConditionStateManager().setState).toBeCalledWith({ expand: true }); expect(api.getConditionStateManager().setState).toBeCalledWith({ expand: true });
expect(api.getCardElementManager().update).toBeCalled(); expect(api.getCardElementManager().update).toBeCalled();
expect(element.hasAttribute('expanded')).toBeTruthy();
}); });
it('should not exit fullscreen when not in fullscreen', () => { it('should not exit fullscreen when not in fullscreen', () => {
const api = createCardAPI(); const api = createCardAPI();
const element = createLitElement();
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
vi.mocked(api.getFullscreenManager().isInFullscreen).mockReturnValue(false); vi.mocked(api.getFullscreenManager().isInFullscreen).mockReturnValue(false);
const manager = new ExpandManager(api); const manager = new ExpandManager(api);
@@ -42,13 +48,45 @@ describe('ExpandManager', () => {
it('should toggle expanded', () => { it('should toggle expanded', () => {
const api = createCardAPI(); const api = createCardAPI();
const element = createLitElement();
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
vi.mocked(api.getFullscreenManager().isInFullscreen).mockReturnValue(false); vi.mocked(api.getFullscreenManager().isInFullscreen).mockReturnValue(false);
const manager = new ExpandManager(api); const manager = new ExpandManager(api);
manager.toggleExpanded(); manager.toggleExpanded();
expect(manager.isExpanded()).toBeTruthy(); expect(manager.isExpanded()).toBeTruthy();
expect(element.hasAttribute('expanded')).toBeTruthy();
manager.toggleExpanded(); manager.toggleExpanded();
expect(manager.isExpanded()).toBeFalsy(); expect(manager.isExpanded()).toBeFalsy();
expect(element.hasAttribute('expanded')).toBeFalsy();
});
it('should set expanded attribute on card element when expanded', () => {
const api = createCardAPI();
const element = createLitElement();
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
vi.mocked(api.getFullscreenManager().isInFullscreen).mockReturnValue(false);
const manager = new ExpandManager(api);
expect(element.hasAttribute('expanded')).toBeFalsy();
manager.setExpanded(true);
expect(element.hasAttribute('expanded')).toBeTruthy();
});
it('should remove expanded attribute on card element when collapsed', () => {
const api = createCardAPI();
const element = createLitElement();
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
vi.mocked(api.getFullscreenManager().isInFullscreen).mockReturnValue(false);
const manager = new ExpandManager(api);
manager.setExpanded(true);
expect(element.hasAttribute('expanded')).toBeTruthy();
manager.setExpanded(false);
expect(element.hasAttribute('expanded')).toBeFalsy();
}); });
}); });