ui: keep caret shadow behind menu panel
cx
This commit is contained in:
1 parent
df9798c8d8
commit
9cf345921e
1 file changed
+162
-149
+162
-149
@@ -301,175 +301,177 @@
|
|||||||
style={menuStyle}
|
style={menuStyle}
|
||||||
use:portal
|
use:portal
|
||||||
>
|
>
|
||||||
{#if hasPlayback}
|
<div class="menu-panel">
|
||||||
{#if onPlayNow}
|
{#if hasPlayback}
|
||||||
<button class="menu-item" onclick={() => handleAction(onPlayNow)}>
|
{#if onPlayNow}
|
||||||
<Play size={14} />
|
<button class="menu-item" onclick={() => handleAction(onPlayNow)}>
|
||||||
<span>Play now</span>
|
<Play size={14} />
|
||||||
</button>
|
<span>Play now</span>
|
||||||
{/if}
|
</button>
|
||||||
{#if onPlayTrackOnly}
|
|
||||||
<button class="menu-item" onclick={() => handleAction(onPlayTrackOnly)}>
|
|
||||||
<Play size={14} />
|
|
||||||
<span>Play track only</span>
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
{#if onPlayFromHere}
|
|
||||||
<button class="menu-item" onclick={() => handleAction(onPlayFromHere)}>
|
|
||||||
<Play size={14} />
|
|
||||||
<span>Play from here</span>
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
{#if onPlayNext}
|
|
||||||
<button class="menu-item" onclick={() => handleAction(onPlayNext)}>
|
|
||||||
<ListPlus size={14} />
|
|
||||||
<span>Play next</span>
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
{#if onPlayLater}
|
|
||||||
<button class="menu-item" onclick={() => handleAction(onPlayLater)}>
|
|
||||||
<ListEnd size={14} />
|
|
||||||
<span>Play later</span>
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
{#if onCreateRadio}
|
|
||||||
<button class="menu-item" onclick={() => handleAction(onCreateRadio)}>
|
|
||||||
<Radio size={14} />
|
|
||||||
<span>Create radio</span>
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if hasPlayback && (hasLibrary || hasShare || hasNav || hasDownload)}
|
|
||||||
<div class="separator"></div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if hasLibrary}
|
|
||||||
{#if onAddFavorite}
|
|
||||||
<button class="menu-item" onclick={() => handleAction(onAddFavorite)}>
|
|
||||||
<Heart size={14} />
|
|
||||||
<span>Add to favorites</span>
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
{#if onAddToPlaylist && !shouldHidePlaylistFeatures()}
|
|
||||||
<button class="menu-item" onclick={() => handleAction(onAddToPlaylist)}>
|
|
||||||
<ListMusic size={14} />
|
|
||||||
<span>Add to playlist</span>
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
{#if onRemoveFromPlaylist}
|
|
||||||
<button class="menu-item danger" onclick={() => handleAction(onRemoveFromPlaylist)}>
|
|
||||||
<Trash2 size={14} />
|
|
||||||
<span>Remove from playlist</span>
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if hasLibrary && (hasShare || hasNav)}
|
|
||||||
<div class="separator"></div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if hasShare}
|
|
||||||
<div
|
|
||||||
class="menu-item submenu-trigger"
|
|
||||||
bind:this={shareTriggerRef}
|
|
||||||
onmouseenter={() => {
|
|
||||||
shareOpen = true;
|
|
||||||
setSubmenuPosition();
|
|
||||||
}}
|
|
||||||
onclick={() => {
|
|
||||||
shareOpen = !shareOpen;
|
|
||||||
if (shareOpen) setSubmenuPosition();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Share2 size={14} />
|
|
||||||
<span>Share</span>
|
|
||||||
<ChevronRight size={14} class="chevron" />
|
|
||||||
{#if shareOpen}
|
|
||||||
<div class="submenu" bind:this={submenuEl} style={submenuStyle}>
|
|
||||||
{#if onShareQobuz}
|
|
||||||
<button class="menu-item" onclick={() => handleAction(onShareQobuz)}>
|
|
||||||
<Link size={14} />
|
|
||||||
<span>Qobuz™ link</span>
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
{#if onShareSonglink}
|
|
||||||
<button class="menu-item" onclick={() => handleAction(onShareSonglink)}>
|
|
||||||
<Link size={14} />
|
|
||||||
<span>Song.link</span>
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
{#if onPlayTrackOnly}
|
||||||
{/if}
|
<button class="menu-item" onclick={() => handleAction(onPlayTrackOnly)}>
|
||||||
|
<Play size={14} />
|
||||||
|
<span>Play track only</span>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
{#if onPlayFromHere}
|
||||||
|
<button class="menu-item" onclick={() => handleAction(onPlayFromHere)}>
|
||||||
|
<Play size={14} />
|
||||||
|
<span>Play from here</span>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
{#if onPlayNext}
|
||||||
|
<button class="menu-item" onclick={() => handleAction(onPlayNext)}>
|
||||||
|
<ListPlus size={14} />
|
||||||
|
<span>Play next</span>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
{#if onPlayLater}
|
||||||
|
<button class="menu-item" onclick={() => handleAction(onPlayLater)}>
|
||||||
|
<ListEnd size={14} />
|
||||||
|
<span>Play later</span>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
{#if onCreateRadio}
|
||||||
|
<button class="menu-item" onclick={() => handleAction(onCreateRadio)}>
|
||||||
|
<Radio size={14} />
|
||||||
|
<span>Create radio</span>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
|
||||||
{#if (hasShare || hasLibrary) && hasDownload}
|
{#if hasPlayback && (hasLibrary || hasShare || hasNav || hasDownload)}
|
||||||
<div class="separator"></div>
|
<div class="separator"></div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if hasDownload}
|
{#if hasLibrary}
|
||||||
{#if isTrackDownloaded}
|
{#if onAddFavorite}
|
||||||
|
<button class="menu-item" onclick={() => handleAction(onAddFavorite)}>
|
||||||
|
<Heart size={14} />
|
||||||
|
<span>Add to favorites</span>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
{#if onAddToPlaylist && !shouldHidePlaylistFeatures()}
|
||||||
|
<button class="menu-item" onclick={() => handleAction(onAddToPlaylist)}>
|
||||||
|
<ListMusic size={14} />
|
||||||
|
<span>Add to playlist</span>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
{#if onRemoveFromPlaylist}
|
||||||
|
<button class="menu-item danger" onclick={() => handleAction(onRemoveFromPlaylist)}>
|
||||||
|
<Trash2 size={14} />
|
||||||
|
<span>Remove from playlist</span>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if hasLibrary && (hasShare || hasNav)}
|
||||||
|
<div class="separator"></div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if hasShare}
|
||||||
<div
|
<div
|
||||||
class="menu-item submenu-trigger"
|
class="menu-item submenu-trigger"
|
||||||
bind:this={downloadTriggerRef}
|
bind:this={shareTriggerRef}
|
||||||
onmouseenter={() => {
|
onmouseenter={() => {
|
||||||
downloadOpen = true;
|
shareOpen = true;
|
||||||
shareOpen = false;
|
setSubmenuPosition();
|
||||||
setDownloadSubmenuPosition();
|
|
||||||
}}
|
}}
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
downloadOpen = !downloadOpen;
|
shareOpen = !shareOpen;
|
||||||
shareOpen = false;
|
if (shareOpen) setSubmenuPosition();
|
||||||
if (downloadOpen) setDownloadSubmenuPosition();
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CloudDownload size={14} />
|
<Share2 size={14} />
|
||||||
<span>Save for offline</span>
|
<span>Share</span>
|
||||||
<ChevronRight size={14} class="chevron" />
|
<ChevronRight size={14} class="chevron" />
|
||||||
{#if downloadOpen}
|
{#if shareOpen}
|
||||||
<div class="submenu" bind:this={downloadSubmenuEl} style={downloadSubmenuStyle}>
|
<div class="submenu" bind:this={submenuEl} style={submenuStyle}>
|
||||||
{#if onReDownload}
|
{#if onShareQobuz}
|
||||||
<button class="menu-item" onclick={() => handleAction(onReDownload)}>
|
<button class="menu-item" onclick={() => handleAction(onShareQobuz)}>
|
||||||
<RefreshCw size={14} />
|
<Link size={14} />
|
||||||
<span>Refresh offline copy</span>
|
<span>Qobuz™ link</span>
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
{#if onRemoveDownload}
|
{#if onShareSonglink}
|
||||||
<button class="menu-item danger" onclick={() => handleAction(onRemoveDownload)}>
|
<button class="menu-item" onclick={() => handleAction(onShareSonglink)}>
|
||||||
<Trash2 size={14} />
|
<Link size={14} />
|
||||||
<span>Remove offline copy</span>
|
<span>Song.link</span>
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
|
||||||
<button class="menu-item" onclick={() => handleAction(onDownload)}>
|
|
||||||
<CloudDownload size={14} />
|
|
||||||
<span>Save for offline</span>
|
|
||||||
</button>
|
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if hasDownload && hasNav}
|
{#if (hasShare || hasLibrary) && hasDownload}
|
||||||
<div class="separator"></div>
|
<div class="separator"></div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if hasNav}
|
{#if hasDownload}
|
||||||
{#if onGoToAlbum}
|
{#if isTrackDownloaded}
|
||||||
<button class="menu-item" onclick={() => handleAction(onGoToAlbum)}>
|
<div
|
||||||
<Disc3 size={14} />
|
class="menu-item submenu-trigger"
|
||||||
<span>Go to album</span>
|
bind:this={downloadTriggerRef}
|
||||||
</button>
|
onmouseenter={() => {
|
||||||
|
downloadOpen = true;
|
||||||
|
shareOpen = false;
|
||||||
|
setDownloadSubmenuPosition();
|
||||||
|
}}
|
||||||
|
onclick={() => {
|
||||||
|
downloadOpen = !downloadOpen;
|
||||||
|
shareOpen = false;
|
||||||
|
if (downloadOpen) setDownloadSubmenuPosition();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CloudDownload size={14} />
|
||||||
|
<span>Save for offline</span>
|
||||||
|
<ChevronRight size={14} class="chevron" />
|
||||||
|
{#if downloadOpen}
|
||||||
|
<div class="submenu" bind:this={downloadSubmenuEl} style={downloadSubmenuStyle}>
|
||||||
|
{#if onReDownload}
|
||||||
|
<button class="menu-item" onclick={() => handleAction(onReDownload)}>
|
||||||
|
<RefreshCw size={14} />
|
||||||
|
<span>Refresh offline copy</span>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
{#if onRemoveDownload}
|
||||||
|
<button class="menu-item danger" onclick={() => handleAction(onRemoveDownload)}>
|
||||||
|
<Trash2 size={14} />
|
||||||
|
<span>Remove offline copy</span>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<button class="menu-item" onclick={() => handleAction(onDownload)}>
|
||||||
|
<CloudDownload size={14} />
|
||||||
|
<span>Save for offline</span>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
{#if onGoToArtist}
|
|
||||||
<button class="menu-item" onclick={() => handleAction(onGoToArtist)}>
|
{#if hasDownload && hasNav}
|
||||||
<User size={14} />
|
<div class="separator"></div>
|
||||||
<span>Go to artist</span>
|
|
||||||
</button>
|
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
|
||||||
|
{#if hasNav}
|
||||||
|
{#if onGoToAlbum}
|
||||||
|
<button class="menu-item" onclick={() => handleAction(onGoToAlbum)}>
|
||||||
|
<Disc3 size={14} />
|
||||||
|
<span>Go to album</span>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
{#if onGoToArtist}
|
||||||
|
<button class="menu-item" onclick={() => handleAction(onGoToArtist)}>
|
||||||
|
<User size={14} />
|
||||||
|
<span>Go to artist</span>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
@@ -504,12 +506,17 @@
|
|||||||
.menu {
|
.menu {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
min-width: 160px;
|
min-width: 160px;
|
||||||
|
z-index: 99999;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-panel {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
background-color: var(--bg-tertiary);
|
background-color: var(--bg-tertiary);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 2px 0;
|
padding: 2px 0;
|
||||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
|
||||||
z-index: 99999;
|
|
||||||
overflow: visible;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Caret outside the menu pointing at the trigger */
|
/* Caret outside the menu pointing at the trigger */
|
||||||
@@ -536,7 +543,7 @@
|
|||||||
border-right: 9px solid var(--bg-tertiary);
|
border-right: 9px solid var(--bg-tertiary);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shadow for caret (only outward, never over the menu) */
|
/* Shadow for caret (only outward, never over the panel) */
|
||||||
.menu.open-left::before,
|
.menu.open-left::before,
|
||||||
.menu.open-right::before {
|
.menu.open-right::before {
|
||||||
content: '';
|
content: '';
|
||||||
@@ -550,6 +557,7 @@
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
filter: blur(2px);
|
filter: blur(2px);
|
||||||
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu.open-left::before {
|
.menu.open-left::before {
|
||||||
@@ -564,6 +572,11 @@
|
|||||||
border-right: 10px solid rgba(0, 0, 0, 0.9);
|
border-right: 10px solid rgba(0, 0, 0, 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menu.open-left::after,
|
||||||
|
.menu.open-right::after {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.menu-item {
|
.menu-item {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
|
|||||||
Reference in new issue
Block a user