Skip to content

Finalized the configuration catalog for IS#6111

Merged
himeshsiriwardana merged 1 commit into
wso2:masterfrom
himeshsiriwardana:config-catalog-incomplete
May 7, 2026
Merged

Finalized the configuration catalog for IS#6111
himeshsiriwardana merged 1 commit into
wso2:masterfrom
himeshsiriwardana:config-catalog-incomplete

Conversation

@himeshsiriwardana
Copy link
Copy Markdown
Contributor

Purpose

$subject

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

📝 Walkthrough

Walkthrough

The 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.

Changes

Custom Dropdown Filter UI

Layer / File(s) Summary
DOM Structure
en/theme/material/templates/config-catalog.html
Native <select> element replaced with custom dropdown wrapper (mb-task-filter) containing trigger button, menu container with topic options (All configurations, minimum-required, configure-actions, etc.), and backdrop. Work in progress banner removed.
Component Styling
en/theme/material/assets/css/config-catalog.css
Custom select styling introduced for .mb-custom-select with trigger, menu, individual options, and backdrop. Trigger includes hover and expanded state styling. Search input restyled for wider, lighter-weight appearance.
Interaction Wiring
en/theme/material/assets/js/config-catalog.js
Native select event handlers replaced with wrapper-based custom control logic. Trigger click toggles menu visibility; option selection updates data-value attribute and refreshes filters. Clear button resets to first option. Search input and filter behavior preserved.

Suggested labels

Team/Identity Server Core

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is incomplete and largely empty, containing only a placeholder '$subject' without any meaningful content about the changes, purpose, test environment, or security checks as required by the template. Complete the description following the template: add a clear Purpose explaining what was changed and why, list any related PRs, specify the test environment, and complete all security checklist items.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Finalized the configuration catalog for IS' is vague and generic, using the non-descriptive term 'finalized' without clearly conveying what specific changes were made to the configuration catalog. Use a more specific title that describes the main change, such as 'Replace native select with custom dropdown in configuration catalog' or 'Refactor task filter UI with custom select component'.
✅ Passed checks (2 passed)
Check name Status Explanation
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
en/theme/material/assets/js/config-catalog.js (1)

137-152: 💤 Low value

Reuse outer menu and call refresh() to avoid shadowing and divergent reset paths.

menu is already in scope from line 92, so the inner var menu = document.getElementById(...) at line 138 just shadows it. The handler can also reuse refresh() for consistency with the option-click path, since data-value and searchInput.value have 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

📥 Commits

Reviewing files that changed from the base of the PR and between f6963cd and 4372a6f.

📒 Files selected for processing (4)
  • en/identity-server/next/docs/_data/configuration_catalog.yaml
  • en/theme/material/assets/css/config-catalog.css
  • en/theme/material/assets/js/config-catalog.js
  • en/theme/material/templates/config-catalog.html

Comment on lines +79 to +108
<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 &amp; 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 &amp; high availability</button>
<button type="button" class="mb-custom-select__option" data-value="configure-database">Database &amp; persistence</button>
<button type="button" class="mb-custom-select__option" data-value="configure-email">Email &amp; notifications</button>
<button type="button" class="mb-custom-select__option" data-value="configure-identity">Identity &amp; user lifecycle</button>
<button type="button" class="mb-custom-select__option" data-value="configure-monitoring">Logging &amp; monitoring</button>
<button type="button" class="mb-custom-select__option" data-value="configure-oauth">OAuth 2.0 &amp; OIDC</button>
<button type="button" class="mb-custom-select__option" data-value="configure-fido">Passkeys &amp; FIDO2</button>
<button type="button" class="mb-custom-select__option" data-value="configure-cache">Performance &amp; 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 &amp; certificates</button>
<button type="button" class="mb-custom-select__option" data-value="configure-user-store">User stores &amp; LDAP</button>
</div>
<div class="mb-custom-select__backdrop" id="mbTaskSelectBackdrop"></div>
</div>
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 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:


🏁 Script executed:

git ls-files | grep -E "(config-catalog\.(html|js|css)|en/theme/material)" | head -20

Repository: 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.js

Repository: 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:

  1. Label association broken: The <label> (line 79) has no for attribute and the trigger button lacks aria-labelledby, so screen readers will not announce the "Filter by topic" context.
  2. Popup relationship undeclared: The trigger button is missing aria-haspopup="listbox" and aria-controls="mbTaskSelectMenu", preventing AT from understanding that the button opens a listbox or which one.
  3. Menu lacks semantic role: The menu container (line 88) has no role="listbox" or aria-labelledby.
  4. Options lack semantics: Option buttons (lines 89–105) have no role="option" and no aria-selected attributes; selected state is conveyed only via the visual is-selected class.
  5. 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-selected when 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.

@himeshsiriwardana himeshsiriwardana merged commit 55619ce into wso2:master May 7, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants