Skip to content

feat(player): add a volume control to the desktop player - #60

Merged
suitux merged 2 commits into
suitux:mainfrom
Hellraiser28:feat/player-volume
Oct 20, 2026
Merged

suitux merged 2 commits into
suitux:mainfrom
Hellraiser28:feat/player-volume

Conversation

@Hellraiser28

Copy link
Copy Markdown
Contributor

Closes #49

Adds a volume control to the desktop (sidebar) player.

tagr-49-volume-expanded tagr-49-volume-compact

What it does

  • A speaker button next to shuffle opens a small popover with a volume slider
    and the current percentage. The icon reflects the level (muted / low / high).
  • Works in both the expanded and the compact sidebar player.
  • The volume lives in the player store and is applied to the shared <audio>
    element, both when it changes and when the element is created.
  • It's remembered across reloads in localStorage (tagr-player-volume, same
    naming as tagr-edit-count). A missing or invalid value falls back to 100 %;
    if storage is unavailable (e.g. private mode) it simply isn't remembered.
  • The labels reuse the existing playback.volume string, so no new
    translations are needed.

Why not on mobile

I left the mobile player unchanged on purpose: on iOS/iPadOS,
HTMLMediaElement.volume can't be set from JavaScript (the hardware buttons
always control the level), and on Android a slider would only duplicate the
volume keys. Happy to add it to the expanded mobile player too if you'd prefer.

Testing

  • New unit tests for the store (default, restore, invalid value, clamping,
    persistence, applying to the audio element) and for the control (opens with
    the current value, keyboard changes the volume).
  • tsc --noEmit, ESLint and the full vitest suite pass, and the Docker image
    builds.
  • Checked in a browser against a build of this branch: moving the slider
    updates the audio element's volume live, the value survives a reload, and
    the icon switches between its three states.

Side note: .prettierrc uses jsxBracketSameLine, which Prettier 3 no longer
supports, so running Prettier reformats existing files. I kept the existing
style (> on the same line) instead.

Adds a speaker button next to shuffle in the sidebar player that opens a popover with a volume slider. The volume lives in the player store, is applied to the shared audio element (also when it is created) and is remembered in localStorage. The mobile player is unchanged. Closes suitux#49.
Comment thread src/stores/player-store.ts Outdated
Comment on lines +12 to +35
const VOLUME_STORAGE_KEY = 'tagr-player-volume'

function clampVolume(value: number): number {
return Number.isFinite(value) ? Math.min(Math.max(value, 0), 1) : 1
}

function loadVolume(): number {
if (typeof window === 'undefined') return 1
try {
const stored = window.localStorage.getItem(VOLUME_STORAGE_KEY)
return stored === null ? 1 : clampVolume(parseFloat(stored))
} catch {
return 1
}
}

function saveVolume(value: number) {
try {
window.localStorage.setItem(VOLUME_STORAGE_KEY, String(value))
} catch {
// Storage may be unavailable (private mode, blocked site data); the volume still applies for this session.
}
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be moved into src/features/player/volume.ts

What do you think 😄 ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call — done 😄 Moved VOLUME_STORAGE_KEY, clampVolume, loadVolume and saveVolume into src/features/player/volume.ts, the store now imports them from there, and the test pulls the storage key from the module too.

@suitux
suitux merged commit 3a58277 into suitux:main Oct 20, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] Add a volume slider for music player

2 participants