Skip to content

🫥 fix: Remove the Focus Line Across the Top of Select Popovers - #200

Open
danny-avila wants to merge 1 commit into
mainfrom
pr/fu-select-search-ring
Open

danny-avila wants to merge 1 commit into
mainfrom
pr/fu-select-search-ring

Conversation

@danny-avila

Copy link
Copy Markdown
Contributor

Pull Request Template

⚠️ Before Submitting a PR, Please Review:

  • Please ensure that you have thoroughly read and understood the Contributing Docs before submitting your Pull Request.

⚠️ Documentation Updates Notice:

  • Kindly note that documentation updates are managed in this repository: librechat.ai

Summary

Every click-ui Select popover showed a 2px line in the focus color across its top, over the first option. It appeared in light and dark, and also when the Select was opened with the mouse. Affected Selects: the audit log's Target type filter, the configuration Jump to… list, and the Langfuse destination picker.

Cause. When the popover opens, click-ui moves focus into the Select's search input (data-testid="select-search-input"). Unless the Select has showSearch, click-ui gives that input zero height, no padding and outline: none. The app's input:not([cmdk-input]):focus-visible rule in src/styles.css (2px solid focus color, 1px offset, !important) overrides that outline. Chrome matches :focus-visible on a focused text input however it got focus, so the zero-height ring showed as a line after mouse opens too.

Fix. A rule placed right after the input ring rule removes the outline from that input unless the Select shows its search:

[data-testid='select-search-input']:not([class*='search-bar_show-search']):focus-visible {
  outline: none !important;
}
  • Both selectors match click-ui's own markup in 0.9.1 (current) and 0.15.0 (⬆️ chore: Upgrade Click UI, i18next, TypeScript, Vitest and the Dev Tooling to Their New Majors #194). InternalSelect sets the test id, and a shown search adds the CSS module class search-bar_show-search__IhdJT, which has the same name and hash in both versions. The substring match also holds if the hash changes.
  • This is a separate rule rather than another entry in the input rule's :not(). A compound selector inside that :not() would raise the input rule's specificity to (0,3,1). It would then beat .cui-field input:focus-visible { outline: none !important } at (0,2,1) and bring back the bare-input ring that rule removes inside click-ui fields. The new rule, at (0,3,0), beats only the input ring rule.
  • Keyboard users can still see where they are, because the highlighted option is marked. 💍 fix: Unclip and Recolor the Keyboard Highlight Ring in Select Popovers #195 fixes that option's keyboard ring. The two PRs change different lines of src/styles.css and merge cleanly. This PR also merges cleanly with ⬆️ chore: Upgrade Click UI, i18next, TypeScript, Vitest and the Dev Tooling to Their New Majors #194.
  • A Select with showSearch keeps its ring on the visible search input. The app has one, the "Add field" picker in InlineField.tsx, but no page renders it today: custom endpoints are edited in the drawer, and the model spec preset renders field by field. The e2e covers this case with a stand-in (see Testing).

Change Type

  • Bug fix (non-breaking change which fixes an issue)

Testing

New live spec, e2e/a11y/select.spec.ts. Like the configuration a11y spec, it needs E2E_LIVE=1 and E2E_BASE_URL. It runs on the audit log Target type filter and on the Jump to… list (at 1024 px, where the list shows), in light and dark. Each test:

  • opens the Select with a click and checks that the search input has focus, has zero height and has outline-style: none;
  • then gives that same input click-ui's real shown-search class, read from the page's stylesheets, and checks that it now has height and a 2px solid ring.

On main, all four tests fail at the outline-style check (received solid). With this change they pass. A probe that injects a rule removing the outline from every Select search input showed that the second half fails for that over-broad fix.

The two Selects and the theme list are exported from e2e/live.ts as SELECTS and THEMES rather than declared in the spec. e2e/a11y/config.spec.ts now imports THEMES from there instead of keeping its own copy; it collects the same 66 tests as before.

Overlap with #195. #195 adds e2e/a11y/menus.spec.ts, which declares the same THEMES and SELECTS (same two Selects, same locators, same 1024 px viewport) locally. The two PRs still merge cleanly, because #195 doesn't touch e2e/live.ts. Whichever merges second should delete those two local declarations from menus.spec.ts and import them from e2e/live.ts. The definitions are identical, so that is a deletion plus an import.

Live, against a LibreChat backend, in light and dark:

  • Before: the audit log Target type and Jump to… popovers both had the line over their first option.
  • After: the line is gone from both. ArrowDown still shows the keyboard highlight. Text fields keep their rings (the audit log Actor field, and the configuration "Filter this tab" field, whose ring is on its wrapper).
  • The stand-in shown-search input (25px tall) shows its focus ring.
  • Same results on ⬆️ chore: Upgrade Click UI, i18next, TypeScript, Vitest and the Dev Tooling to Their New Majors #194's branch (click-ui 0.15.0) with this commit cherry-picked: the spec passes and screenshots show no line.

The Langfuse destination picker uses the same click-ui Select and gets the same fix. It wasn't opened live because it needs a Langfuse setup.

Test Configuration:

  • Chromium (Playwright), LibreChat dev backend, MongoDB replica set.
  • click-ui 0.9.1, and 0.15.0 on ⬆️ chore: Upgrade Click UI, i18next, TypeScript, Vitest and the Dev Tooling to Their New Majors #194's branch.
  • npx tsc --noEmit, npx eslint src/ e2e/ --max-warnings 0, npx prettier --check on the changed files, bun run test:lint-rules, npx vitest run (3338 tests), bun run build. The ESLint config doesn't cover e2e/, so the import order of the changed e2e files was checked against the project conventions by hand.
  • Live: e2e/a11y/select.spec.ts (4 tests), and the system-tab axe tests of e2e/a11y/config.spec.ts in both themes after the THEMES change.

Checklist

  • My code adheres to this project's style guidelines
  • I have performed a self-review of my own code
  • I have commented in any complex areas of my code
  • My changes do not introduce new warnings
  • I have written tests demonstrating that my changes are effective or that my feature works
  • Local unit tests pass with my changes

An open click-ui Select moves focus into its search input. Unless the
Select shows its search, that input has zero height, and the app's
`input:not([cmdk-input]):focus-visible` ring drew it as a 2px line in the
focus color across the first option, in both themes and also when the
Select was opened with the mouse.

A new rule in src/styles.css removes the outline from
`[data-testid='select-search-input']` unless its class contains
`search-bar_show-search`. click-ui 0.9.1 and 0.15.0 render the same test id
and CSS module class, so a Select that shows its search keeps its ring. The
rule is separate from the input ring rule because a compound selector in that
rule's `:not()` would raise its specificity above
`.cui-field input:focus-visible { outline: none }` and bring back the bare
input ring inside click-ui fields.

e2e/a11y/select.spec.ts (live) opens the audit log Target type filter and the
configuration Jump to list in light and dark. It checks that the focused,
zero-height search input has no outline, then that the same input with
click-ui's shown-search class has height and a 2px solid ring. The two
Selects and the theme list are exported from e2e/live.ts as SELECTS and
THEMES, so other a11y specs can open the same Selects without copying the
setup; e2e/a11y/config.spec.ts now imports THEMES instead of declaring its
own.
@danny-avila

Copy link
Copy Markdown
Contributor Author

@codex review

Pass 1. Head: e62d59e

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-27T10:56:04.583444Z e62d59e Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: e62d59e170

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant