fix(ui): a disabled menu row says why it is off, under its label

The reason for a disabled menu row lived in a `title` on a natively disabled
button: no pointer events, so no tooltip, and roving focus skips the row —
four translated sentences reached nobody (the Watch later rename/delete
lock, "no other list to move to", the reorder gate). An aria-disabled row was
tried and reverted in E10's review. ActionMenu items now take a `note`,
rendered as a muted line under a disabled row's label: seen, and readable in
a screen reader's browse mode. Only the icon and label dim — row-level
opacity would dim the explanation too. The reorder group states its reason
once, under its first row.
This commit is contained in:
2026-09-19 07:57:20 +02:00
parent df7c3db085
commit bc138e3b37
4 changed files with 55 additions and 26 deletions
+3 -3
View File
@@ -199,7 +199,7 @@ export default function PlaylistsRail({
// Interpolated, not spelled out: the HU copy said "Watch later", a name the Hungarian UI never
// shows for this list ("Megnézem később") — so the message named a list the reader had never seen
// (E10 review round 1). Passing the localized name makes the two impossible to drift.
const lockedTitle = ctxBuiltin
const lockedNote = ctxBuiltin
? t("playlists.builtinLocked", { name: t("playlists.watchLater") })
: undefined;
const railItems: ActionMenuItem[] = !ctxPl
@@ -210,7 +210,7 @@ export default function PlaylistsRail({
label: t("playlists.rename"),
icon: <Pencil className="w-4 h-4" />,
disabled: ctxBuiltin,
title: lockedTitle,
note: lockedNote,
onSelect: () => {
setRenameValue(ctxPl.name);
setRenamingId(ctxPl.id);
@@ -224,7 +224,7 @@ export default function PlaylistsRail({
separatorBefore: true,
danger: true,
disabled: ctxBuiltin,
title: lockedTitle,
note: lockedNote,
// The same dialog (and the same "what gets selected next" rule) as the detail header's
// trash button — one implementation, two entry points.
onSelect: () => void plActions.remove(ctxPl),