Skip to content

fix: assets/knowledge-base accessibility - #13973

Merged
deon-sanchez merged 45 commits into
release-1.12.0from
kb-a11y
Jul 21, 2026
Merged

fix: assets/knowledge-base accessibility#13973
deon-sanchez merged 45 commits into
release-1.12.0from
kb-a11y

Conversation

@deon-sanchez

@deon-sanchez deon-sanchez commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

This pull request introduces a new accessibility utility component, improves keyboard and ARIA handling in core input components, and makes minor semantic and accessibility improvements to the UI. The most significant changes are the addition of the RadixAriaControlsFix component, improved focus management for command lists, and enhanced accessibility for database and model input components. Additionally, it removes excessive inline comments from ModelInputComponent for better maintainability.

Accessibility and ARIA improvements:

  • Added the new RadixAriaControlsFix component (src/frontend/src/components/common/radixAriaControlsFix/index.tsx) to address ARIA and keyboard navigation issues with Radix UI and Command components, ensuring correct focus and ARIA attributes for better accessibility.
  • Updated the CrashErrorComponent to use a semantic <main> tag instead of a <div>, improving accessibility and document structure. [1] [2]

Command list focus and input improvements:

  • Integrated the focusCommandListOnOpen utility into both the database provider and model input popovers to ensure the command list receives focus when opened, enhancing keyboard navigation. [1] [2] [3]
  • Added a label to the Command component in the database provider input for better screen reader support, and improved focus ring styles for the manage providers button. [1] [2]

Code and maintainability improvements:

These changes collectively improve accessibility, keyboard usability, and code clarity across the relevant UI components.

Test plan for QA

Automated (CI / local)

  • Run KB a11y suite: cd src/frontend && RUN_A11Y=true npx playwright test tests/a11y/knowledge-bases.a11y.spec.ts --project=chromium --workers=1
  • Optionally assert against baselines: RUN_A11Y=true RUN_A11Y_ASSERT=true npx playwright test tests/a11y/knowledge-bases.a11y.spec.ts --project=chromium --workers=1
  • Confirm CI a11y-scan workflow is green for this branch

Manual — Knowledge Bases list (/assets/knowledge-bases)

Keyboard & focus

  • Tab through page chrome → search → table; focus ring is always visible
  • Enter a row’s actions cell with Enter, then Tab between Ingest and ⋮ (AG-Grid must not steal Tab while focus is on those buttons)
  • Open ⋮ with keyboard; arrow through menu items; Escape closes menu and returns focus to the trigger
  • Icon-only controls have accessible names (Ingest files, More actions for {name})

Row actions & states

  • Idle row: Ingest button + menu (Ingest files / View chunks / Delete)
  • Busy/ingesting row: Ingest disabled; menu shows Stop ingestion instead of Delete
  • Delete (single) opens confirmation modal; Escape/Cancel closes without trap; Confirm deletes
  • Select rows → bulk Delete (N) → confirmation modal; cancel restores selection UI

Drawer & ingestion runs

  • Open detail drawer (row click / expected affordance); close control is labeled and keyboard-reachable
  • Drawer with empty / loading / error / populated runs
  • Open an ingestion run detail dialog; labeled dialog; close with Escape; focus returns sanely
  • Opening a row-actions menu while drawer is open does not dismiss the drawer unexpectedly

Create / Add sources modal

  • Create KB: Step 1 (config) → browse menu → add run metadata → validation error on bad key → Next
  • Step 2 Review: with files, no files, preview loading, preview error, multi-file preview switcher
  • Add sources from existing KB: source name disabled; same keyboard path through steps
  • Per-file metadata toggle/editor and remove-file controls are labeled and operable by keyboard
  • Embedding model + DB provider dropdowns open/close with keyboard; Escape does not trap focus in the modal

Search / empty / error

  • Empty state heading and CTA
  • Search with no matches
  • Failed list load shows error toast/message without breaking keyboard nav

Manual — Chunks page (/assets/knowledge-bases/{kb}/chunks)

  • Back control is labeled and returns to KB list
  • Search, source-type filter, page-size select are keyboard operable
  • Metadata filter: open popover → key/value comboboxes → apply → chips appear and are removable
  • Expand/collapse a long chunk card with keyboard/click; focus remains sensible
  • Loading, empty (“no chunks found”), and fetch-error states

Assistive tech / visual spot checks

  • VoiceOver (macOS) or NVDA: announce row action buttons, menu items, modal titles, and form errors (metadata validation is not color-only)
  • Zoom to 200% and narrow viewport (~320px / 400% zoom): no clipped critical controls on list, drawer, create modal, or chunks filters
  • Status badges (ingesting / failed / succeeded) are not conveyed by color alone

