fix: stop Bitwarden filling the participant field and line its suggestions up with the typed text

This commit is contained in:
Linus Rath
2026-10-11 20:50:10 +02:00
parent f382568d1d
commit 687fde4185
2 changed files with 31 additions and 1 deletions
@@ -0,0 +1,21 @@
import { render, screen } from '@testing-library/react';
import { describe, expect, it, vi } from 'vitest';
import React from 'react';
vi.mock('@/components/ui/avatar', () => ({ Avatar: () => null }));
vi.mock('@/stores/contact-store', () => {
const state = { contacts: [], getAutocomplete: () => [] };
const hook = (sel?: (s: typeof state) => unknown) => (typeof sel === 'function' ? sel(state) : state);
hook.getState = () => state;
return { useContactStore: hook };
});
const { ParticipantInput } = await import('../participant-input');
describe('ParticipantInput', () => {
it('is a search field, which Bitwarden never offers to fill', () => {
// Bitwarden offered saved logins for the e-mail placeholder.
render(<ParticipantInput participants={[]} onAdd={vi.fn()} onRemove={vi.fn()} />);
expect(screen.getByRole('combobox')).toHaveAttribute('type', 'search');
});
});
+10 -1
View File
@@ -115,8 +115,14 @@ export const ParticipantInput = forwardRef<ParticipantInputHandle, ParticipantIn
return (
<div className="space-y-2">
<div className="relative">
{/* type="search": Bitwarden skips search fields unconditionally and
otherwise offered logins for the e-mail placeholder. */}
<Input
ref={inputRef}
type="search"
autoComplete="off"
enterKeyHint="enter"
className="[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none"
value={query}
onChange={(e) => handleInputChange(e.target.value)}
onKeyDown={handleKeyDown}
@@ -136,7 +142,10 @@ export const ParticipantInput = forwardRef<ParticipantInputHandle, ParticipantIn
ref={listRef}
id="participant-suggestions"
role="listbox"
className="absolute z-50 w-full mt-1 bg-background border border-border rounded-md shadow-lg max-h-48 overflow-y-auto"
// Shifted left so each name starts under the typed text (13px into
// the field; 1px border, 12px padding and the 28px avatar plus gap
// into the list), with the avatar to the left of it.
className="absolute z-50 -left-9 right-0 mt-1 bg-background border border-border rounded-md shadow-lg max-h-48 overflow-y-auto"
>
{suggestions.map((s, i) => (
<li