diff options
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/style.css')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/style.css | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/style.css b/packages/meshbay-hub/src/meshbay_hub/static/style.css index f46e5c2..5642262 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/style.css +++ b/packages/meshbay-hub/src/meshbay_hub/static/style.css @@ -4167,6 +4167,8 @@ h2 .gn-owner, h3 .gn-owner { font-size: 0.55em; } .music-tile-slot { min-height: 200px; } .music-card { + /* The dots button floats over the cover's top-right corner. */ + position: relative; cursor: pointer; border-radius: 8px; overflow: hidden; @@ -4288,6 +4290,25 @@ h2 .gn-owner, h3 .gn-owner { font-size: 0.55em; } cursor: pointer; text-align: left; } +/* The row holds two controls — play it, and its menu — so it is a div, and + the play action is the button inside it. A button cannot contain another + button: the browser reparents the inner one and the row comes apart. + music-player.js's queue panel has no menu and is still a plain button, which + is why `cursor` stays on the row rather than moving to the child. */ +.music-track-main { + display: flex; + align-items: center; + gap: 10px; + flex: 1; + min-width: 0; + padding: 0; + border: none; + background: none; + color: inherit; + font: inherit; + text-align: left; + cursor: pointer; +} .music-track-row:hover { background: var(--bg-raised); border-color: var(--border); } .music-track-row.active { border-color: var(--accent); color: var(--accent); } .music-track-no { width: 24px; flex-shrink: 0; color: var(--text-dim); text-align: right; } @@ -5000,3 +5021,123 @@ h2 .gn-owner, h3 .gn-owner { font-size: 0.55em; } white-space: nowrap; border: 0; } + +/* ── Pop-up menus (menu.js) ──────────────────────────────────────────────── + One panel, opened at a point, for right-click on a cover and for the dots + button beside a track. `position: fixed` because the coordinates come from + a pointer or a `getBoundingClientRect()` — both viewport-relative, and an + absolutely-positioned panel would be offset by whatever happens to be + scrolled. menu.js measures and flips it; nothing here knows where it goes. + docs/playlists.md §10.1. */ + +.ctx-menu { + position: fixed; + /* Above everything, modals included: this menu is opened *from* the album + detail overlay, and `.video-overlay` is itself `position: fixed` at 200. + Equal values would leave it to DOM order, which is not a decision. */ + z-index: 300; + min-width: 220px; + max-width: calc(100vw - 16px); + /* A playlist's tracklist expands inside this panel rather than flying out + sideways, so it can be far taller than the window. Same answer the + account menu's language list already has. */ + max-height: calc(100vh - 16px); + overflow-x: hidden; + overflow-y: auto; + padding: 4px 0; + background: var(--bg-surface); + border: 1px solid var(--border); + border-radius: 10px; + box-shadow: var(--shadow-lg); +} + +.ctx-menu-item { + display: flex; + align-items: center; + gap: 10px; + width: 100%; + padding: 9px 14px; + border: none; + background: none; + color: var(--text); + font: inherit; + font-size: 0.9em; + text-align: left; + cursor: pointer; +} +.ctx-menu-item:hover:not(:disabled) { background: var(--sidebar-hover); } +.ctx-menu-item:disabled { color: var(--text-dim); cursor: default; } +.ctx-menu-item.danger { color: var(--error); } + +.ctx-menu-icon { width: 16px; height: 16px; flex-shrink: 0; } +.ctx-menu-label { + flex: 1; + /* A track title is arbitrarily long and the panel is not: one line, cut, + rather than a menu as wide as the longest filename in the library. */ + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.ctx-menu-hint { color: var(--text-dim); font-size: 0.85em; flex-shrink: 0; } +.ctx-menu-caret { + width: 14px; height: 14px; flex-shrink: 0; + color: var(--text-dim); + transition: transform 0.15s; +} +.ctx-menu-caret.flip { transform: rotate(180deg); } + +.ctx-menu-divider { height: 1px; background: var(--border); margin: 4px 0; } + +.ctx-menu-empty { + padding: 8px 14px; + color: var(--text-dim); + font-size: 0.85em; +} + +/* The dots button on a cover or a track row. Revealed on hover where there is + a pointer to hover with, and permanently visible where there is not — a + touchscreen has no hover state, and this is the *only* way in there. */ +.ctx-dots { + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + width: 28px; height: 28px; + padding: 0; + border: none; + border-radius: 6px; + background: none; + color: var(--text-dim); + cursor: pointer; + opacity: 0; + transition: opacity 0.12s, background 0.12s; +} +.ctx-dots svg { width: 18px; height: 18px; } +.ctx-dots:hover { background: var(--sidebar-hover); color: var(--text); } +.ctx-dots:focus-visible { opacity: 1; outline: 2px solid var(--border-focus); } +.music-card:hover .ctx-dots, +.music-track-row:hover .ctx-dots { opacity: 1; } + +@media (hover: none), (pointer: coarse) { + .ctx-dots { opacity: 1; } +} + +/* On a cover, floated over the top-right corner rather than taking a row of + its own — the grid's tiles are sized by their art. */ +.music-card-dots { + position: absolute; + top: 6px; right: 6px; + background: rgba(0, 0, 0, 0.55); + color: #fff; + backdrop-filter: blur(2px); +} +.music-card-dots:hover { background: rgba(0, 0, 0, 0.75); color: #fff; } + +/* A flat folder row expands on click; its menu button sits in the same row and + must not take the whole width with it. */ +.video-flat-row .ctx-dots { margin-left: auto; } +.video-flat-row .ctx-dots + .video-flat-chevron { margin-left: 8px; } + +/* "Play all" and the album's menu, side by side under the cover. */ +.music-detail-actions { display: flex; align-items: center; gap: 6px; } +.music-detail-actions .ctx-dots { opacity: 1; } |