diff --git a/frontend/src/components/Playlists.tsx b/frontend/src/components/Playlists.tsx index 27ed8765..de3e04e6 100644 --- a/frontend/src/components/Playlists.tsx +++ b/frontend/src/components/Playlists.tsx @@ -606,173 +606,185 @@ export default function Playlists() { {/* Header (title, actions, view controls) is fixed chrome — it portals into the shell's fixed band, so only the video list scrolls. */} -
-
-
+ {/* Two tight rows beside a small cover: title + actions on the first, the meta line and the + view controls sharing the second. This band is FIXED chrome (it never scrolls), so every + row it sheds is list height won back — the old layout stacked three rows next to the + cover plus a fourth block under it, for roughly twice this height. */} +
+
+
{items[0]?.thumbnail_url && ( )}
- {renaming ? ( - setRenameValue(e.target.value)} - onBlur={saveRename} - onKeyDown={(e) => { - if (e.key === "Enter") saveRename(); - if (e.key === "Escape") setRenaming(false); - }} - aria-label={t("playlists.rename")} - className="text-lg font-semibold bg-surface border border-border rounded-md px-2 py-0.5 focus:outline-hidden focus:ring-2 focus:ring-accent/40" - /> - ) : ( -
-

{plName(detail)}

- {editable && ( - + )} + {detail.yt_playlist_id && ( + + + + )} + + )} +
+ {linked && detail.dirty && ( + - + + {t("playlists.unsynced")} + + )} + + {editable && canWrite && ( + )} - {detail.yt_playlist_id && ( - - - + + + )} + {editable && ( + )}
- )} -
- {t("playlists.itemCount", { count: items.length })} - {totalSeconds > 0 && ` · ${formatRuntime(totalSeconds)}`} - {filterActive && ` · ${t("playlists.filteredCount", { count: shown.length })}`}
-
- - {editable && canWrite && ( - )} - - )} - {linked && detail.dirty && ( - - )} - {editable && ( - - )} - {linked && detail.dirty && ( - - - {t("playlists.unsynced")} - + {canSaveOrder && ( + + )} + {/* ONE sentence that names the state. Three loose texts used to pile up here + (reset link + save hint + "reordering is off"), and none of them answered the + question a user actually has — "did I just change my playlist?". Worse, + sorting a list whose stored order ALREADY matches the sort produced a + warning, no Save button and no visible change, which reads as a malfunction. + Now the line says which of the three situations you are in; the disabled grip + still explains itself on hover/focus. */} + {viewActive && {viewStatus}} + {canEdit && ( +
+ +
+ )} + )}
- - {(items.length > 1 || viewActive) && ( -
- - {viewActive && ( - - )} - {canSaveOrder && ( - - )} - {/* ONE sentence that names the state. Three loose texts used to pile up here (reset - link + save hint + "reordering is off"), and none of them answered the question a - user actually has — "did I just change my playlist?". Worse, sorting a list whose - stored order ALREADY matches the sort produced a warning, no Save button and no - visible change, which reads as a malfunction. Now the line says which of the three - situations you are in; the disabled grip still explains itself on hover/focus. */} - {viewActive && {viewStatus}} - {canEdit && ( -
- -
- )} -
- )}