mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-21 22:15:40 +00:00
fix(ui): shrink-wrap floating player bar instead of full-width strip (#969)
* fix(ui): shrink-wrap floating player bar instead of full-width strip The bar used fixed left and right insets, which stretched its background across the whole main column. Center it with max-content width so only the pill-shaped controls are painted, and soften the drop shadow. * docs: note PR #969 in changelog and settings credits
This commit is contained in:
@@ -491,6 +491,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
* Nonsense queries no longer return unrelated fuzzy matches (e.g. long repeated letters).
|
||||
|
||||
|
||||
### Floating player bar — remove full-width background strip
|
||||
|
||||
**By [@cucadmuh](https://github.com/cucadmuh), reported by Asra on the Psysonic Discord, PR [#969](https://github.com/Psychotoxical/psysonic/pull/969)**
|
||||
|
||||
* Floating mode no longer stretches the player bar between sidebar and queue with fixed `left`/`right` — only the centered pill is painted over the page instead of a full-width black band behind the rounded corners.
|
||||
|
||||
|
||||
### In-page browse — virtual scroll and cover-art priority
|
||||
|
||||
**By [@cucadmuh](https://github.com/cucadmuh), PR [#783](https://github.com/Psychotoxical/psysonic/pull/783)**
|
||||
|
||||
@@ -154,6 +154,7 @@ const CONTRIBUTOR_ENTRIES = [
|
||||
'Player: persist volume/repeat/queue visibility/Last.fm cache outside quota-bound queue blob (report: norp on Psysonic Discord) (PR #958)',
|
||||
'Player transport: custom delay input capped to browser timer limit; preview/countdown aligned for fractional minutes (report: zunoz on Psysonic Discord) (PR #967)',
|
||||
'Settings: in-page search indexes AudioMuse + shortcut rows; rejects junk fuzzy matches (report: zunoz on Psysonic Discord) (PR #968)',
|
||||
'Floating player bar: center shrink-wrapped pill instead of full-width background strip (report: Asra on Psysonic Discord) (PR #969)',
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { computeFloatingPlayerBarStyle } from './computeFloatingPlayerBarStyle';
|
||||
|
||||
describe('computeFloatingPlayerBarStyle', () => {
|
||||
it('centers in the main column and shrink-wraps instead of stretching', () => {
|
||||
const style = computeFloatingPlayerBarStyle(220, 1600, 1920);
|
||||
expect(style.left).toBe(910);
|
||||
expect(style.right).toBe('auto');
|
||||
expect(style.transform).toBe('translateX(-50%)');
|
||||
expect(style.width).toBe('max-content');
|
||||
expect(style.maxWidth).toBe(1332);
|
||||
});
|
||||
|
||||
it('accounts for a hidden queue panel', () => {
|
||||
const style = computeFloatingPlayerBarStyle(220, null, 1920);
|
||||
expect(style.left).toBe(1070);
|
||||
expect(style.maxWidth).toBe(1652);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
import type { CSSProperties } from 'react';
|
||||
|
||||
const HORIZONTAL_MARGIN_PX = 24;
|
||||
|
||||
/** Center the floating bar in the main column; shrink-wrap width instead of stretching. */
|
||||
export function computeFloatingPlayerBarStyle(
|
||||
sidebarRight: number,
|
||||
queueLeft: number | null,
|
||||
viewportWidth: number,
|
||||
): CSSProperties {
|
||||
const contentLeft = sidebarRight;
|
||||
const contentRight = queueLeft ?? viewportWidth;
|
||||
const contentWidth = Math.max(0, contentRight - contentLeft);
|
||||
const maxWidth = Math.max(100, contentWidth - HORIZONTAL_MARGIN_PX * 2);
|
||||
const centerX = contentLeft + contentWidth / 2;
|
||||
|
||||
return {
|
||||
left: centerX,
|
||||
right: 'auto',
|
||||
transform: 'translateX(-50%)',
|
||||
width: 'max-content',
|
||||
maxWidth,
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { computeFloatingPlayerBarStyle } from './computeFloatingPlayerBarStyle';
|
||||
|
||||
/** Computes the floating player-bar position based on the current sidebar +
|
||||
* queue panel widths. Returns an inline-style object (left/right/width); only
|
||||
@@ -14,17 +15,13 @@ export function useFloatingPlayerBar(
|
||||
if (!floatingPlayerBar) return;
|
||||
|
||||
const updatePosition = () => {
|
||||
const sidebar = document.querySelector('.sidebar') as HTMLElement;
|
||||
const queue = document.querySelector('.queue-panel') as HTMLElement;
|
||||
const sidebar = document.querySelector('.sidebar') as HTMLElement | null;
|
||||
const queue = document.querySelector('.queue-panel') as HTMLElement | null;
|
||||
|
||||
const leftOffset = sidebar ? sidebar.getBoundingClientRect().right : 0;
|
||||
const rightOffset = queue ? window.innerWidth - queue.getBoundingClientRect().left : 0;
|
||||
const sidebarRight = sidebar ? sidebar.getBoundingClientRect().right : 0;
|
||||
const queueLeft = queue ? queue.getBoundingClientRect().left : null;
|
||||
|
||||
setFloatingStyle({
|
||||
left: leftOffset + 24,
|
||||
right: rightOffset + 24,
|
||||
width: 'auto',
|
||||
});
|
||||
setFloatingStyle(computeFloatingPlayerBarStyle(sidebarRight, queueLeft, window.innerWidth));
|
||||
};
|
||||
|
||||
updatePosition();
|
||||
|
||||
@@ -40,3 +40,7 @@
|
||||
"sidebar main queue";
|
||||
}
|
||||
|
||||
.app-shell.floating-player .resizer {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,19 +21,18 @@
|
||||
.player-bar.floating {
|
||||
position: fixed;
|
||||
bottom: 12px;
|
||||
/* left/right handled dynamically by JS */
|
||||
/* left / max-width set by useFloatingPlayerBar — center + shrink-wrap */
|
||||
z-index: 1000;
|
||||
border-radius: 50px;
|
||||
width: auto;
|
||||
min-width: 100px;
|
||||
max-width: none;
|
||||
width: max-content;
|
||||
max-width: min(100%, calc(100vw - 48px));
|
||||
grid-area: unset;
|
||||
padding: 0 24px 0 8px;
|
||||
gap: 16px;
|
||||
background: var(--bg-player);
|
||||
border: 1px solid rgba(255, 255, 255, 0.12);
|
||||
box-shadow:
|
||||
0 8px 32px rgba(0, 0, 0, 0.8),
|
||||
0 8px 32px rgba(0, 0, 0, 0.45),
|
||||
0 0 0 1px rgba(255, 255, 255, 0.05),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user