# Browsing Another Song Shouldn't Interrupt the One You're Playing

A creator is listening to one version of a song and opens another version's lyrics. Should the music change?

In a music workspace, that interaction exposes a state-design problem. Reading, listening, and choosing a source for the next creative action are related activities, but they are different decisions.

At AISongsMaker, we treat those decisions separately for completed songs. This article explains the state boundary behind that behavior. The code below is a simplified example, not a copy of our production implementation.

## One selected ID can carry too much meaning

A single `selectedTrackId` looks convenient. The highlighted row, details panel, audio element, and continuation form can all read from it.

The trouble starts when clicking a row means “show me the lyrics,” while the audio element interprets the same change as “play this song.” A navigation action becomes a playback action. If a continuation form also reads that ID, inspecting a different result can quietly change the source of the next operation.

Consider three songs:

| Responsibility | Song | What the creator is doing |
| --- | --- | --- |
| Player | A | Listening to an arrangement |
| Details | B | Reading another version's lyrics |
| Creation source | C | Preparing a continuation from an earlier result |

This is a valid workspace state. It should not need three browser tabs.

## Give each action a smaller contract

Use state names that describe their responsibility:

```ts
type TrackId = string;

type WorkspaceState = {
  playingTrackId: TrackId | null;
  detailTrackId: TrackId | null;
  sourceTrackId: TrackId | null;
};

// Illustrative handlers; not a full player implementation.
function inspectTrack(id: TrackId) {
  setDetailTrackId(id);
  setDetailsOpen(true);
}

function requestPlayback(id: TrackId) {
  setPlayingTrackId(id);
}

function prepareContinuation(id: TrackId) {
  setSourceTrackId(id);
}
```

The important part is what these handlers are allowed to change. Inspecting lyrics does not assign an audio source. Preparing a continuation does not require starting playback.

Explicit preview controls can have a different contract. A public example's preview button is an invitation to listen, so changing the player there is reasonable. The boundary applies to inspection actions; it is not a rule that every click must preserve playback.

## Make the separation visible

Separate state is useful only if the interface tells the same story.

The player should identify the song it is actually playing. A details panel should identify the song being inspected. A continuation form should show its source rather than making the creator infer it from whichever row is highlighted.

On mobile, opening details can change the visible screen without changing the audio. Returning to the list should restore navigation context. If opening and closing panels moves focus, preserve a sensible return target for keyboard users too.

Per-track playback position is another independent concern. When a creator explicitly switches back to a song, a saved position can help them resume a comparison. That position should belong to the song being played, not the most recently inspected song.

## Check the boundaries, not just the happy path

A useful regression sequence is to play A, open B's details, and verify that A remains the player source and its playback continues. Then prepare an action from C and check that the form identifies C without silently replacing either of the other contexts.

Test explicit playback separately: starting B should update the player. Also cover a missing or deleted source, closing details with the keyboard, and returning from details on a narrow screen. Clear unavailable state honestly rather than falling back to an unrelated song.

This design does not establish a retention improvement or prove that every music product needs the same layout. It gives each action a clear responsibility. Before using a single “selected item” in a creative application, ask which decision that selection actually represents.

