feat(ai-settings): put Clear inside the API key field, drop the eye #20

Merged
Ghost merged 2 commits from feat/api-key-clear-in-place-of-eye into develop 2026-06-20 17:18:55 +03:00

Problem

Each endpoint API-key PasswordInput (Chat / LLM, Embeddings, Voice / STT) showed Mantine's built-in visibility toggle (the 'eye') plus a separate 'Clear' link below the field. The eye is useless: the key field is a write-only buffer — the stored key never loads back (the server only returns hasApiKey), so clicking the eye reveals an empty buffer.

Change

Replace the eye with a Clear ActionIcon in the field's rightSection. Passing a custom rightSection suppresses the built-in eye (Mantine). The Clear action appears only when a key is stored AND the buffer is empty (has*ApiKey && form.values.*ApiKey.length === 0); as soon as the user starts typing a new key, the rightSection falls back to undefined and the default eye returns — now it's useful (verify what was typed). After Clear, the handler sets has*ApiKey=false, so the rightSection flips back too. Self-consistent.

Applied to all three endpoint cards. The old <Stack> wrapper and <Anchor>Clear</Anchor> link are gone; Anchor removed from the @mantine/core import (no remaining usages). The Clear icon-only button carries type='button' (never submits) and aria-label.

Out of scope (per plan)

Same pattern in the external MCP-server form (ai-mcp-server-form.tsx Authorization header field) — noted in the backlog as a possible follow-up for consistency.

Verification

  • npx tsc --noEmit -p apps/client/tsconfig.json — clean.
  • pnpm --filter client test — 58/58 pass (cosmetic change, no new tests).
  • pnpm --filter client lint — pre-existing infrastructure failure (broken @tanstack/eslint-plugin-query); unrelated.
## Problem Each endpoint API-key `PasswordInput` (Chat / LLM, Embeddings, Voice / STT) showed Mantine's built-in visibility toggle (the 'eye') plus a separate 'Clear' link below the field. The eye is **useless**: the key field is a write-only buffer — the stored key never loads back (the server only returns `hasApiKey`), so clicking the eye reveals an empty buffer. ## Change Replace the eye with a Clear `ActionIcon` in the field's `rightSection`. Passing a custom `rightSection` suppresses the built-in eye (Mantine). The Clear action appears **only** when a key is stored AND the buffer is empty (`has*ApiKey && form.values.*ApiKey.length === 0`); as soon as the user starts typing a new key, the `rightSection` falls back to `undefined` and the default eye returns — now it's useful (verify what was typed). After Clear, the handler sets `has*ApiKey=false`, so the `rightSection` flips back too. Self-consistent. Applied to all three endpoint cards. The old `<Stack>` wrapper and `<Anchor>Clear</Anchor>` link are gone; `Anchor` removed from the `@mantine/core` import (no remaining usages). The Clear icon-only button carries `type='button'` (never submits) and `aria-label`. ## Out of scope (per plan) Same pattern in the external MCP-server form (`ai-mcp-server-form.tsx` Authorization header field) — noted in the backlog as a possible follow-up for consistency. ## Verification - `npx tsc --noEmit -p apps/client/tsconfig.json` — clean. - `pnpm --filter client test` — 58/58 pass (cosmetic change, no new tests). - `pnpm --filter client lint` — pre-existing infrastructure failure (broken `@tanstack/eslint-plugin-query`); unrelated.
Ghost added 1 commit 2026-06-20 13:52:50 +03:00
The PasswordInput for each endpoint API key (Chat / LLM, Embeddings,
Voice / STT) used to show Mantine's built-in visibility toggle (the
'eye') plus a separate 'Clear' link below the field. The eye is useless
here: the key field is a write-only buffer, the stored key never loads
back (the server only returns hasApiKey), so clicking the eye reveals an
empty buffer.

Replace it with a Clear ActionIcon in the field's right section. Passing
a custom rightSection suppresses the built-in eye (Mantine). The Clear
action appears ONLY when a key is stored AND the buffer is empty
(has*ApiKey && form.values.*ApiKey.length === 0); as soon as the user
starts typing a new key, the rightSection falls back to undefined and
the default eye returns - now it is useful (verify what was typed).
After Clear, the handler sets has*ApiKey=false, so the rightSection
flips back too. Self-consistent.

The old Stack wrapper and Anchor 'Clear' link are gone; Anchor is
removed from the @mantine/core import (no remaining usages). The Clear
icon-only button carries type='button' (never submits) and an
aria-label. The two-column 'Model | API key' layout and the write-only
buffer/handler semantics are unchanged.
vvzvlad added 1 commit 2026-06-20 17:18:36 +03:00
The in-field Clear for the API key fields is implemented and merged via
this branch, so the backlog plan is no longer needed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ghost merged commit 1982ef0f23 into develop 2026-06-20 17:18:55 +03:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: vvzvlad/gitmost#20