diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index b903c7f..cd46ef0 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -480,6 +480,10 @@ export default function DashboardPage() { value={tableSearch} onChange={(e) => setTableSearch(e.target.value)} placeholder="Search callsign, name, grid, frequency…" + autoComplete="off" + data-lpignore="true" + data-1p-ignore="" + data-form-type="other" className="flex-1 min-w-0 bg-transparent border-0 outline-none text-fg text-[15px] placeholder:text-fg-3" /> / diff --git a/src/app/globals.css b/src/app/globals.css index c4f97ff..886fe44 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -237,3 +237,20 @@ background: var(--line-hi); filter: brightness(1.4); } + +/* ────────────────────────────────────────────────────────────── + Suppress password-manager autofill icon overlays + ────────────────────────────────────────────────────────────── + LastPass injects overlays + positioned absolutely over inputs it thinks are credentials, + regardless of data-lpignore. Since this app is ham-radio data + (callsign, RST, datetime, city, etc.) and not credentials, we + hide the in-field icon globally. LP/1P autofill still works on + the auth forms via the extension's keyboard shortcut and + dropdown — only the in-field icon overlay is hidden. */ +svg[data-lastpass-icon="true"], +com-1password-button, +[data-dashlane-rid], +[data-bitwarden-watching] { + display: none !important; +} diff --git a/src/app/new-contact/page.tsx b/src/app/new-contact/page.tsx index 6290753..3855936 100644 --- a/src/app/new-contact/page.tsx +++ b/src/app/new-contact/page.tsx @@ -479,6 +479,9 @@ export default function NewContactPage() { onChange={handleChange} placeholder="W1AW" autoComplete="off" + data-lpignore="true" + data-1p-ignore="" + data-form-type="other" className={cn( 'w-full bg-transparent border-0 border-b-2 border-line-hi text-fg font-mono text-[32px] sm:text-[56px] font-semibold tracking-[0.04em] py-3 sm:py-4 outline-none transition-colors uppercase placeholder:text-fg-3', 'focus:border-accent', @@ -652,6 +655,10 @@ export default function NewContactPage() { name="rst_sent" value={formData.rst_sent} onChange={handleChange} + autoComplete="off" + data-lpignore="true" + data-1p-ignore="" + data-form-type="other" className="w-full bg-transparent border-0 outline-none text-center text-fg font-mono text-[28px] font-semibold mt-1" />
@@ -675,6 +682,10 @@ export default function NewContactPage() { name="rst_received" value={formData.rst_received} onChange={handleChange} + autoComplete="off" + data-lpignore="true" + data-1p-ignore="" + data-form-type="other" className="w-full bg-transparent border-0 outline-none text-center text-fg font-mono text-[28px] font-semibold mt-1" />
diff --git a/src/app/search/page.tsx b/src/app/search/page.tsx index 851d672..3c01da7 100644 --- a/src/app/search/page.tsx +++ b/src/app/search/page.tsx @@ -768,6 +768,16 @@ export default function SearchPage() { + {/* Wrapping the filter fields in a
gives LastPass a form + context to bind to, so it respects data-lpignore on the + individual inputs and stops attaching its autofill icon. + Search is debounced on filter change, so the form has no + real submit action — Enter is suppressed via preventDefault. */} + e.preventDefault()} + className="space-y-6" + > {/* Quick Filters */}
@@ -793,6 +803,7 @@ export default function SearchPage() { handleFilterChange('callsign', e.target.value)} @@ -802,6 +813,7 @@ export default function SearchPage() { handleFilterChange('name', e.target.value)} @@ -811,6 +823,7 @@ export default function SearchPage() { handleFilterChange('qth', e.target.value)} @@ -885,6 +898,7 @@ export default function SearchPage() { handleFilterChange('gridLocator', e.target.value)} @@ -931,6 +945,7 @@ export default function SearchPage() {
)} +
diff --git a/src/components/ui/combobox.tsx b/src/components/ui/combobox.tsx index 4bcaa4f..586a1c2 100644 --- a/src/components/ui/combobox.tsx +++ b/src/components/ui/combobox.tsx @@ -86,6 +86,10 @@ export function Combobox({ placeholder={searchPlaceholder} value={search} onChange={(e) => setSearch(e.target.value)} + autoComplete="off" + data-lpignore="true" + data-1p-ignore="" + data-form-type="other" />
diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx index f7d760c..06ce4fe 100644 --- a/src/components/ui/input.tsx +++ b/src/components/ui/input.tsx @@ -36,6 +36,14 @@ const Input = React.forwardRef( type={type} className={cn(inputVariants({ size, mono, className }))} ref={ref} + // Suppress password-manager autofill UI by default — this app is + // ham-radio data, not credentials. Auth forms pass an explicit + // autoComplete value (e.g. "email", "current-password") which + // overrides via prop spread below. + autoComplete="off" + data-lpignore="true" + data-1p-ignore="" + data-form-type="other" {...props} /> )