Add submenu() method to Menu for nested plain lists - #137
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #137 +/- ##
===========================================
Coverage 100.00% 100.00%
- Complexity 316 324 +8
===========================================
Files 8 8
Lines 1005 1064 +59
===========================================
+ Hits 1005 1064 +59 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR adds an opt-in submenu() mode to the Menu widget to render hierarchical menu items as plain nested lists (<ul>/<li>) instead of delegating submenus to Dropdown::widget(), enabling use-cases like sidebars, sitemaps, and tree navigation.
Changes:
- Add
Menu::submenu(bool)flag and pass it intoHelper\Normalizer::menu()to normalize parent items when nested rendering is enabled. - Update
Menu::renderItems()to recursively render nested lists whensubmenu(true)is set. - Add PHPUnit coverage for submenu rendering and edge cases; update changelog.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
src/Menu.php |
Adds submenu state + setter and implements recursive nested-list rendering path. |
src/Helper/Normalizer.php |
Extends menu normalization to also normalize parent items when submenu is enabled. |
tests/Menu/MenuTest.php |
Adds tests validating nested-list output, active items, and invalid tag inputs in submenu mode. |
tests/Menu/ImmutableTest.php |
Ensures submenu() preserves immutability contract. |
CHANGELOG.md |
Documents the new submenu() feature entry. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
📝 WalkthroughWalkthroughThe PR adds a ChangesMenu Submenu Nested List Feature
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 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: 2
🤖 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/Helper/Normalizer.php`:
- Around line 92-100: Parent items in submenu(true) mode aren't marked active
when a child matches currentPath; update the block that handles $submenu so that
after computing the child's active state (use self::active($child,
$items[$i]['link'], $currentPath, $activateItems)) you propagate it to the
parent by setting $items[$i]['active'] = $items[$i]['active'] || $childActive
(or OR together any child/descendant active results). Ensure you evaluate all
relevant children/descendants and use the same self::active call used for
individual items so Menu::renderItem() will render parents as active when any
child is active.
In `@src/Menu.php`:
- Around line 718-759: The code assumes every $item is an array and indexes into
$item['items'] and $item['visible'], which breaks when Menu::items() contains
raw string entries (e.g. '-' or 'label'); before treating a child as an array
add a guard like is_array($item) (or is_string($item) check) and handle string
entries by rendering them as a dropdown entry (reuse
$this->renderDropdown([$item]) or the same treatment used earlier) instead of
indexing into $item or calling $this->renderItem($item); update the branch
around renderDropdown([$item]), renderItems(), renderItem(), and the visibility
checks so string items are returned/added to $lines immediately and only arrays
proceed to access ['items'] or ['visible'].
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 9b7f33f1-f588-4600-aa23-07d6b32ce03e
📒 Files selected for processing (6)
CHANGELOG.mdsrc/Helper/Normalizer.phpsrc/Menu.phptests/Helper/NormalizerTest.phptests/Menu/ImmutableTest.phptests/Menu/MenuTest.php
What does this PR do?
Add
submenu()method toMenu. Whensubmenu(true)is set, items with sub-items render as nested<ul>/<li>lists instead of delegating toDropdown::widget().Currently, all items with sub-items go through Dropdown, which adds toggle buttons,
data-bs-toggle, and dropdown-specific markup. This makes Menu unusable for sidebar navigation, sitemaps, or tree menus that need plain nested lists.With
submenu(true), parent items render their own link viarenderItem(), and sub-items are rendered recursively throughrenderItems().Normalizer::menu()also normalizes parent items (label, link, active, etc.) when$submenuis true.It also fixes a
TypeErrorwhen menu items contain raw string entries like-. Such strings now render directly, matching the documenteditems()behavior.No BC break:
submenudefaults tofalse, preserving current Dropdown behavior.Summary by CodeRabbit
New Features
submenu()method enabling the Menu widget to render nested items as plain HTML lists instead of dropdown widgets.Tests