Regression

  • Create a KB end-to-end, ingest additional files, view chunks, stop an in-progress ingestion, delete a KB — all still work with mouse
  • No new console errors when opening menus/modals from the table or drawer

… guide

- Introduced a manual validation tracker for IBM Level 1 accessibility, detailing validation methods and criteria.
- Added a comprehensive engineering compliance guide aligned with IBM Equal Access Toolkit v7.3, covering essential accessibility requirements and best practices.
- The tracker complements existing automated checks and serves as a shared checklist for UI validation.
…cker

- Introduced a comprehensive guide for IBM Accessibility Level 1 compliance, detailing essential requirements aligned with the IBM Equal Access Toolkit v7.3.
- Added a manual validation tracker to facilitate UI accessibility checks, complementing existing automated tools.
- Updated README to include references to the new criteria and tracker documents, emphasizing their role in the accessibility testing process.
…ibility scans

- Added a new skill for authoring Playwright accessibility scan spec files, aimed at enhancing IBM Equal Access compliance for Langflow frontend features and routes.
- Updated the README to include guidance on using the new skill and its integration with existing a11y testing workflows.
- Enhanced the IBM Level 1 criteria documentation to clarify the scope and application of accessibility requirements.
- Revised the README to enhance clarity on Langflow's accessibility testing processes, including a detailed overview of scanning methods and their purposes.
- Added sections for quick start and workflow for adding a11y coverage, making it easier for contributors to understand how to implement accessibility tests.
- Updated references to IBM Level 1 compliance documents, ensuring users have access to the necessary resources for effective a11y validation.
…ents

- Introduced RadixAriaControlsFix component to manage aria-controls attributes for better accessibility in popovers and dialogs.
- Updated CrashErrorComponent to use semantic <main> tag for improved structure.
- Added new localization keys for various actions and navigation in multiple languages, enhancing user experience.
- Implemented aria-labels for buttons and interactive elements to ensure compliance with accessibility standards.
- Improved accessibility in FilesPanel and StepReview components by adding descriptive aria-labels for better screen reader support.
…ts in es.json

- Adjusted line numbers for multiple hashed secrets in the .secrets.baseline file to reflect changes in the src/frontend/src/locales/es.json file.
- Ensured that all entries are correctly aligned with their respective line numbers for better tracking and management of secrets.
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ed03bc94-d719-4612-8789-f954031a37c4

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

This PR adds a RadixAriaControlsFix component to patch Radix UI aria-controls behavior, applies aria-label/aria-labelledby attributes across Knowledge Base UI components, adds corresponding translation keys across seven locales, extends a11y test tooling with ignoreRules filtering, adds new Playwright fixtures/specs for Knowledge Base accessibility, updates the crash error component to use a <main> tag, and regenerates the secrets baseline.

Changes

Knowledge Base accessibility improvements

Layer / File(s) Summary
RadixAriaControlsFix component
src/frontend/src/components/common/radixAriaControlsFix/index.tsx, .../knowledgePage/index.tsx, .../sourceChunksPage/SourceChunksPage.tsx
New component caches/restores aria-controls on closed/reopened Radix elements and adjusts focus guards via a MutationObserver; wired into Knowledge Base and chunks pages.
ARIA labels on interactive elements
FilesPanel.tsx, StepReview.tsx, IngestionRunDetailModal.tsx, KnowledgeBaseDrawer.tsx, KnowledgeBasesTab.tsx, knowledgeBaseColumns.tsx, SourceChunksPage.tsx, ChunkCard.tsx, crashErrorComponent/index.tsx
Adds i18n-backed aria-label/aria-labelledby to buttons, dropdowns, dialogs, and inputs; updates delete-confirmation modal usage to avoid unlabeled fallback triggers; adds interpolation support to a translation helper; switches crash component wrapper to <main>.
Locale translation keys
src/frontend/src/locales/{en,de,es,fr,ja,pt,zh-Hans}.json
Adds new Knowledge UI translation keys for actions, close labels, pagination, chunk preview navigation, copy/remove actions across all seven locales.
A11y test tooling ignoreRules
tests/utils/types.ts, tests/utils/accessibility-checker.ts, tests/fixtures.ts
Adds an optional ignoreRules parameter threaded through A11yScanOptions, formatA11yFailure, and countNewA11yViolations to exclude specific rule IDs from violation counts/messages.
Knowledge Base a11y fixtures and specs
tests/a11y/helpers/knowledge-bases.fixtures.ts, tests/a11y/knowledge-bases.a11y.spec.ts
New fixtures module with seeded data, route mocks, and navigation helpers; new Playwright spec running scenario-driven and explicit accessibility scans across list/chunks/modal/drawer states with an ignore-rules list.
Secrets baseline regeneration
.secrets.baseline
Updates stored line_number values for locale file secret findings and refreshes generated_at.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant KnowledgePage
  participant RadixAriaControlsFix
  participant DOM
  participant MutationObserver

  KnowledgePage->>RadixAriaControlsFix: mount component
  RadixAriaControlsFix->>DOM: cache aria-controls, remove on closed elements
  RadixAriaControlsFix->>MutationObserver: observe data-state/aria-controls mutations
  DOM-->>MutationObserver: attribute mutation occurs
  MutationObserver->>RadixAriaControlsFix: re-run fixClosedTriggers
  RadixAriaControlsFix->>DOM: restore cached aria-controls on reopen
  KnowledgePage->>RadixAriaControlsFix: unmount component
  RadixAriaControlsFix->>MutationObserver: disconnect observer
