Space the refusal evenly, and let it go when the menu does

- It sat flush against the tiles with twice that gap beneath; now 16px
  all round, the same as everything else in the menu keeps from the frame
- It can be dismissed, and it does not outlive the menu it appeared in.
  Before, it stayed until the next attempt: closing the chevron and
  opening it again showed a message about a file chosen long ago
- Checked: shown on refusal, gone when dismissed, shown again on the next
  refusal, gone on reopening

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
fkwp
2026-09-17 23:01:54 +02:00
co-authored by Claude Opus 5
parent fb223bcc4b
commit 72ad732771
2 changed files with 19 additions and 4 deletions
@@ -370,7 +370,10 @@ Please see LICENSE in the repository root for full details.
min-inline-size: 0;
}
/* Sits under the tiles, inside the same margin they keep from the frame. */
/* Sits under the tiles, inside the same margin they keep from the frame, and
with the same distance above it as below: the menu's own bottom padding
supplies the lower half, so only the upper half is set here. Without it the
message sits flush against the tiles with a gap twice its size underneath. */
.effectError {
padding: 0 var(--cpd-space-4x) var(--cpd-space-4x);
padding: var(--cpd-space-4x) var(--cpd-space-4x) 0;
}
+14 -2
View File
@@ -187,6 +187,12 @@ export const MediaMuteAndSwitchButton: FC<MediaMuteAndSwitchButtonProps> = ({
// Held open across the file picker: a native dialog takes the focus, and the
// menu would take that as a click elsewhere and close behind it.
const [choosingFile, setChoosingFile] = useState(false);
// The refusal belongs to the attempt that caused it. It stays while the menu
// is open, can be dismissed, and is gone by the time the menu is opened
// again: a message about a file chosen minutes ago explains nothing.
const [refusalSeen, setRefusalSeen] = useState(false);
useEffect(() => setRefusalSeen(false), [backgroundEffectError]);
const chooseFile = useRef<HTMLInputElement>(null);
useEffect(() => {
const input = chooseFile.current;
@@ -657,6 +663,8 @@ export const MediaMuteAndSwitchButton: FC<MediaMuteAndSwitchButtonProps> = ({
onOpenChange={(open) => {
// Ignore the close the file picker provokes by taking the focus.
if (!open && choosingFile) return;
// A refusal does not outlive the menu it was shown in.
if (!open) setRefusalSeen(true);
setMenuOpen(open);
}}
side="top"
@@ -767,11 +775,15 @@ export const MediaMuteAndSwitchButton: FC<MediaMuteAndSwitchButtonProps> = ({
<div role="none" className={styles.effectGrid}>
{effectTiles()}
</div>
{backgroundEffectError !== undefined && (
{backgroundEffectError !== undefined && !refusalSeen && (
// Beside the grid rather than over the call: the user is
// looking here, having just chosen the file this is about.
<div role="none" className={styles.effectError}>
<Alert type="critical" title={backgroundEffectError} />
<Alert
type="critical"
title={backgroundEffectError}
onClose={(): void => setRefusalSeen(true)}
/>
</div>
)}
</div>