fix: assets/knowledge-base accessibility - #13973
Conversation
… 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.
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughThis PR adds a ChangesKnowledge Base accessibility improvements
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
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 9✅ Passed checks (9 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
✅ Test Coverage AdvisorNo source changes detected without accompanying tests. Thanks for keeping coverage up! 🎉
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (4)
src/frontend/src/locales/de.json (1)
965-965: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low valueGerman quotation spacing deviates from convention.
„ {{name}} “inserts spaces inside the guillemet-style quotes; standard German typography uses„{{name}}“without internal spacing (as doesmoreActionsForandremoveFile).✏️ 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 winDuplicate gate-release pattern; use the existing
gateRoutehelper.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 winReport counts line stays unfiltered by
ignoreRules, unlike "New issues".
New issuesreflects theignoreRules-filtered count, butReport counts: violation=…still uses the rawreport.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 valueInconsistent quoting of interpolated names between strings.
moreActionsForwraps{{name}}in guillemets (« … ») whileremoveFileleaves 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
📒 Files selected for processing (24)
.secrets.baselinesrc/frontend/src/components/common/crashErrorComponent/index.tsxsrc/frontend/src/components/common/radixAriaControlsFix/index.tsxsrc/frontend/src/locales/de.jsonsrc/frontend/src/locales/en.jsonsrc/frontend/src/locales/es.jsonsrc/frontend/src/locales/fr.jsonsrc/frontend/src/locales/ja.jsonsrc/frontend/src/locales/pt.jsonsrc/frontend/src/locales/zh-Hans.jsonsrc/frontend/src/modals/knowledgeBaseUploadModal/components/FilesPanel.tsxsrc/frontend/src/modals/knowledgeBaseUploadModal/components/StepReview.tsxsrc/frontend/src/pages/MainPage/pages/knowledgePage/components/IngestionRunDetailModal.tsxsrc/frontend/src/pages/MainPage/pages/knowledgePage/components/KnowledgeBaseDrawer.tsxsrc/frontend/src/pages/MainPage/pages/knowledgePage/components/KnowledgeBasesTab.tsxsrc/frontend/src/pages/MainPage/pages/knowledgePage/config/knowledgeBaseColumns.tsxsrc/frontend/src/pages/MainPage/pages/knowledgePage/index.tsxsrc/frontend/src/pages/MainPage/pages/knowledgePage/sourceChunksPage/SourceChunksPage.tsxsrc/frontend/src/pages/MainPage/pages/knowledgePage/sourceChunksPage/components/ChunkCard.tsxsrc/frontend/tests/a11y/helpers/knowledge-bases.fixtures.tssrc/frontend/tests/a11y/knowledge-bases.a11y.spec.tssrc/frontend/tests/fixtures.tssrc/frontend/tests/utils/accessibility-checker.tssrc/frontend/tests/utils/types.ts
| document.querySelectorAll("[data-radix-focus-guard]").forEach((node) => { | ||
| node.setAttribute("tabindex", "-1"); | ||
| node.setAttribute("aria-hidden", "true"); | ||
| }); |
There was a problem hiding this comment.
🩺 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:
- 1: https://radix-ui-primitives.mintlify.app/api/focus-guards
- 2: https://cs.usm.maine.edu/~behrooz.mansouri/AIIRLab/node_modules/@radix-ui/react-focus-guards/dist/index.mjs.map
- 3: https://radix-ui-primitives.mintlify.app/api/focus-scope
- 4: https://app.unpkg.com/@radix-ui/react-focus-scope@1.1.10/files/dist/index.mjs.map
🌐 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:
- 1: https://radix-ui-primitives.mintlify.app/api/focus-guards
- 2: https://radix-ui-primitives.mintlify.app/api/focus-scope
- 3: https://www.jinghuangsu.com/til/radix-ui-focus-scope
- 4: [Dialog]: Adding tabindex breaks tabbing radix-ui/primitives#1673
- 5: https://github.com/radix-ui/primitives/blob/7d884d2bddf9501187be77ae1ba406b8ea15ce24/packages/react/popover/src/Popover.tsx
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.
| fixClosedTriggers(); | ||
|
|
||
| const observer = new MutationObserver(fixClosedTriggers); | ||
| observer.observe(document.body, { | ||
| subtree: true, | ||
| childList: true, | ||
| attributes: true, | ||
| attributeFilter: ["data-state", "aria-controls"], | ||
| }); | ||
|
|
||
| return () => observer.disconnect(); |
There was a problem hiding this comment.
🚀 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.
| 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.
… 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.
…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.
…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.
…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.
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
RadixAriaControlsFixcomponent, improved focus management for command lists, and enhanced accessibility for database and model input components. Additionally, it removes excessive inline comments fromModelInputComponentfor better maintainability.Accessibility and ARIA improvements:
RadixAriaControlsFixcomponent (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.CrashErrorComponentto use a semantic<main>tag instead of a<div>, improving accessibility and document structure. [1] [2]Command list focus and input improvements:
focusCommandListOnOpenutility into both the database provider and model input popovers to ensure the command list receives focus when opened, enhancing keyboard navigation. [1] [2] [3]Commandcomponent 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:
ModelInputComponent, streamlining the code and making it easier to maintain without affecting logic or behavior. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14]These changes collectively improve accessibility, keyboard usability, and code clarity across the relevant UI components.
Test plan for QA
Automated (CI / local)
cd src/frontend && RUN_A11Y=true npx playwright test tests/a11y/knowledge-bases.a11y.spec.ts --project=chromium --workers=1RUN_A11Y=true RUN_A11Y_ASSERT=true npx playwright test tests/a11y/knowledge-bases.a11y.spec.ts --project=chromium --workers=1a11y-scanworkflow is green for this branchManual — Knowledge Bases list (
/assets/knowledge-bases)Keyboard & focus
Row actions & states
Drawer & ingestion runs
Create / Add sources modal
Search / empty / error
Manual — Chunks page (
/assets/knowledge-bases/{kb}/chunks)Assistive tech / visual spot checks
Regression