Loading

Possibly related PRs

  • langflow-ai/langflow#13330: Both PRs regenerate .secrets.baseline and locale baseline files, updating the same “Secret Keyword” entries' line_number/generated_at.
  • langflow-ai/langflow#13561: Both PRs extend the frontend accessibility testing infrastructure, updating runA11yScan support and accessibility-checker.ts/fixtures.ts for ignore-rule handling.

Suggested labels: bug

Suggested reviewers: viktoravelino, olayinkaadelakun

🚥 Pre-merge checks | ✅ 9
✅ Passed checks (9 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Test Coverage For New Implementations ✅ Passed The PR adds real tests for the new knowledge-base UI/a11y flows plus unit tests for updated components, and the repo’s .test.tsx/.a11y.spec.ts naming is consistent.
Test Quality And Coverage ✅ Passed The new Playwright a11y suite exercises KB list/chunks/upload flows, loading/error states, dialogs, filters, and API mocks with proper async gating.
Test File Naming And Structure ✅ Passed PASS: The new Playwright a11y spec follows the repo’s .spec.ts convention, uses test.describe with descriptive cases, and covers positive/negative states with clear setup.
Excessive Mock Usage Warning ✅ Passed The new tests use route stubs only for external API data in Playwright a11y flows; core UI behavior is exercised through real interactions, not over-mocked.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main knowledge-base accessibility work, though it is broader than the full changeset.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch kb-a11y

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@deon-sanchez
deon-sanchez marked this pull request as ready for review July 6, 2026 23:45
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

✅ Test Coverage Advisor

No source changes detected without accompanying tests. Thanks for keeping coverage up! 🎉

Advisory check only — never blocks merge.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
src/frontend/src/locales/de.json (1)

965-965: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

German quotation spacing deviates from convention.

„ {{name}} “ inserts spaces inside the guillemet-style quotes; standard German typography uses „{{name}}“ without internal spacing (as does moreActionsFor and removeFile).

✏️ Proposed fix
-  "knowledge.action.moreActionsFor": "Aktionen für „ {{name}} “",
+  "knowledge.action.moreActionsFor": "Aktionen für „{{name}}“",
-  "knowledge.removeFile": "„ {{name}} “ entfernen",
+  "knowledge.removeFile": "„{{name}}“ entfernen",

Also applies to: 1103-1103

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/frontend/src/locales/de.json` at line 965, The German locale strings for
knowledge.action.moreActionsFor and removeFile use incorrect spacing inside the
quotation marks; update the translated values in de.json to follow standard
German typography by removing the internal spaces around the placeholder,
matching the existing quoting style used elsewhere in the locale file.
src/frontend/tests/a11y/knowledge-bases.a11y.spec.ts (1)

207-228: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate gate-release pattern; use the existing gateRoute helper.

This test manually reimplements the same delayed-fulfillment pattern that gateRoute (imported and used elsewhere in this file, e.g. Line 465, Line 602, Line 697) already provides.

♻️ Proposed refactor
   test("scans the loading state", RELEASE, async ({ page }) => {
-    let releaseList: () => void = () => {};
-    const listReady = new Promise<void>((resolve) => {
-      releaseList = resolve;
-    });
-    await page.route(KB_LIST_GLOB, async (route) => {
-      await listReady;
-      await route.fulfill({ json: SEEDED_KNOWLEDGE_BASES });
-    });
+    const releaseList = await gateRoute(
+      page,
+      KB_LIST_GLOB,
+      SEEDED_KNOWLEDGE_BASES,
+    );

     await awaitBootstrapTest(page, { skipModal: true });
     await page.goto("/assets/knowledge-bases");
     await disableAnimations(page);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/frontend/tests/a11y/knowledge-bases.a11y.spec.ts` around lines 207 - 228,
The loading-state test is manually duplicating the delayed route-release pattern
instead of using the existing gateRoute helper. Update the `scans the loading
state` test to gate `KB_LIST_GLOB` with `gateRoute` like the other tests in this
file, so the route setup and release flow stay consistent and reusable. Keep the
rest of the assertions and `awaitBootstrapTest`/`runA11yScan` flow unchanged.
src/frontend/tests/utils/accessibility-checker.ts (1)

118-123: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Report counts line stays unfiltered by ignoreRules, unlike "New issues".

New issues reflects the ignoreRules-filtered count, but Report counts: violation=… still uses the raw report.summary.counts, which can look inconsistent when many issues are suppressed via ignoreRules.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/frontend/tests/utils/accessibility-checker.ts` around lines 118 - 123,
The report summary in accessibility-checker is inconsistent because the “Report
counts” line still uses the raw counts instead of the ignoreRules-filtered
values used for “New issues.” Update the logic in the report-building flow
around the lines array in accessibility-checker.ts so the counts displayed in
“Report counts” are derived from the filtered issue set (or otherwise adjusted
with ignoreRules) to match the behavior of failingIssues and keep the summary
consistent.
src/frontend/src/locales/es.json (1)

965-965: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Inconsistent quoting of interpolated names between strings.

moreActionsFor wraps {{name}} in guillemets (« … ») while removeFile leaves it unquoted. Consider aligning the two for visual consistency.

✏️ Proposed fix
-  "knowledge.removeFile": "Eliminar {{name}}",
+  "knowledge.removeFile": "Eliminar « {{name}} »",

Also applies to: 1103-1103

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/frontend/src/locales/es.json` at line 965, Align the locale strings for
knowledge.action.moreActionsFor and knowledge.action.removeFile so interpolated
{{name}} is quoted consistently. Update the Spanish entries in es.json to use
the same visual treatment for the name placeholder in both messages, keeping the
wording and punctuation style matched across these two keys.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/frontend/src/components/common/radixAriaControlsFix/index.tsx`:
- Around line 43-53: The MutationObserver setup in radixAriaControlsFix should
be throttled so repeated DOM mutations do not trigger full-document rescans on
every callback. Update the fixClosedTriggers observer flow to coalesce bursts
with requestAnimationFrame or a small debounce, while keeping the existing
observer.disconnect cleanup intact. Keep the scan logic in fixClosedTriggers
unchanged, but ensure it runs at most once per frame regardless of how many
childList/subtree mutations occur.
- Around line 37-40: The DOM mutation in the Radix focus guard fix is making
`data-radix-focus-guard` elements untabbable, which breaks Radix edge
Tab/Shift+Tab handling. Update the logic in `radixAriaControlsFix` so it no
longer sets `tabindex="-1"` or `aria-hidden` on these guards. Instead, adjust
the scanner/exclusion logic in the same area to skip `data-radix-focus-guard`
nodes entirely while leaving their default tabbable behavior intact.

---

Nitpick comments:
In `@src/frontend/src/locales/de.json`:
- Line 965: The German locale strings for knowledge.action.moreActionsFor and
removeFile use incorrect spacing inside the quotation marks; update the
translated values in de.json to follow standard German typography by removing
the internal spaces around the placeholder, matching the existing quoting style
used elsewhere in the locale file.

In `@src/frontend/src/locales/es.json`:
- Line 965: Align the locale strings for knowledge.action.moreActionsFor and
knowledge.action.removeFile so interpolated {{name}} is quoted consistently.
Update the Spanish entries in es.json to use the same visual treatment for the
name placeholder in both messages, keeping the wording and punctuation style
matched across these two keys.

In `@src/frontend/tests/a11y/knowledge-bases.a11y.spec.ts`:
- Around line 207-228: The loading-state test is manually duplicating the
delayed route-release pattern instead of using the existing gateRoute helper.
Update the `scans the loading state` test to gate `KB_LIST_GLOB` with
`gateRoute` like the other tests in this file, so the route setup and release
flow stay consistent and reusable. Keep the rest of the assertions and
`awaitBootstrapTest`/`runA11yScan` flow unchanged.

In `@src/frontend/tests/utils/accessibility-checker.ts`:
- Around line 118-123: The report summary in accessibility-checker is
inconsistent because the “Report counts” line still uses the raw counts instead
of the ignoreRules-filtered values used for “New issues.” Update the logic in
the report-building flow around the lines array in accessibility-checker.ts so
the counts displayed in “Report counts” are derived from the filtered issue set
(or otherwise adjusted with ignoreRules) to match the behavior of failingIssues
and keep the summary consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 45196151-197e-44c3-8202-81e79935daa9

📥 Commits

Reviewing files that changed from the base of the PR and between 6bd0e05 and 5d09a62.

📒 Files selected for processing (24)
  • .secrets.baseline
  • src/frontend/src/components/common/crashErrorComponent/index.tsx
  • src/frontend/src/components/common/radixAriaControlsFix/index.tsx
  • src/frontend/src/locales/de.json
  • src/frontend/src/locales/en.json
  • src/frontend/src/locales/es.json
  • src/frontend/src/locales/fr.json
  • src/frontend/src/locales/ja.json
  • src/frontend/src/locales/pt.json
  • src/frontend/src/locales/zh-Hans.json
  • src/frontend/src/modals/knowledgeBaseUploadModal/components/FilesPanel.tsx
  • src/frontend/src/modals/knowledgeBaseUploadModal/components/StepReview.tsx
  • src/frontend/src/pages/MainPage/pages/knowledgePage/components/IngestionRunDetailModal.tsx
  • src/frontend/src/pages/MainPage/pages/knowledgePage/components/KnowledgeBaseDrawer.tsx
  • src/frontend/src/pages/MainPage/pages/knowledgePage/components/KnowledgeBasesTab.tsx
  • src/frontend/src/pages/MainPage/pages/knowledgePage/config/knowledgeBaseColumns.tsx
  • src/frontend/src/pages/MainPage/pages/knowledgePage/index.tsx
  • src/frontend/src/pages/MainPage/pages/knowledgePage/sourceChunksPage/SourceChunksPage.tsx
  • src/frontend/src/pages/MainPage/pages/knowledgePage/sourceChunksPage/components/ChunkCard.tsx
  • src/frontend/tests/a11y/helpers/knowledge-bases.fixtures.ts
  • src/frontend/tests/a11y/knowledge-bases.a11y.spec.ts
  • src/frontend/tests/fixtures.ts
  • src/frontend/tests/utils/accessibility-checker.ts
  • src/frontend/tests/utils/types.ts

Comment on lines +37 to +40
document.querySelectorAll("[data-radix-focus-guard]").forEach((node) => {
node.setAttribute("tabindex", "-1");
node.setAttribute("aria-hidden", "true");
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== File context ==\n'
sed -n '1,140p' src/frontend/src/components/common/radixAriaControlsFix/index.tsx

printf '\n== Search for focus guard usage ==\n'
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' 'data-radix-focus-guard|aria-hidden="true"|tabindex="-1"|tabIndex=\{0\}' src/frontend src | sed -n '1,200p'

printf '\n== Package versions ==\n'
python3 - <<'PY'
import json, pathlib
for path in [pathlib.Path('package.json'), pathlib.Path('src/frontend/package.json')]:
    if path.exists():
        print(f'## {path}')
        data = json.loads(path.read_text())
        deps = {}
        for k in ('dependencies','devDependencies','peerDependencies','optionalDependencies'):
            deps.update(data.get(k, {}))
        for name in ('`@radix-ui/react-focus-scope`','`@radix-ui/react-dialog`','`@radix-ui/react-popover`','`@radix-ui/react-dropdown-menu`','`@radix-ui/react-menu`'):
            if name in deps:
                print(name, deps[name])
PY

printf '\n== Relevant Radix source references in repo ==\n'
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' '`@radix-ui/react-focus-scope`|focus guard|focus trap|trapped' . | sed -n '1,200p'

Repository: langflow-ai/langflow

Length of output: 28653


🌐 Web query:

Radix UI focus guard data-radix-focus-guard tabIndex 0 onFocus redirect focus-scope source

💡 Result:

In Radix UI, the data-radix-focus-guard attribute is used to identify invisible, focusable elements that ensure keyboard focus management works reliably across the entire document [1][2]. These guards are essential components injected by the @radix-ui/react-focus-guards package to help components like Dialog and Popover trap and maintain focus [1][3]. Key technical details regarding these guards include: Mechanism: Radix UI injects two invisible elements into the document body—one at the very beginning (afterbegin) and one at the very end (beforeend) [1][2]. These elements are explicitly marked with the data-radix-focus-guard attribute [1][2]. Purpose: By assigning them tabIndex={0}, Radix UI makes these elements focusable [1]. This ensures that when a user reaches the beginning or end of a focus-trapped area, the browser's focus events (like focusin and focusout) are consistently fired [1]. This allows the library's focus-trapping logic to detect when the user is trying to move focus outside the trapped region and redirect it accordingly, preventing the focus from "leaking" into the browser UI or other non-trapped areas [1][3]. Properties: To keep them invisible and non-interactive to the user, they are styled with opacity: 0, position: fixed, and pointer-events: none, while their outline is set to none [1][2]. Reference Counting: The implementation uses a reference counter to manage these guards [1]. Multiple components can "request" focus guards, but only one pair exists in the document at any time; they are only removed when the last component requiring them unmounts [1][2]. Relationship with FocusScope: While FocusGuards provides the infrastructure for capturing focus at the document edges, FocusScope is the component that performs the actual logic of trapping, looping, and restoring focus [3]. When FocusScope is set to trapped={true}, it listens for focus events and, should the focus land on a guard or attempt to exit the scope, it uses its internal logic to redirect focus back to a valid element within the designated scope [3][4].

Citations:


🌐 Web query:

@radix-ui/react-focus-scope focus guards tabIndex 0 focusin trapped source implementation

💡 Result:

In Radix UI, focus management relies on two primary utilities working in tandem: @radix-ui/react-focus-guards and @radix-ui/react-focus-scope [1][2]. Focus Guards (Implementation) Focus guards are invisible, focusable elements strategically placed in the DOM to ensure focus events are captured correctly at the document boundaries [1]. - Structure: They are elements with an empty data-radix-focus-guard attribute [1]. - Styling: They are set to tabIndex={0} (making them focusable), with CSS properties like position: fixed, opacity: 0, and pointer-events: none to remain invisible and non-obstructive [1]. - Functionality: They are injected at the very start and end of document.body [1]. When a user tabs into these guards, they provide a reliable target for the browser to trigger focusin and focusout events, which the FocusScope can then monitor [1]. This prevents "focus leakage" where focus might otherwise accidentally move into the browser's chrome or become lost when navigating at the edges of a trapped focus area [1]. Focus Scope and Trapping The FocusScope component manages the trapping of focus within a specific DOM container [2]. - Trapping Mechanism: When trapped={true}, FocusScope listens for focusin and focusout events [2]. If the focus moves to an element outside the defined scope, the component programmatically redirects it back inside [2]. - Tab Navigation: It implements a "looping" behavior: when a user tabs from the last focusable element in the scope, focus is programmatically moved back to the first element (and vice versa for Shift+Tab) [2][3]. - Implementation Logic: FocusScope uses a function—often identified in community discussions as a variation of getTabbableCandidates—to scan the DOM tree within its container [3]. It evaluates element properties, including tabIndex, to determine the order of focusable items [4][3]. - tabIndex Usage: While focus guards use tabIndex={0} to participate in the natural tab order [1], the container of the FocusScope itself often uses tabIndex={-1} [3]. This makes the container programmatically focusable (allowing it to receive focus via JavaScript) without adding it to the natural keyboard tab order [3]. These systems ensure that even in complex UI components like Modals or Popovers, keyboard focus remains strictly contained, predictable, and compliant with accessibility standards [1][2][5].

Citations:


Don't force Radix focus guards to tabindex="-1" data-radix-focus-guard elements need to stay tabbable for Radix to catch edge Tab/Shift+Tab navigation and redirect focus back into open dialogs/popovers. Remove this mutation and exclude these guards from the scanner instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/frontend/src/components/common/radixAriaControlsFix/index.tsx` around
lines 37 - 40, The DOM mutation in the Radix focus guard fix is making
`data-radix-focus-guard` elements untabbable, which breaks Radix edge
Tab/Shift+Tab handling. Update the logic in `radixAriaControlsFix` so it no
longer sets `tabindex="-1"` or `aria-hidden` on these guards. Instead, adjust
the scanner/exclusion logic in the same area to skip `data-radix-focus-guard`
nodes entirely while leaving their default tabbable behavior intact.

Comment on lines +43 to +53
fixClosedTriggers();

const observer = new MutationObserver(fixClosedTriggers);
observer.observe(document.body, {
subtree: true,
childList: true,
attributes: true,
attributeFilter: ["data-state", "aria-controls"],
});

return () => observer.disconnect();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

Throttle the observer callback to avoid full-document rescans on every DOM mutation.

childList/subtree mutations aren't limited by attributeFilter, so any DOM change anywhere under document.body (e.g. table row virtualization, unrelated re-renders) triggers 3 full-document querySelectorAll scans plus writes. This can add up on pages with frequent DOM churn.

Coalesce bursts with requestAnimationFrame (or a small debounce) so the scan runs at most once per frame regardless of mutation volume.

⚡ Suggested throttling
+    let rafId: number | null = null;
+    const scheduleFixup = () => {
+      if (rafId !== null) return;
+      rafId = requestAnimationFrame(() => {
+        rafId = null;
+        fixClosedTriggers();
+      });
+    };
+
     fixClosedTriggers();
-    const observer = new MutationObserver(fixClosedTriggers);
+    const observer = new MutationObserver(scheduleFixup);
     observer.observe(document.body, {
       subtree: true,
       childList: true,
       attributes: true,
       attributeFilter: ["data-state", "aria-controls"],
     });

-    return () => observer.disconnect();
+    return () => {
+      observer.disconnect();
+      if (rafId !== null) cancelAnimationFrame(rafId);
+    };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fixClosedTriggers();
const observer = new MutationObserver(fixClosedTriggers);
observer.observe(document.body, {
subtree: true,
childList: true,
attributes: true,
attributeFilter: ["data-state", "aria-controls"],
});
return () => observer.disconnect();
let rafId: number | null = null;
const scheduleFixup = () => {
if (rafId !== null) return;
rafId = requestAnimationFrame(() => {
rafId = null;
fixClosedTriggers();
});
};
fixClosedTriggers();
const observer = new MutationObserver(scheduleFixup);
observer.observe(document.body, {
subtree: true,
childList: true,
attributes: true,
attributeFilter: ["data-state", "aria-controls"],
});
return () => {
observer.disconnect();
if (rafId !== null) cancelAnimationFrame(rafId);
};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/frontend/src/components/common/radixAriaControlsFix/index.tsx` around
lines 43 - 53, The MutationObserver setup in radixAriaControlsFix should be
throttled so repeated DOM mutations do not trigger full-document rescans on
every callback. Update the fixClosedTriggers observer flow to coalesce bursts
with requestAnimationFrame or a small debounce, while keeping the existing
observer.disconnect cleanup intact. Keep the scan logic in fixClosedTriggers
unchanged, but ensure it runs at most once per frame regardless of how many
childList/subtree mutations occur.

…lity testing

- Added a new skill for authoring Playwright accessibility scan spec files, aimed at improving coverage for Langflow frontend features and routes.
- Created a centralized JSON file for managing accessibility rule suppressions, ensuring clarity on which rules are framework-owned and cannot be fixed at the feature level.
- Updated existing accessibility test specifications to utilize the new ignore rules, streamlining the process of identifying actionable issues versus suppressed ones.
- Enhanced documentation for accessibility testing workflows, including detailed instructions on capturing all relevant UI states during scans.
- Improved the HTML report generation to clearly distinguish between actionable and suppressed accessibility issues, aiding developers in focusing on necessary fixes.
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Frontend Unit Test Coverage Report

Coverage Summary

Lines Statements Branches Functions
Coverage: 46%
46.81% (66856/142801) 70.12% (9386/13385) 45.28% (1538/3396)

Unit Test Results

Tests Skipped Failures Errors Time
5343 0 💤 0 ❌ 0 🔥 18m 50s ⏱️

@codecov

codecov Bot commented Jul 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 82.01604% with 157 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (release-1.12.0@3c39c0d). Learn more about missing BASE report.

Files with missing lines Patch % Lines
...owledgePage/components/IngestionRunDetailModal.tsx 56.00% 33 Missing ⚠️
...s/knowledgePage/components/KnowledgeBaseDrawer.tsx 30.43% 32 Missing ⚠️
...ges/knowledgePage/components/KnowledgeBasesTab.tsx 74.60% 32 Missing ⚠️
...edgePage/sourceChunksPage/components/ChunkCard.tsx 22.22% 14 Missing ⚠️
...c/components/common/radixAriaControlsFix/index.tsx 92.30% 8 Missing ⚠️
...enderComponent/components/tableComponent/index.tsx 46.66% 8 Missing ⚠️
...geBaseUploadModal/components/StepConfiguration.tsx 84.84% 5 Missing ⚠️
...ages/knowledgePage/config/knowledgeBaseColumns.tsx 97.25% 5 Missing ⚠️
...e/sourceChunksPage/components/MetadataCombobox.tsx 88.88% 4 Missing ⚠️
...ntend/src/modals/deleteConfirmationModal/index.tsx 50.00% 3 Missing ⚠️
... and 7 more
Additional details and impacted files

Impacted file tree graph

@@                Coverage Diff                @@
##             release-1.12.0   #13973   +/-   ##
=================================================
  Coverage                  ?   60.36%           
=================================================
  Files                     ?     2357           
  Lines                     ?   233697           
  Branches                  ?    34527           
=================================================
  Hits                      ?   141066           
  Misses                    ?    91015           
  Partials                  ?     1616           
Flag Coverage Δ
frontend 60.07% <82.01%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...nent/components/dbProviderInputComponent/index.tsx 65.04% <100.00%> (ø)
...ts/modelInputComponent/components/ModelTrigger.tsx 82.75% <100.00%> (ø)
...Component/components/modelInputComponent/index.tsx 93.36% <100.00%> (ø)
...Component/hooks/use-ag-grid-accessibility-patch.ts 89.44% <100.00%> (ø)
...enderComponent/utils/focus-command-list-on-open.ts 100.00% <100.00%> (ø)
src/frontend/src/components/ui/select.tsx 91.13% <100.00%> (ø)
...wledgeBaseUploadModal/KnowledgeBaseUploadModal.tsx 100.00% <100.00%> (ø)
...knowledgeBaseUploadModal/components/FilesPanel.tsx 86.78% <100.00%> (ø)
...knowledgeBaseUploadModal/components/StepReview.tsx 87.24% <100.00%> (ø)
...modelProviderModal/components/ProviderListItem.tsx 94.44% <100.00%> (ø)
... and 21 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

… for Knowledge Bases

- Introduced a new JSON file, `knowledge-bases-ignore-rules.json`, to centralize accessibility rule suppressions specific to the Knowledge Bases feature.
- Updated relevant test specifications to import the new feature-specific ignore rules, enhancing clarity on which rules are framework-owned and cannot be fixed at the feature level.
- Modified the HTML report generation to reflect KB-specific suppressions, ensuring that only relevant findings are greyed out while actionable issues remain visible.
- Enhanced documentation to guide other features in creating their own ignore rules as needed, promoting consistency in accessibility testing practices.
Bring in IBM Accessibility Level 1 criteria guide and route validation
tracker. Resolve conflicts in a11y-spec-authoring skill and README by
keeping kb-a11y's feature-specific ignore-rules approach.
…rets in pt.json

- Updated line numbers for multiple hashed secrets in the .secrets.baseline file to reflect changes in the src/frontend/src/locales/pt.json file.
- Modified the generated_at timestamp for consistency.
- Changed version field in Structured Data Analysis Agent configuration to null.
- Improved CSS variable definitions for better accessibility compliance.
@deon-sanchez deon-sanchez self-assigned this Jul 7, 2026
@deon-sanchez deon-sanchez changed the title Knowledge Base Accessibility fix: knowledge base accessibility Jul 7, 2026
@github-actions github-actions Bot added the bug Something isn't working label Jul 7, 2026
…orting

- Added `writeA11yIgnoreSidecar` function to persist applied ignore rules for each scan, enabling precise reporting of suppressed rules.
- Updated HTML report generation to read from the new sidecar files, ensuring only relevant rules are greyed out based on individual scan configurations.
- Enhanced documentation to clarify the management of suppression rules and their impact on accessibility reporting.
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 7, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 7, 2026
@github-actions github-actions Bot removed the bug Something isn't working label Jul 8, 2026
@deon-sanchez deon-sanchez changed the title fix: /assets/knowledge-base accessibility fix: assets/knowledge-base accessibility Jul 10, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 10, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 13, 2026
@deon-sanchez
deon-sanchez enabled auto-merge July 13, 2026 14:50
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 13, 2026
…bility tests

Modified the test ID for the OpenAI text embedding option in the knowledge bases accessibility test to ensure accurate visibility checks. This change enhances the reliability of the accessibility tests for the embedding dropdown.
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 13, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 13, 2026
@deon-sanchez
deon-sanchez disabled auto-merge July 13, 2026 18:29
@deon-sanchez
deon-sanchez enabled auto-merge July 13, 2026 18:51
@deon-sanchez
deon-sanchez added this pull request to the merge queue Jul 13, 2026
@erichare
erichare removed this pull request from the merge queue due to the queue being cleared Jul 13, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 13, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 13, 2026
…ation

- Added .cursor/settings.local.json to .gitignore for personal settings.
- Revised the description and workflow of the ibm-a11y-level1-audit skill to clarify its default behavior and remediation process.
- Updated related skills references and progress checklist to reflect changes in auditing and fixing accessibility issues.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working lgtm This PR has been approved by a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants