Finalized the configuration catalog for IS#6111
Conversation
📝 WalkthroughWalkthroughThe configuration catalog page's topic filter is refactored from a native HTML select element to a custom dropdown UI. The HTML structure, CSS styling, and JavaScript event handling are updated cohesively to implement the new component while removing a WIP banner. ChangesCustom Dropdown Filter UI
Suggested labels
🚥 Pre-merge checks | ✅ 2 | ❌ 3❌ Failed checks (2 warnings, 1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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 |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
en/theme/material/assets/js/config-catalog.js (1)
137-152: 💤 Low valueReuse outer
menuand callrefresh()to avoid shadowing and divergent reset paths.
menuis already in scope from line 92, so the innervar menu = document.getElementById(...)at line 138 just shadows it. The handler can also reuserefresh()for consistency with the option-click path, sincedata-valueandsearchInput.valuehave already been reset by that point.♻️ Proposed refactor
if (clearBtn) { clearBtn.addEventListener('click', function () { - var menu = document.getElementById('mbTaskSelectMenu'); - var firstOption = menu ? menu.querySelector('.mb-custom-select__option') : null; - if (menu) { - menu.querySelectorAll('.mb-custom-select__option').forEach(function (o) { - o.classList.remove('is-selected'); - }); - } + var firstOption = menu ? menu.querySelector('.mb-custom-select__option') : null; + if (menu) { + menu.querySelectorAll('.mb-custom-select__option').forEach(function (o) { + o.classList.remove('is-selected'); + }); + } if (firstOption) { firstOption.classList.add('is-selected'); wrapper.setAttribute('data-value', firstOption.getAttribute('data-value')); valueLabel.textContent = firstOption.textContent.trim(); } if (searchInput) searchInput.value = ''; - applyFilters('', ''); + refresh(); }); }🤖 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 `@en/theme/material/assets/js/config-catalog.js` around lines 137 - 152, Remove the inner shadowing "var menu = document.getElementById(...)" in the clearBtn click handler and reuse the outer menu variable declared at line ~92; after clearing option classes and selecting the firstOption, call the existing refresh() function instead of manually setting wrapper.setAttribute('data-value', ...), valueLabel.textContent and searchInput.value so the reset path matches the option-click flow (keep a guard if firstOption is null and still clear searchInput if needed), and remove the duplicated manual apply/reset logic so the handler relies on refresh() to update UI and call applyFilters as implemented by refresh().
🤖 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 `@en/theme/material/templates/config-catalog.html`:
- Around line 79-108: The custom dropdown lacks ARIA semantics and keyboard
support: update the label/button/menu/options and JS to be accessible. In the
HTML, set the label element with an explicit association (give the label id
"mbTaskSelectLabel" a for or make the trigger reference it via aria-labelledby),
add aria-haspopup="listbox" and aria-controls="mbTaskSelectMenu" to the trigger
button (id="mbTaskSelectTrigger"), set role="listbox" and
aria-labelledby="mbTaskSelectLabel" on the menu (id="mbTaskSelectMenu"), and add
role="option" and aria-selected="false" to every option button (toggle to "true"
for the one with class "is-selected"). In config-catalog.js, whenever selection
changes (the code that toggles "is-selected"), also update aria-selected on
options, ensure the trigger's aria-expanded is updated, add an Escape-key
handler that closes the menu and returns focus to mbTaskSelectTrigger, and
ensure focus management for ArrowUp/ArrowDown navigates role="option" elements.
Also update the CSS selector change suggested (.mb-task-filter label →
.mb-task-filter__label) so styles target the labeled element.
---
Nitpick comments:
In `@en/theme/material/assets/js/config-catalog.js`:
- Around line 137-152: Remove the inner shadowing "var menu =
document.getElementById(...)" in the clearBtn click handler and reuse the outer
menu variable declared at line ~92; after clearing option classes and selecting
the firstOption, call the existing refresh() function instead of manually
setting wrapper.setAttribute('data-value', ...), valueLabel.textContent and
searchInput.value so the reset path matches the option-click flow (keep a guard
if firstOption is null and still clear searchInput if needed), and remove the
duplicated manual apply/reset logic so the handler relies on refresh() to update
UI and call applyFilters as implemented by refresh().
🪄 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.yml
Review profile: CHILL
Plan: Pro
Run ID: c2f13115-ecdd-4186-8f4e-382a612f5d36
📒 Files selected for processing (4)
en/identity-server/next/docs/_data/configuration_catalog.yamlen/theme/material/assets/css/config-catalog.cssen/theme/material/assets/js/config-catalog.jsen/theme/material/templates/config-catalog.html
| <label id="mbTaskSelectLabel">Filter by topic:</label> | ||
| <div class="mb-custom-select" id="mbTaskSelectWrapper" data-value=""> | ||
| <button type="button" class="mb-custom-select__trigger" id="mbTaskSelectTrigger" aria-expanded="false"> | ||
| <span class="mb-custom-select__label" id="mbTaskSelectValue">All configurations</span> | ||
| <svg class="mb-custom-select__chevron" xmlns="http://www.w3.org/2000/svg" width="12" height="12" | ||
| viewBox="0 0 12 12" fill="currentColor" aria-hidden="true"> | ||
| <path d="M2.22 4.47a.75.75 0 011.06 0L6 7.19l2.72-2.72a.75.75 0 111.06 1.06l-3.25 3.25a.75.75 0 01-1.06 0L2.22 5.53a.75.75 0 010-1.06z" /> | ||
| </svg> | ||
| </button> | ||
| <div class="mb-custom-select__menu" id="mbTaskSelectMenu"> | ||
| <button type="button" class="mb-custom-select__option is-selected" data-value="">All configurations</button> | ||
| <button type="button" class="mb-custom-select__option" data-value="minimum-required">Quick start / minimal setup</button> | ||
| <button type="button" class="mb-custom-select__option" data-value="configure-actions">Actions & event hooks</button> | ||
| <button type="button" class="mb-custom-select__option" data-value="configure-ai">AI services</button> | ||
| <button type="button" class="mb-custom-select__option" data-value="configure-security">API authorization</button> | ||
| <button type="button" class="mb-custom-select__option" data-value="configure-authentication">Authentication methods</button> | ||
| <button type="button" class="mb-custom-select__option" data-value="configure-clustering">Clustering & high availability</button> | ||
| <button type="button" class="mb-custom-select__option" data-value="configure-database">Database & persistence</button> | ||
| <button type="button" class="mb-custom-select__option" data-value="configure-email">Email & notifications</button> | ||
| <button type="button" class="mb-custom-select__option" data-value="configure-identity">Identity & user lifecycle</button> | ||
| <button type="button" class="mb-custom-select__option" data-value="configure-monitoring">Logging & monitoring</button> | ||
| <button type="button" class="mb-custom-select__option" data-value="configure-oauth">OAuth 2.0 & OIDC</button> | ||
| <button type="button" class="mb-custom-select__option" data-value="configure-fido">Passkeys & FIDO2</button> | ||
| <button type="button" class="mb-custom-select__option" data-value="configure-cache">Performance & caching</button> | ||
| <button type="button" class="mb-custom-select__option" data-value="configure-sts">Security token service (STS)</button> | ||
| <button type="button" class="mb-custom-select__option" data-value="configure-tls">TLS & certificates</button> | ||
| <button type="button" class="mb-custom-select__option" data-value="configure-user-store">User stores & LDAP</button> | ||
| </div> | ||
| <div class="mb-custom-select__backdrop" id="mbTaskSelectBackdrop"></div> | ||
| </div> |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
WAI-ARIA Authoring Practices select-only combobox pattern aria-haspopup listbox
💡 Result:
For a WAI-ARIA Authoring Practices “select-only combobox” pattern whose popup is a listbox, the key attributes/semantics are: 1) Use role="combobox" for the control and role="listbox" for the popup - APG defines “Select-Only Combobox” as a single-select combobox with no text input (functionally similar to a native HTML select). [1] - The APG example uses role="combobox" and role="listbox"/option roles for the popup content. [2] 2) aria-haspopup - For a combobox whose popup is a listbox, aria-haspopup is not required because combobox has an implicit aria-haspopup value of listbox. [3][4] - When you do include it, use aria-haspopup="listbox" (as shown in the APG ARIA 1.1 listbox-popup combobox examples). [5] 3) aria-expanded - Set aria-expanded="false" when collapsed and aria-expanded="true" when expanded (APG/DigitalA11Y guidance). [2][6] 4) Connect the combobox to the popup via aria-controls - APG select-only example uses aria-controls to point to the element that serves as the popup. [2] - (In the APG pattern examples, when the combobox is expanded, the combobox popup should exist and be referenced appropriately, including via aria-controls.) [6] 5) Manage active option via aria-activedescendant - In the APG select-only combobox, when the listbox is displayed, focus management is communicated using aria-activedescendant on the combobox pointing to the visually indicated option. [2] 6) Option selection state (aria-selected) - APG notes that aria-selected is used to indicate the selected item; the select-only example sets aria-selected true on the option referenced/indicated as selected. [2] Minimal attribute mapping (select-only + listbox popup) - Combobox element: role="combobox"; aria-expanded={true|false}; aria-controls={listbox id}; aria-activedescendant={focused/active option id}; (aria-haspopup optional if popup is listbox) [2][3] - Popup: role="listbox"; each item: role="option" and aria-selected (for selected item) [2] Note: Your exact attribute set may vary slightly depending on whether you follow the APG select-only example structure (div+aria-controls) or an input-based combobox structure, but the aria-haspopup/listbox and focus via aria-activedescendant principles above come directly from the APG pattern and examples. [2][7]
Citations:
- 1: https://www.w3.org/WAI/ARIA/apg/patterns/combobox/
- 2: https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-select-only/
- 3: https://www.blackdogcat.xyz/en-US/docs/Web/Accessibility/ARIA/Reference/Roles/combobox_role
- 4: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-haspopup
- 5: https://www.w3.org/TR/2017/NOTE-wai-aria-practices-1.1-20171214/examples/combobox/aria1.1pattern/listbox-combo.html
- 6: https://digitala11y.com/combobox-role
- 7: https://www.w3.org/WAI/ARIA/apg/patterns/combobox
🏁 Script executed:
git ls-files | grep -E "(config-catalog\.(html|js|css)|en/theme/material)" | head -20Repository: wso2/docs-is
Length of output: 1023
🏁 Script executed:
find . -path "*/theme/material/templates/config-catalog.html" -o -path "*/theme/material/assets/js/config-catalog.js"Repository: wso2/docs-is
Length of output: 154
🏁 Script executed:
cat -n ./en/theme/material/templates/config-catalog.html | sed -n '75,115p'Repository: wso2/docs-is
Length of output: 4031
🏁 Script executed:
cat -n ./en/theme/material/assets/js/config-catalog.jsRepository: wso2/docs-is
Length of output: 6359
🏁 Script executed:
cat -n ./en/theme/material/assets/css/config-catalog.css | sed -n '40,50p'Repository: wso2/docs-is
Length of output: 327
Custom dropdown is missing ARIA semantics required for accessible keyboard and screen-reader navigation.
Replacing a native <select> with a custom button + listbox shifts accessibility responsibility to the markup and JavaScript. The implementation has several critical gaps:
- Label association broken: The
<label>(line 79) has noforattribute and the trigger button lacksaria-labelledby, so screen readers will not announce the "Filter by topic" context. - Popup relationship undeclared: The trigger button is missing
aria-haspopup="listbox"andaria-controls="mbTaskSelectMenu", preventing AT from understanding that the button opens a listbox or which one. - Menu lacks semantic role: The menu container (line 88) has no
role="listbox"oraria-labelledby. - Options lack semantics: Option buttons (lines 89–105) have no
role="option"and noaria-selectedattributes; selected state is conveyed only via the visualis-selectedclass. - Keyboard handling incomplete: The JavaScript (config-catalog.js) has no Escape-key handler and does not restore focus to the trigger on close. It also does not toggle
aria-selectedwhen the selection changes (lines 120–122, 141–142).
🩹 Suggested HTML changes
- <label id="mbTaskSelectLabel">Filter by topic:</label>
+ <span id="mbTaskSelectLabel" class="mb-task-filter__label">Filter by topic:</span>
<div class="mb-custom-select" id="mbTaskSelectWrapper" data-value="">
- <button type="button" class="mb-custom-select__trigger" id="mbTaskSelectTrigger" aria-expanded="false">
+ <button type="button" class="mb-custom-select__trigger" id="mbTaskSelectTrigger"
+ aria-haspopup="listbox" aria-controls="mbTaskSelectMenu"
+ aria-labelledby="mbTaskSelectLabel mbTaskSelectValue" aria-expanded="false">
<span class="mb-custom-select__label" id="mbTaskSelectValue">All configurations</span>
<svg class="mb-custom-select__chevron" ... aria-hidden="true"> ... </svg>
</button>
- <div class="mb-custom-select__menu" id="mbTaskSelectMenu">
- <button type="button" class="mb-custom-select__option is-selected" data-value="">All configurations</button>
- <button type="button" class="mb-custom-select__option" data-value="minimum-required">Quick start / minimal setup</button>
+ <div class="mb-custom-select__menu" id="mbTaskSelectMenu" role="listbox" aria-labelledby="mbTaskSelectLabel">
+ <button type="button" role="option" aria-selected="true" class="mb-custom-select__option is-selected" data-value="">All configurations</button>
+ <button type="button" role="option" aria-selected="false" class="mb-custom-select__option" data-value="minimum-required">Quick start / minimal setup</button>Apply role="option" and aria-selected="false" to all remaining options, and update the CSS selector in config-catalog.css (line 44) from .mb-task-filter label to .mb-task-filter__label.
In config-catalog.js, sync aria-selected with the is-selected class and add an Escape-key handler:
menu.querySelectorAll('.mb-custom-select__option').forEach(function (o) {
o.classList.remove('is-selected');
+ o.setAttribute('aria-selected', 'false');
});
option.classList.add('is-selected');
+ option.setAttribute('aria-selected', 'true');
+ document.addEventListener('keydown', function (e) {
+ if (e.key === 'Escape' && trigger.getAttribute('aria-expanded') === 'true') {
+ setOpen(false);
+ trigger.focus();
+ }
+ });🤖 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 `@en/theme/material/templates/config-catalog.html` around lines 79 - 108, The
custom dropdown lacks ARIA semantics and keyboard support: update the
label/button/menu/options and JS to be accessible. In the HTML, set the label
element with an explicit association (give the label id "mbTaskSelectLabel" a
for or make the trigger reference it via aria-labelledby), add
aria-haspopup="listbox" and aria-controls="mbTaskSelectMenu" to the trigger
button (id="mbTaskSelectTrigger"), set role="listbox" and
aria-labelledby="mbTaskSelectLabel" on the menu (id="mbTaskSelectMenu"), and add
role="option" and aria-selected="false" to every option button (toggle to "true"
for the one with class "is-selected"). In config-catalog.js, whenever selection
changes (the code that toggles "is-selected"), also update aria-selected on
options, ensure the trigger's aria-expanded is updated, add an Escape-key
handler that closes the menu and returns focus to mbTaskSelectTrigger, and
ensure focus management for ArrowUp/ArrowDown navigates role="option" elements.
Also update the CSS selector change suggested (.mb-task-filter label →
.mb-task-filter__label) so styles target the labeled element.
Purpose
$subject