Merge pull request #1885 from psiberfunk/fix/capture-pill-setup-tooltip

fix(dictation): give the setup-state pill label a hover tooltip
This commit is contained in:
Palash Debnath
2026-09-09 12:21:38 -07:00
committed by GitHub
3 changed files with 30 additions and 1 deletions
+1 -1
View File
@@ -2176,7 +2176,7 @@ export default function CaptureWidget({ onDismiss }) {
<div className="min-w-0 flex-1 overflow-hidden">
<span
className="block overflow-hidden text-ellipsis whitespace-nowrap text-[12.5px] font-medium tracking-[0.01em]"
title={state === 'error' ? errorInfo?.message || undefined : undefined}
title={state === 'error' ? errorInfo?.message || label || undefined : label || undefined}
>
{emoji} {label}
</span>
@@ -1429,6 +1429,14 @@ describe('CaptureWidget', () => {
expect(screen.queryByText(/Listening/)).not.toBeInTheDocument();
});
it('exposes the full setup label as a title, since the 300px pill clips it', async () => {
mocks.holder.a11y = false;
render(withI18n(<CaptureWidget />));
const labelEl = await screen.findByText(/Allow Accessibility/);
expect(labelEl.title).toBe(i18n.t('capture.a11y_setup'));
});
it('clears the Accessibility setup pill after the native grant changes', async () => {
vi.useFakeTimers();
try {
@@ -126,6 +126,27 @@ describe('CaptureWidget — mic permission pre-flight (Tauri)', () => {
window.__TAURI_INTERNALS__ = {};
});
// #1884: the pill clips its label, so every state that can clip needs a
// hover title. This covers the error branch that carries a message — the
// title is the detailed message, which is strictly more than the clipped
// label shows. The no-message branch falls through to the label and is
// covered by the setup-state test in CaptureWidget.test.jsx.
it('uses the error detail as the title, not just the clipped label', async () => {
stubInvoke({ mic: 'denied' });
installGum(async () => {
throw notFound();
});
render(<CaptureWidget />);
pressShortcut();
const labelEl = await screen.findByText(/Mic access denied/);
// Assert the detail itself, not merely "some different string". This
// phrase lives only in `errorInfo.message` (capture.mic_hint_linux) and
// never in the label, so a regression that fell back to the label — or
// any unrelated tooltip — fails here.
expect(labelEl.title).toMatch(/audio group/);
});
it('OS-denied → guided error pill with Open Settings, getUserMedia never called', async () => {
stubInvoke({ mic: 'denied' });
const gum = installGum(async () => {