Skip to content

fix: batch of small UI bugs (#21 #22 #24 #26 #28 #29) - #94

Merged
0xMMA merged 9 commits into
mainfrom
fix/ui-quick-bugs
Oct 5, 2026
Merged

0xMMA merged 9 commits into
mainfrom
fix/ui-quick-bugs

Conversation

@0xMMA

@0xMMA 0xMMA commented Sep 24, 2026 •

Copy link
Copy Markdown
Owner

Six small UI bugs from the April triage: one commit each, plus a follow-up commit for #22 from review.

#21 — version shows vv3.6.0

Release builds are stamped with the git tag (v3.6.0), and the sidebar template added a second v. versionLabel() (core/version-label.ts) now adds the prefix only to a bare version number:

Stamped version Shown
v3.6.0 v3.6.0
3.6.0 v3.6.0
v3.7.0-alpha.2-5-gabc1234 (CI's git describe) unchanged
0a1b2c3 (the commit hash git describe --always falls back to) unchanged
dev dev (was vdev)

The About tab uses the same label, so both places read the same. DOM tests cover the sidebar and the About tab. On the old code the sidebar tests showed vv3.6.0, vv3.7.0-… and vdev.

#22 — Bedrock is offered but only errors

  • Removed from the Active Provider dropdown and from the key fields on the AI Providers tab. The Go stub, the bedrock settings value and the AWS_SECRET_ACCESS_KEY env mapping stay, so Implement AWS Bedrock provider with full credential config #23 can bring it back.
  • README says "AWS Bedrock is not available yet" and links Implement AWS Bedrock provider with full credential config #23. CLAUDE.md's provider list drops it. Also changed website/index.html (meta description, hero sentence, provider chip), because the public site made the same false claim. Note: pages.yml deploys the site on merge, so merging this PR updates keylint.io.

Saved provider bedrock, what the user gets: the value is left as it is. Switching it to a working provider automatically would send the user's text to a service they never picked (and usually one without a key, which just fails differently). Instead, the Active Provider field shows the placeholder "Choose a provider" with a warning under it: "AWS Bedrock is not available yet, so KeyLint has no provider to use. Choose another one and save." Picking any provider clears the warning, and Save stores the choice. Saving without picking keeps bedrock. The Pyramidize page (it has its own provider dropdown) behaves the same way:

  • "Choose a provider" with the note "AWS Bedrock is not available yet. Choose another provider here, or in Settings to keep it." A choice made on this page lasts for the session only.
  • no misleading "No AI API key" banner, and no model-list probe that would say "could not be reached";
  • Pyramidize, the global-instruction Apply (button and Ctrl+Enter) and the selection bubble's Apply are all disabled or return early. The canvas is editable before any Pyramidize, so the user never gets the raw unsupported provider: "bedrock" error. This was added in the follow-up commit fix(pyramidize): keep an unavailable provider out of canvas refinement;
  • picking a provider clears the note and enables the button.

The hotkey path keeps its existing Go error ("AWS Bedrock is not yet supported. Please select a different provider"). Tests cover both screens (settings.component.spec.ts, new unavailable-provider.spec.ts). The shared list lives in core/constants.ts (UNAVAILABLE_PROVIDERS).

Known leftover: a Bedrock secret someone saved earlier stays in the OS keyring and can no longer be seen or deleted in the app. Nothing reads it, because the backend errors out before resolving the key. It's worth a delete-only row or a note in #23. I did not delete it automatically.

#24 — Light and System themes are unstyled

Only Dark is styled, and a dropdown with one entry is not a choice, so the Theme control is gone. applyTheme() now keeps .app-dark whatever theme_preference says, so a light or system saved by an older version can't strip the styling either. The field stays in the settings model and is saved unchanged (tested), ready for #25. dark-mode.spec.ts gains a test that serves a stored "light" through the Wails runtime endpoint (page.route('**/wails/runtime'), answering only Settings.Get) and checks that the page stays dark with no Theme label. On the old code this test fails: the stored light removed .app-dark. Docs (.claude/rules/architecture.md, .claude/docs/architecture.md) are updated.

#26 — Sensitive Logging toggle squeezed, knob clips

The long hint beside the switch made the flex row shrink it. Measured before: Start on Boot 40×24, Sensitive Logging 30×24. After the fix both are 40×24. The fix is flex-shrink: 0 on p-toggle-switch inside .toggle-row, so it also protects the toggle rows PR #31 adds. A new Playwright spec, e2e/settings-toggles.spec.ts, asserts at a 600px viewport that every toggle-row switch is 40px wide. Without the fix it measured 10px there.

#28 — light input background in dark mode, fixed at the root

Measured: the global-instruction input is disabled until the canvas has text, and when disabled it rendered rgb(226,232,240) (slate-200). The root cause is app-wide: .app-dark sat on <body>, but PrimeNG declares each component's tokens on :root as aliases of the theme tokens (--p-select-overlay-background: var(--p-overlay-select-background)), and an alias resolves on the element that declares it. <html> never saw the dark theme, so every aliased token came out light. That covered disabled fields, every p-select dropdown panel (white), tab-bar tokens, and the dim slate key labels on the AI Providers tab. The side finding about dropdown panels shares this cause and is fixed by the same change.

The fix moves .app-dark to <html> (index.html, applyTheme()). The existing overrides in styles.scss are kept, so surfaces that were already dark stay exactly as they were.

Colours that change — needs your visual OK. Everything below moves from Aura's light token to its correct dark token. That also makes the accent consistent: buttons already used orange-400. Measured in Chromium, main → this PR:

  • Fix page, checked "auto copy to clipboard" box: fill orange-500 → orange-400, and the check mark turns from white to near-black #18181b. This is the most visible change.
  • Tabs: active label and underline orange-500 #f97316 → orange-400 #fb923c; inactive labels slate-500 → zinc-400; the tab bar's bottom line slate-200 → zinc-700.
  • About tab text: slate-700 rgb(51,65,85), practically unreadable on near-black (a bug that was already there) → white. So "About: no visible change" in the first version of this description was wrong.
  • Focus rings and borders on inputs, selects, tabs and toggles: orange-500 → orange-400. Invalid/error borders shift to Aura's dark red as well.
  • Dropdown panels: white → zinc-900; the selected option is dark instead of a peach highlight.
  • Input hover borders: light slate → zinc. Provider-card labels on AI Providers: dim slate → white. Native scrollbars: dark (color-scheme: dark).

Unchanged, measured: primary buttons (Save is rgb(251,146,60) with rgb(24,24,27) text either way), page, card and input surfaces, and the welcome wizard apart from its dropdown. The card background moved to :root.app-dark: at equal specificity PrimeNG's own :root card token, injected later, would win and lift the settings card off the page (seen in a screenshot, then fixed). Disabled pInputText/pTextarea/p-select get zinc-900 with muted text instead of Aura's zinc-700 block. Two new dark-mode E2E tests pin the disabled input (rgb(24,24,27)) and an open dropdown panel (rgb(24,24,27)). The disabled-input test also asserts that .app-dark is on <html> and that PrimeNG's --p-inputtext-disabled-background token resolves to its dark value #3f3f46. I checked that it fails once the class is put back on <body>. The roadmap note on #37 that parked "Aura dark tokens not propagated" under #35 is updated. It wasn't a PrimeNG version gap.

Not fixed, separate cause: the "No AI API key configured" banner on Pyramidize is still light amber. Its colours are hardcoded in text-enhancement.component.ts (.api-key-banner, --p-amber-100 background), not theme tokens.

#29 — Apply competes with Pyramidize

Apply is now secondary while the instruction is empty or only whitespace, and turns primary as soon as the user types one. Three DOM tests cover this (secondary when empty, primary once typed, back to secondary on whitespace). Two of them failed before the fix.

Screenshots (Chromium, ng serve, before → after; kept outside the repo)

  • Settings › General: the Theme dropdown is gone. Both toggles are the same size, and the Sensitive Logging knob sits inside its track.
  • Settings with a stored light: before, the whole page was light (white card, slate sidebar). After, it is identical to dark.
  • Settings with a stored bedrock: before, "AWS Bedrock" was selected like a working provider. After, "Choose a provider" with the amber warning under it.
  • Pyramidize with a stored bedrock: "Choose a provider", the amber note under it, no key banner, and a dimmed Pyramidize button.
  • Welcome wizard (stubbed first run), <body> vs <html>: identical.
  • Pyramidize with an empty canvas: before, a pale grey instruction field and an orange Apply. After, a dark field and a grey Apply. After typing, Apply is orange.
  • Pyramidize provider dropdown open: before, a white panel with slate text. After, a zinc-900 panel with light text.
  • AI Providers tab: the key labels ("OpenAI API Key") were dim slate before and are white after. No AWS key row.
  • Fix, About, App Defaults: no visible change apart from the above.

Verification

  • cd frontend && npm test: 15 files, 224 tests passed, 0 failures. Each changed spec was also run alone: shell 16/16, settings 67/67, text-enhancement 39/39, unavailable-provider 5/5. The six issue commits each passed the full unit suite before the follow-up.
  • npm run build: builds. The one warning, text-enhancement component styles over their 4 kB budget, was already there; this PR does not touch those styles.
  • npx playwright test, whole suite: 62 passed, 3 skipped (silent-fix.spec.ts, skipped by design). One earlier run had a single 30s timeout in pyramidize-layout › tab switching, the first test right after ng serve recompiled. That spec then passed 3/3 on its own, and the latest full run was clean. It ran against this branch's own ng serve on port 4310 through an out-of-repo config override, because another worktree's dev server held :4200 and the repo config would have silently reused it locally. git status was clean afterwards.
  • go test ./internal/... passed and go build -o bin/KeyLint . built. No Go files changed, so there is no wire or bindings regeneration.

PR #31 (frozen) merge check

git merge-tree --write-tree --name-only origin/feature/shortcut-double-press HEAD: clean, no conflicting files. internal/features/settings/model.go no longer conflicts either, because #31 is now based on 991e0d1. My edits stay out of the lines #31 changes: I appended new specs instead of editing the ones it rewrites, and left the shell's ngOnInit/subscription code alone.

Two things to watch when #31 merges:

Nits left alone because #31 edits those lines:

Review

A second, independent Opus review found no blockers. Its points are addressed: the refine paths are guarded, the colour list is complete, the e2e test now fails on <body>, the key-field test has a positive assertion, the Pyramidize note points to Settings, and the nits are fixed. The first Opus review ran on the branch. I checked its findings myself and addressed them here: Pyramidize now handles a saved Bedrock provider, versionLabel handles a commit hash, the About tab uses the same label, #26 got a regression test, and the #28 comment is corrected. Its claim that primary buttons change colour was measured and is wrong.

Closes #21, closes #22, closes #24, closes #26, closes #28, closes #29

Release builds are stamped with the git tag (v3.6.0), so the template's
hardcoded "v" produced "vv3.6.0". versionLabel() (core/version-label.ts)
now adds the prefix only to a bare version number: tags and git-describe
output keep their own "v", a dev build shows "dev" rather than "vdev",
and a lone commit hash from `git describe --always` stays as it is. The
About tab uses the same label, so both places read alike.

Closes #21
Bedrock is a stub that only returns "not yet supported", yet it sat in
the Active Provider dropdown with its own key field. It is gone from
both, and README, CLAUDE.md and the website no longer list it. The Go
stub and the settings value stay so #23 can bring it back.

A settings file that already names bedrock is left as it is: switching
it would send the user's text to a service they never chose. Settings
and Pyramidize both show "Choose a provider" with a note that AWS
Bedrock is not available yet. Pyramidize also stays disabled, skips the
key banner and model probe for it, and so never reaches the raw
"unsupported provider" error. Picking any provider clears the note.

Closes #22
Only the dark theme is styled. Choosing Light dropped PrimeNG into its
unstyled light mode, and System did nothing. The theme control is gone
(a dropdown with one entry is not a choice), and applyTheme() keeps
.app-dark whatever theme_preference says, so a value saved by an older
version cannot unstyle the app either. The field stays in the settings
model and is saved unchanged, for the light theme in #25.

The dark-mode E2E spec gains a test that serves a stored "light" through
the Wails runtime endpoint and asserts the page stays dark with no theme
control.

Closes #24
The Sensitive Logging row puts a long hint next to its switch, and the
flex row squeezed the switch (30px at 1280px wide, 10px at 600px), so
the knob slid past the track's edge. The switch no longer shrinks; a
Playwright test at a 600px viewport asserts every toggle row's switch
keeps its 40px width.

Closes #26
PrimeNG declares component tokens on :root as aliases of the theme
tokens (the select panel's background is var(overlay background)), and
an alias resolves on the element that declares it. With .app-dark on
<body>, <html> never saw the dark theme, so every aliased token came out
light: the disabled Pyramidize global-instruction input (slate-200),
every p-select dropdown panel (white), tab bars, and the dim slate key
labels on the AI Providers tab.

The class now sits on <html> (index.html, applyTheme). The existing
overrides in styles.scss are kept so no colour that was right changes;
the card background moves to :root.app-dark so PrimeNG's own :root card
token cannot raise the settings card off the page. Disabled pInputText,
pTextarea and p-select keep a dark zinc-900 surface with muted text,
rather than Aura's zinc-700 block. Two dark-mode E2E tests pin the
disabled-input and dropdown-panel colours.

Closes #28
Apply wore the same accent as the Pyramidize button even while it was
disabled, so a button that could do nothing competed with the page's
main action. It is now secondary while the global instruction is empty
or whitespace, and turns primary as soon as the user types one.

Closes #29
With a saved AWS Bedrock provider, the Pyramidize button was already
guarded, but the Editor canvas is editable before any Pyramidize:
typing a global instruction enabled Apply, and Apply, Ctrl+Enter or the
selection bubble ended in a raw "unsupported provider: bedrock" error.
Apply now stays secondary and disabled, the bubble's Apply is disabled,
and both methods return early. The note on the page now points to
Settings, since a choice made on the page lasts for the session only.

Also: the settings spec's no-AWS-key test asserts the provider keys that
must be there, so an unrendered tab cannot pass it, and the lookup uses
Object.hasOwn so an inherited property name cannot match.

Refs #22
@0xMMA

0xMMA commented Sep 24, 2026

Copy link
Copy Markdown
Owner Author

Ready once visually approved: CI green, independent Opus review with review-pr fork supplement, all findings addressed (9759984). Needs Michael's visual OK on the #28 colour shifts listed in the body, the check-mark colour on the Fix page's auto-copy checkbox especially. website/index.html deploys via pages.yml on merge.

@0xMMA
0xMMA merged commit a48adbb into main Oct 5, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant