From 9e7e7ce5a15f8477cc74ace957e777358e789f02 Mon Sep 17 00:00:00 2001 From: Logan Date: Fri, 21 Aug 2026 02:23:48 -0400 Subject: [PATCH] feat(shell): put every menu in the app through the one surface Fourteen call sites, one tag name each and nothing else -- which is what menu-surface's shape buys: the host's panel is slotted into whichever presentation is up, so no item model, no keyboard model and no styling moved. The 48px rows come from contextMenuStyles, the one stylesheet every one of these hosts already includes, because the panel is the host's own light DOM and only the host's stylesheet can reach it. Two of the fourteen were found by the source sweep rather than by the conversion: queue-panel's add-to-playlist popup, which is a real menu. now-playing's cover preview is allowlisted instead -- it is a hover affordance in the bottom bar, so a touch device never opens it and nothing clips it. The playlist submenu had to come too, and that is the one place this change made something worse before it made it better. It is a placement="right-start" flyout anchored to its row, and making the menu full-width moved that anchor to x=0 -- so the flip put the picker at x -182 to 0, entirely off-screen, and "Add to Playlist" led nowhere at all. Before the change the row started at x~245 and the same flip landed on screen. It is a sheet now and stacks over the first, which is also why menu-shown does not re-assert focus while it is open. The three hosts that do not use ContextMenuController -- page-header's overflow menu, playlist-view's hand-rolled menu, queue-panel's picker -- bind menu-dismiss themselves, or Escape would close the sheet and leave their own open flag set. page-header is included deliberately: the clipping does not bite there, since it opens downward from the top of a full-height view, but on a phone every action of an overflowing page lives in that menu at wa-dropdown-item defaults. One surface, so there is no second answer to what a menu looks like. --- .../components/artists-view/artists-view.ts | 27 ++++++------- .../src/components/cover-grid/cover-grid.ts | 27 ++++++------- .../explore-album-details.ts | 24 ++++++------ .../explore-artist-details.ts | 24 ++++++------ .../components/explore-view/explore-view.ts | 15 ++++--- .../src/components/genres-view/genres-view.ts | 27 ++++++------- .../src/components/page-header/page-header.ts | 25 +++++++----- .../playlist-details/playlist-details.ts | 27 ++++++------- .../components/playlist-view/playlist-view.ts | 18 ++++----- .../src/components/queue-panel/queue-panel.ts | 39 +++++++++---------- .../smart-playlist-details.ts | 27 ++++++------- .../src/components/track-list/track-list.ts | 27 ++++++------- 12 files changed, 145 insertions(+), 162 deletions(-) diff --git a/frontend/src/components/artists-view/artists-view.ts b/frontend/src/components/artists-view/artists-view.ts index 16659af..3c143fe 100644 --- a/frontend/src/components/artists-view/artists-view.ts +++ b/frontend/src/components/artists-view/artists-view.ts @@ -26,14 +26,15 @@ import { contextMenuStyles, isContextMenuKey, } from '@utils/context-menu-controller.js'; -import type { ContextMenuHost } from '@utils/context-menu-controller.js'; +import type { ContextMenuHost, MenuTarget } from '@utils/context-menu-controller.js'; import { FavoritesController } from '@store/controllers/favorites-controller'; import { ViewLifecycleMixin } from '@utils/view-lifecycle'; import { RovingGridController } from '@utils/roving-grid'; import '@awesome.me/webawesome/dist/components/icon/icon.js'; import '@awesome.me/webawesome/dist/components/popup/popup.js'; -import type WaPopup from '@awesome.me/webawesome/dist/components/popup/popup.js'; +import type { MenuSurface } from '../menu-surface/menu-surface'; +import '../menu-surface/menu-surface'; import '@awesome.me/webawesome/dist/components/dropdown-item/dropdown-item.js'; import '@components/playlist-picker/playlist-picker.js'; import { dict, list } from '@utils/binding'; @@ -131,17 +132,17 @@ export class ArtistsView private contextMenuArtistId: number | null = null; @query('#context-menu') - private contextMenuPopup!: WaPopup; + private contextMenuPopup!: MenuSurface; @query('#playlist-submenu') - private playlistSubmenuPopup!: WaPopup; + private playlistSubmenuPopup!: MenuSurface; - getContextMenuPopup(): WaPopup | undefined { + getContextMenuPopup(): MenuTarget | undefined { return this.contextMenuPopup; } getPlaylistSubmenuPopup(): - | WaPopup + | MenuTarget | undefined { return this.playlistSubmenuPopup; } @@ -1336,11 +1337,8 @@ export class ArtistsView private renderContextMenu() { return html` - @@ -1434,13 +1432,12 @@ export class ArtistsView ` : nothing} - + - @@ -1468,7 +1465,7 @@ export class ArtistsView ` : nothing} - + `; } diff --git a/frontend/src/components/cover-grid/cover-grid.ts b/frontend/src/components/cover-grid/cover-grid.ts index 8e4f3de..c4580c9 100644 --- a/frontend/src/components/cover-grid/cover-grid.ts +++ b/frontend/src/components/cover-grid/cover-grid.ts @@ -23,7 +23,8 @@ import { gridColumnsFor, gridSpacingFor } from '@utils/grid-spacing'; import { queueStore } from '@store/queue-store'; import type { QueueSource } from '@store/queue-store'; import '@awesome.me/webawesome/dist/components/popup/popup.js'; -import type WaPopup from '@awesome.me/webawesome/dist/components/popup/popup.js'; +import type { MenuSurface } from '../menu-surface/menu-surface'; +import '../menu-surface/menu-surface'; import '@awesome.me/webawesome/dist/components/dropdown-item/dropdown-item.js'; import '@awesome.me/webawesome/dist/components/icon/icon.js'; import '@components/playlist-picker/playlist-picker.js'; @@ -51,7 +52,7 @@ import { ContextMenuController, isContextMenuKey, } from '@utils/context-menu-controller.js'; -import type { ContextMenuHost } from '@utils/context-menu-controller.js'; +import type { ContextMenuHost, MenuTarget } from '@utils/context-menu-controller.js'; import { FavoritesController } from '@store/controllers/favorites-controller'; import { creditLink, exploreLinkStyles } from '../../utils/explore-link'; import { creditStore } from '@store/credit-store'; @@ -415,17 +416,17 @@ export class CoverGrid splitIndex = 0; @query('#context-menu') - private contextMenuPopup!: WaPopup; + private contextMenuPopup!: MenuSurface; @query('#playlist-submenu') - private playlistSubmenuPopup!: WaPopup; + private playlistSubmenuPopup!: MenuSurface; // ContextMenuHost interface. - getContextMenuPopup(): WaPopup | undefined { + getContextMenuPopup(): MenuTarget | undefined { return this.contextMenuPopup; } - getPlaylistSubmenuPopup(): WaPopup | undefined { + getPlaylistSubmenuPopup(): MenuTarget | undefined { return this.playlistSubmenuPopup; } @@ -2087,11 +2088,8 @@ export class CoverGrid const { ctxMenu } = this; return html` - ${ctxMenu.contextMenuOpen @@ -2204,13 +2202,12 @@ export class CoverGrid ` : nothing} - + - ${ctxMenu.playlistSubmenuOpen @@ -2232,7 +2229,7 @@ export class CoverGrid ` : nothing} - + `; diff --git a/frontend/src/components/explore-album-details/explore-album-details.ts b/frontend/src/components/explore-album-details/explore-album-details.ts index 5106123..71bc799 100644 --- a/frontend/src/components/explore-album-details/explore-album-details.ts +++ b/frontend/src/components/explore-album-details/explore-album-details.ts @@ -49,9 +49,11 @@ import { contextMenuStyles, isContextMenuKey, } from '@utils/context-menu-controller.js'; -import type { ContextMenuHost } from '@utils/context-menu-controller.js'; +import type { ContextMenuHost, MenuTarget } from '@utils/context-menu-controller.js'; import '@awesome.me/webawesome/dist/components/popup/popup.js'; import type WaPopup from '@awesome.me/webawesome/dist/components/popup/popup.js'; +import type { MenuSurface } from '../menu-surface/menu-surface'; +import '../menu-surface/menu-surface'; import '@awesome.me/webawesome/dist/components/dropdown-item/dropdown-item.js'; import { dictByName } from '@utils/binding'; import type { TrackDetails } from '@components/track-details/track-details.js'; @@ -327,7 +329,7 @@ export class ExploreAlbumDetails extends LitElement implements ContextMenuHost { @state() private ctxMenuTrack: MBTrack | null = null; @query('#track-context-menu') - private contextMenuPopup!: WaPopup; + private contextMenuPopup!: MenuSurface; @query('#playlist-submenu') private playlistSubmenuPopup?: WaPopup; @@ -337,11 +339,11 @@ export class ExploreAlbumDetails extends LitElement implements ContextMenuHost { // -- ContextMenuHost interface -- - getContextMenuPopup(): WaPopup | undefined { + getContextMenuPopup(): MenuTarget | undefined { return this.contextMenuPopup; } - getPlaylistSubmenuPopup(): WaPopup | undefined { + getPlaylistSubmenuPopup(): MenuTarget | undefined { return this.playlistSubmenuPopup; } @@ -3781,11 +3783,8 @@ export class ExploreAlbumDetails extends LitElement implements ContextMenuHost { const track = this.ctxMenuTrack; return html` - ${this.ctxMenu.contextMenuOpen && track @@ -3846,13 +3845,12 @@ export class ExploreAlbumDetails extends LitElement implements ContextMenuHost { ` : nothing} - + - ${this.ctxMenu.playlistSubmenuOpen @@ -3869,7 +3867,7 @@ export class ExploreAlbumDetails extends LitElement implements ContextMenuHost { ` : nothing} - + `; } } diff --git a/frontend/src/components/explore-artist-details/explore-artist-details.ts b/frontend/src/components/explore-artist-details/explore-artist-details.ts index c981310..5c42394 100644 --- a/frontend/src/components/explore-artist-details/explore-artist-details.ts +++ b/frontend/src/components/explore-artist-details/explore-artist-details.ts @@ -61,9 +61,11 @@ import { contextMenuStyles, isContextMenuKey, } from '@utils/context-menu-controller.js'; -import type { ContextMenuHost } from '@utils/context-menu-controller.js'; +import type { ContextMenuHost, MenuTarget } from '@utils/context-menu-controller.js'; import '@awesome.me/webawesome/dist/components/popup/popup.js'; import type WaPopup from '@awesome.me/webawesome/dist/components/popup/popup.js'; +import type { MenuSurface } from '../menu-surface/menu-surface'; +import '../menu-surface/menu-surface'; import '@awesome.me/webawesome/dist/components/dropdown-item/dropdown-item.js'; import { dict, dictByName } from '@utils/binding'; import type { TrackDetails } from '@components/track-details/track-details.js'; @@ -215,7 +217,7 @@ export class ExploreArtistDetails extends LitElement implements ContextMenuHost @state() private ctxMenuTarget: ContextMenuTarget | null = null; @query('#context-menu') - private contextMenuPopup!: WaPopup; + private contextMenuPopup!: MenuSurface; @query('#playlist-submenu') private playlistSubmenuPopup?: WaPopup; @@ -233,11 +235,11 @@ export class ExploreArtistDetails extends LitElement implements ContextMenuHost // -- ContextMenuHost interface -- - getContextMenuPopup(): WaPopup | undefined { + getContextMenuPopup(): MenuTarget | undefined { return this.contextMenuPopup; } - getPlaylistSubmenuPopup(): WaPopup | undefined { + getPlaylistSubmenuPopup(): MenuTarget | undefined { return this.playlistSubmenuPopup; } @@ -2621,11 +2623,8 @@ export class ExploreArtistDetails extends LitElement implements ContextMenuHost const target = this.ctxMenuTarget; return html` - ${this.ctxMenu.contextMenuOpen && target @@ -2643,13 +2642,12 @@ export class ExploreArtistDetails extends LitElement implements ContextMenuHost ` : nothing} - + - ${this.ctxMenu.playlistSubmenuOpen @@ -2666,7 +2664,7 @@ export class ExploreArtistDetails extends LitElement implements ContextMenuHost ` : nothing} - + `; } diff --git a/frontend/src/components/explore-view/explore-view.ts b/frontend/src/components/explore-view/explore-view.ts index e3d4c63..a7bc195 100644 --- a/frontend/src/components/explore-view/explore-view.ts +++ b/frontend/src/components/explore-view/explore-view.ts @@ -37,9 +37,11 @@ import { contextMenuStyles, isContextMenuKey, } from '@utils/context-menu-controller.js'; -import type { ContextMenuHost } from '@utils/context-menu-controller.js'; +import type { ContextMenuHost, MenuTarget } from '@utils/context-menu-controller.js'; import '@awesome.me/webawesome/dist/components/popup/popup.js'; import type WaPopup from '@awesome.me/webawesome/dist/components/popup/popup.js'; +import type { MenuSurface } from '../menu-surface/menu-surface'; +import '../menu-surface/menu-surface'; import '@awesome.me/webawesome/dist/components/dropdown-item/dropdown-item.js'; import { dict, dictByName } from '@utils/binding'; import { ICON_QUEUE } from '@utils/icon-language'; @@ -206,13 +208,13 @@ export class ExploreView extends ViewLifecycleMixin(LitElement) implements Conte @state() private ctxMenuTarget: ExploreMenuTarget | null = null; @litQuery('#explore-context-menu') - private contextMenuPopup!: WaPopup; + private contextMenuPopup!: MenuSurface; // -- ContextMenuHost interface -- // No playlist submenu — same reason as the album/artist detail // pages: every action here resolves its one file lazily. - getContextMenuPopup(): WaPopup | undefined { + getContextMenuPopup(): MenuTarget | undefined { return this.contextMenuPopup; } @@ -1341,11 +1343,8 @@ export class ExploreView extends ViewLifecycleMixin(LitElement) implements Conte const owned = Boolean(target?.localId); return html` - ${this.ctxMenu.contextMenuOpen && target @@ -1374,7 +1373,7 @@ export class ExploreView extends ViewLifecycleMixin(LitElement) implements Conte ` : nothing} - + `; } diff --git a/frontend/src/components/genres-view/genres-view.ts b/frontend/src/components/genres-view/genres-view.ts index 8c0a6f7..4cea184 100644 --- a/frontend/src/components/genres-view/genres-view.ts +++ b/frontend/src/components/genres-view/genres-view.ts @@ -24,14 +24,15 @@ import { contextMenuStyles, isContextMenuKey, } from '@utils/context-menu-controller.js'; -import type { ContextMenuHost } from '@utils/context-menu-controller.js'; +import type { ContextMenuHost, MenuTarget } from '@utils/context-menu-controller.js'; import { FavoritesController } from '@store/controllers/favorites-controller'; import { ViewLifecycleMixin } from '@utils/view-lifecycle'; import { RovingGridController } from '@utils/roving-grid'; import '@awesome.me/webawesome/dist/components/icon/icon.js'; import '@awesome.me/webawesome/dist/components/popup/popup.js'; -import type WaPopup from '@awesome.me/webawesome/dist/components/popup/popup.js'; +import type { MenuSurface } from '../menu-surface/menu-surface'; +import '../menu-surface/menu-surface'; import '@awesome.me/webawesome/dist/components/dropdown-item/dropdown-item.js'; import '@components/playlist-picker/playlist-picker.js'; import { dictByName } from '@utils/binding'; @@ -137,19 +138,19 @@ export class GenresView private contextMenuGenreName: string | null = null; @query('#context-menu') - private contextMenuPopup!: WaPopup; + private contextMenuPopup!: MenuSurface; @query('#playlist-submenu') - private playlistSubmenuPopup!: WaPopup; + private playlistSubmenuPopup!: MenuSurface; // ----- ContextMenuHost interface ----- - getContextMenuPopup(): WaPopup | undefined { + getContextMenuPopup(): MenuTarget | undefined { return this.contextMenuPopup; } getPlaylistSubmenuPopup(): - | WaPopup + | MenuTarget | undefined { return this.playlistSubmenuPopup; } @@ -1176,11 +1177,8 @@ export class GenresView private renderContextMenu() { return html` - @@ -1284,13 +1282,12 @@ export class GenresView ` : nothing} - + - @@ -1318,7 +1315,7 @@ export class GenresView ` : nothing} - + `; } diff --git a/frontend/src/components/page-header/page-header.ts b/frontend/src/components/page-header/page-header.ts index d67fed1..48bba04 100644 --- a/frontend/src/components/page-header/page-header.ts +++ b/frontend/src/components/page-header/page-header.ts @@ -1,9 +1,9 @@ import { LitElement, html, css, nothing } from 'lit'; import { customElement, property, query, state } from 'lit/decorators.js'; import '@awesome.me/webawesome/dist/components/icon/icon.js'; -import '@awesome.me/webawesome/dist/components/popup/popup.js'; import '@awesome.me/webawesome/dist/components/dropdown-item/dropdown-item.js'; -import type WaPopup from '@awesome.me/webawesome/dist/components/popup/popup.js'; +import type { MenuSurface } from '../menu-surface/menu-surface'; +import '../menu-surface/menu-surface'; import { designTokens } from '../../styles/tokens.css'; import { @@ -183,8 +183,8 @@ export class PageHeader extends LitElement { @query('#page-header-overflow') private menuPanel?: HTMLElement; - @query('wa-popup') - private popup?: WaPopup; + @query('menu-surface') + private popup?: MenuSurface; private menuKeyboard = new MenuKeyboard(() => this.closeMenu()); @@ -418,7 +418,7 @@ export class PageHeader extends LitElement { outline-offset: -1px; } - wa-popup { + menu-surface { z-index: 200; } @@ -670,10 +670,17 @@ export class PageHeader extends LitElement { return html`
${this.actions.map((a) => this.renderActionButton(a))} - +
`; } diff --git a/frontend/src/components/playlist-details/playlist-details.ts b/frontend/src/components/playlist-details/playlist-details.ts index c90e7ed..9db18c4 100644 --- a/frontend/src/components/playlist-details/playlist-details.ts +++ b/frontend/src/components/playlist-details/playlist-details.ts @@ -7,7 +7,8 @@ import { } from 'lit/decorators.js'; import '@awesome.me/webawesome/dist/components/icon/icon.js'; import '@awesome.me/webawesome/dist/components/popup/popup.js'; -import type WaPopup from '@awesome.me/webawesome/dist/components/popup/popup.js'; +import type { MenuSurface } from '../menu-surface/menu-surface'; +import '../menu-surface/menu-surface'; import '@awesome.me/webawesome/dist/components/dropdown-item/dropdown-item.js'; import '@lit-labs/virtualizer'; import type { LitVirtualizer } from '@lit-labs/virtualizer'; @@ -35,7 +36,7 @@ import { contextMenuStyles, isContextMenuKey, } from '@utils/context-menu-controller.js'; -import type { ContextMenuHost } from '@utils/context-menu-controller.js'; +import type { ContextMenuHost, MenuTarget } from '@utils/context-menu-controller.js'; import { focusRovingRow, nextRovingIndex } from '@utils/roving-rows'; import { FavoritesController } from '@store/controllers/favorites-controller'; import { notificationStore } from '@store/notification-store'; @@ -145,10 +146,10 @@ export class PlaylistDetails private dragImageEl: HTMLElement | null = null; @query('#context-menu') - private contextMenuPopup!: WaPopup; + private contextMenuPopup!: MenuSurface; @query('#playlist-submenu') - private playlistSubmenuPopup!: WaPopup; + private playlistSubmenuPopup!: MenuSurface; @query('track-details') private trackDetailsDialog!: TrackDetails; @@ -163,11 +164,11 @@ export class PlaylistDetails // ContextMenuHost interface // ================================================================= - getContextMenuPopup(): WaPopup | undefined { + getContextMenuPopup(): MenuTarget | undefined { return this.contextMenuPopup; } - getPlaylistSubmenuPopup(): WaPopup | undefined { + getPlaylistSubmenuPopup(): MenuTarget | undefined { return this.playlistSubmenuPopup; } @@ -1617,11 +1618,8 @@ export class PlaylistDetails private renderContextMenu() { return html` - @@ -1783,13 +1781,12 @@ export class PlaylistDetails ` : nothing} - + - @@ -1816,7 +1813,7 @@ export class PlaylistDetails ` : nothing} - + `; } } diff --git a/frontend/src/components/playlist-view/playlist-view.ts b/frontend/src/components/playlist-view/playlist-view.ts index 0192d12..c3b56ab 100644 --- a/frontend/src/components/playlist-view/playlist-view.ts +++ b/frontend/src/components/playlist-view/playlist-view.ts @@ -2,7 +2,9 @@ import { LitElement, html, css, nothing } from 'lit'; import { customElement, state, query } from 'lit/decorators.js'; import '@awesome.me/webawesome/dist/components/icon/icon.js'; import '@awesome.me/webawesome/dist/components/popup/popup.js'; -import type WaPopup from '@awesome.me/webawesome/dist/components/popup/popup.js'; + +import type { MenuSurface } from '../menu-surface/menu-surface'; +import '../menu-surface/menu-surface'; import '@awesome.me/webawesome/dist/components/dropdown-item/dropdown-item.js'; import { @@ -140,7 +142,7 @@ export class PlaylistView extends ViewLifecycleMixin(LitElement) { private pendingDropPaths: string[] = []; @query('#playlist-context-menu') - private playlistContextMenuPopup!: WaPopup; + private playlistContextMenuPopup!: MenuSurface; @query('duplicate-tracks-dialog') private duplicateDialog!: DuplicateTracksDialog; @@ -1059,7 +1061,7 @@ export class PlaylistView extends ViewLifecycleMixin(LitElement) { ); } - private closePlaylistContextMenu() { + private closePlaylistContextMenu = () => { if (!this.playlistContextMenuOpen) return; this.menuKeyboard.close(); @@ -1072,7 +1074,7 @@ export class PlaylistView extends ViewLifecycleMixin(LitElement) { if (popup) { popup.active = false; } - } + }; private async onPlaylistContextAction( action: string, @@ -1500,13 +1502,11 @@ export class PlaylistView extends ViewLifecycleMixin(LitElement) { ` : this.renderPlaylistList()} - ${this.playlistContextMenuOpen ? html` @@ -1564,7 +1564,7 @@ export class PlaylistView extends ViewLifecycleMixin(LitElement) { ` : nothing} - + diff --git a/frontend/src/components/queue-panel/queue-panel.ts b/frontend/src/components/queue-panel/queue-panel.ts index 1621817..4dcd99e 100644 --- a/frontend/src/components/queue-panel/queue-panel.ts +++ b/frontend/src/components/queue-panel/queue-panel.ts @@ -9,7 +9,8 @@ import { } from 'lit/decorators.js'; import '@awesome.me/webawesome/dist/components/icon/icon.js'; import '@awesome.me/webawesome/dist/components/popup/popup.js'; -import type WaPopup from '@awesome.me/webawesome/dist/components/popup/popup.js'; +import type { MenuSurface } from '../menu-surface/menu-surface'; +import '../menu-surface/menu-surface'; import '@awesome.me/webawesome/dist/components/dropdown-item/dropdown-item.js'; import { QueueController } from '@store/controllers/queue-controller'; import { creditStore } from '@store/credit-store'; @@ -34,7 +35,7 @@ import { contextMenuStyles, isContextMenuKey, } from '@utils/context-menu-controller.js'; -import type { ContextMenuHost } from '@utils/context-menu-controller.js'; +import type { ContextMenuHost, MenuTarget } from '@utils/context-menu-controller.js'; import { focusRovingRow, nextRovingIndex } from '@utils/roving-rows'; import { FavoritesController } from '@store/controllers/favorites-controller'; import { @@ -140,13 +141,13 @@ export class QueuePanel private delegationAttached = false; @query('#add-to-playlist-popup') - private addToPlaylistPopup!: WaPopup; + private addToPlaylistPopup!: MenuSurface; @query('#context-menu') - private contextMenuPopup!: WaPopup; + private contextMenuPopup!: MenuSurface; @query('#playlist-submenu') - private playlistSubmenuPopup!: WaPopup; + private playlistSubmenuPopup!: MenuSurface; /** Unsubscribes the credit-arrival repaint. */ private creditsUnsub?: () => void; @@ -305,11 +306,11 @@ export class QueuePanel // ContextMenuHost interface // ================================================================= - getContextMenuPopup(): WaPopup | undefined { + getContextMenuPopup(): MenuTarget | undefined { return this.contextMenuPopup; } - getPlaylistSubmenuPopup(): WaPopup | undefined { + getPlaylistSubmenuPopup(): MenuTarget | undefined { return this.playlistSubmenuPopup; } @@ -1092,7 +1093,7 @@ export class QueuePanel } } - private closePlaylistPicker() { + private closePlaylistPicker = () => { if (!this.playlistPickerOpen) return; this.playlistPickerOpen = false; @@ -1102,7 +1103,7 @@ export class QueuePanel if (popup) { popup.active = false; } - } + }; private onPlaylistActionComplete = () => { this.closePlaylistPicker(); @@ -2042,9 +2043,11 @@ export class QueuePanel - ${this.playlistPickerOpen @@ -2060,7 +2063,7 @@ export class QueuePanel > ` : nothing} - +
- ${this.ctxMenu.contextMenuOpen @@ -2195,13 +2195,12 @@ export class QueuePanel ` : nothing} - + - ${this.ctxMenu.playlistSubmenuOpen && @@ -2224,7 +2223,7 @@ export class QueuePanel ` : nothing} - + `; diff --git a/frontend/src/components/smart-playlist-details/smart-playlist-details.ts b/frontend/src/components/smart-playlist-details/smart-playlist-details.ts index 83adde0..4b9b112 100644 --- a/frontend/src/components/smart-playlist-details/smart-playlist-details.ts +++ b/frontend/src/components/smart-playlist-details/smart-playlist-details.ts @@ -26,7 +26,7 @@ import { contextMenuStyles, isContextMenuKey, } from '@utils/context-menu-controller.js'; -import type { ContextMenuHost } from '@utils/context-menu-controller.js'; +import type { ContextMenuHost, MenuTarget } from '@utils/context-menu-controller.js'; import { focusRovingRow, nextRovingIndex } from '@utils/roving-rows'; import { FavoritesController } from '@store/controllers/favorites-controller'; import { @@ -40,7 +40,8 @@ import { } from '@utils/drag-image'; import '@awesome.me/webawesome/dist/components/icon/icon.js'; import '@awesome.me/webawesome/dist/components/popup/popup.js'; -import type WaPopup from '@awesome.me/webawesome/dist/components/popup/popup.js'; +import type { MenuSurface } from '../menu-surface/menu-surface'; +import '../menu-surface/menu-surface'; import '@awesome.me/webawesome/dist/components/dropdown-item/dropdown-item.js'; import '@lit-labs/virtualizer'; import type { LitVirtualizer } from '@lit-labs/virtualizer'; @@ -176,10 +177,10 @@ export class SmartPlaylistDetails private dragImageEl: HTMLElement | null = null; @query('#context-menu') - private contextMenuPopup!: WaPopup; + private contextMenuPopup!: MenuSurface; @query('#playlist-submenu') - private playlistSubmenuPopup!: WaPopup; + private playlistSubmenuPopup!: MenuSurface; @query('track-details') private trackDetailsDialog!: TrackDetails; @@ -188,11 +189,11 @@ export class SmartPlaylistDetails // ContextMenuHost interface // ================================================================= - getContextMenuPopup(): WaPopup | undefined { + getContextMenuPopup(): MenuTarget | undefined { return this.contextMenuPopup; } - getPlaylistSubmenuPopup(): WaPopup | undefined { + getPlaylistSubmenuPopup(): MenuTarget | undefined { return this.playlistSubmenuPopup; } @@ -1465,11 +1466,8 @@ export class SmartPlaylistDetails private renderContextMenu() { return html` - ${this.ctxMenu.contextMenuOpen @@ -1583,13 +1581,12 @@ export class SmartPlaylistDetails ` : nothing} - + - @@ -1616,7 +1613,7 @@ export class SmartPlaylistDetails ` : nothing} - + `; } } diff --git a/frontend/src/components/track-list/track-list.ts b/frontend/src/components/track-list/track-list.ts index d278389..db23e33 100644 --- a/frontend/src/components/track-list/track-list.ts +++ b/frontend/src/components/track-list/track-list.ts @@ -18,7 +18,7 @@ import { isContextMenuKey, } from '@utils/context-menu-controller.js'; -import type { ContextMenuHost } from '@utils/context-menu-controller.js'; +import type { ContextMenuHost, MenuTarget } from '@utils/context-menu-controller.js'; import { PlayerController } from '@store/controllers/player-controller'; import { SearchController } from '@store/controllers/search-controller'; import '@components/page-header/page-header'; @@ -63,7 +63,8 @@ import type { } from '@lit-labs/virtualizer'; import { flow } from '@lit-labs/virtualizer/layouts/flow.js'; import '@awesome.me/webawesome/dist/components/popup/popup.js'; -import type WaPopup from '@awesome.me/webawesome/dist/components/popup/popup.js'; +import type { MenuSurface } from '../menu-surface/menu-surface'; +import '../menu-surface/menu-surface'; import '@awesome.me/webawesome/dist/components/dropdown-item/dropdown-item.js'; import '@awesome.me/webawesome/dist/components/icon/icon.js'; import { describeError } from '@utils/describe-error'; @@ -231,18 +232,18 @@ export class TrackList private tracks: library.Track[] = []; @query('#context-menu') - private contextMenuPopup!: WaPopup; + private contextMenuPopup!: MenuSurface; @query('#playlist-submenu') - private playlistSubmenuPopup!: WaPopup; + private playlistSubmenuPopup!: MenuSurface; // -- ContextMenuHost interface -- - getContextMenuPopup(): WaPopup | undefined { + getContextMenuPopup(): MenuTarget | undefined { return this.contextMenuPopup; } - getPlaylistSubmenuPopup(): WaPopup | undefined { + getPlaylistSubmenuPopup(): MenuTarget | undefined { return this.playlistSubmenuPopup; } @@ -2323,11 +2324,8 @@ export class TrackList `} - ${this.ctxMenu.contextMenuOpen @@ -2413,13 +2411,12 @@ export class TrackList ` : nothing} - + - ${this.ctxMenu.playlistSubmenuOpen && this.selection.hasSelection @@ -2437,7 +2434,7 @@ export class TrackList ` : nothing} - + `;