feat(components): add menu_button component with keyboard navigation#7170
feat(components): add menu_button component with keyboard navigation#7170
Conversation
…ugin Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add menu_button section to the components page with demo, slots, props, and sub-component documentation. Remove unused disabled attr from item.html c-vars. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nuItem Add menuButton Alpine component with itemClass getter that uses $menuItem.isActive for keyboard navigation visual feedback. Move hover/active styling from <li> to the <a>/<button> menu item elements where the Alpine UI plugin scope is available. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This comment has been minimized.
This comment has been minimized.
| {{ slot }} | ||
| </button> | ||
| {% else %} | ||
| <a x-menu:item href="{{ href }}" x-bind:class="itemClass" data-focused-class="{{ active_class }}" data-item-class="{{ item_class }}" {{ attrs }}> |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
Detected a template variable used in an anchor tag with the 'href' attribute. This allows a malicious actor to input the 'javascript:' URI and is subject to cross- site scripting (XSS) attacks. If using Flask, use 'url_for()' to safely generate a URL. If using Django, use the 'url' filter to safely generate a URL. If using Mustache, use a URL encoding library, or prepend a slash '/' to the variable for relative links (href="/{{link}}"). You may also consider setting the Content Security Policy (CSP) header.
To resolve this comment:
🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by var-in-href.
You can view more details about this finding in the Semgrep AppSec Platform.
The anchor plugin was omitted from the Alpine 3.15.9 upgrade (#7167). It's required by the menu_button component for dropdown positioning. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace plain <button> trigger with <c-button>, add button_variant prop (default: "primary") so callers can set the variant - Fix caret rotation regression: old header.js rotated chevrons via JS, now handled with group-aria-[expanded=true]:rotate-180 in CSS - Update header profile menu to use button_variant="outline" - Update v2_components docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…l dependency Replace hand-rolled dropdown with c-menu-button component and plain links with c-button. Banner no longer needs expansion_panel.js or the collapse plugin. Button data uses variant names instead of CSS classes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tests were checking for old header markup (hardcoded IDs, x-data="header") that no longer exists after the menu_button refactor. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Closes #7064
Adds a
c-menu-buttonCotton component implementing the ARIA menu-button pattern using the Alpine UIx-menuplugin. Includes keyboard navigation support with visual active-item feedback via$menuItem.isActive.What's included
c-menu-buttoncomponent with sub-components:c-menu-button.item,c-menu-button.dividermenuButtonAlpine component withitemClassgetter for keyboard-active item stylingc-menu-buttonfor both the "Support FLP" dropdown and the profile menuc-menu-buttonfor dropdown buttons andc-buttonfor plain links (dropsexpansion_panel.js+ collapse plugin dependency)c-buttoninternally, withbutton_variantprop for variant controlgroup-aria-[expanded=true]:rotate-180(CSS-only, replaces the old JS-based rotation fromheader.js)@alpinejs/anchorplugin added (was omitted from Upgrade Alpine.js 3.14.8 → 3.15.9, drop version from filenames #7167)/components/Dependencies
Blocked byDepends on #7167 (Alpine upgrade 3.14.8 → 3.15.9, now merged) — the UI plugin's static string bindings (role,tabindex,x-ref) require the CSP-compliant expression parser introduced in Alpine v3.15.0.Keyboard behavior (ARIA menu-button pattern)
aria-activedescendantTest plan
/components/page: menu button demo opens, navigates with keyboard, closes with Escape🤖 Generated with Claude Code