Skip to content

Add submenu() method to Menu for nested plain lists - #137

Open
WarLikeLaux wants to merge 9 commits into
yiisoft:masterfrom
WarLikeLaux:add-menu-submenu
Open

Add submenu() method to Menu for nested plain lists#137
WarLikeLaux wants to merge 9 commits into
yiisoft:masterfrom
WarLikeLaux:add-menu-submenu

Conversation

@WarLikeLaux

@WarLikeLaux WarLikeLaux commented Mar 23, 2026

Copy link
Copy Markdown
Contributor
Q A
Is bugfix?
New feature? ✔️
Docs added?
Tests added? ✔️
Breaks BC?

What does this PR do?

Add submenu() method to Menu. When submenu(true) is set, items with sub-items render as nested <ul>/<li> lists instead of delegating to Dropdown::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 via renderItem(), and sub-items are rendered recursively through renderItems(). Normalizer::menu() also normalizes parent items (label, link, active, etc.) when $submenu is true.

It also fixes a TypeError when menu items contain raw string entries like -. Such strings now render directly, matching the documented items() behavior.

No BC break: submenu defaults to false, preserving current Dropdown behavior.

Summary by CodeRabbit

  • New Features

    • Introduced submenu() method enabling the Menu widget to render nested items as plain HTML lists instead of dropdown widgets.
    • Parent menu items now receive proper normalization when containing nested items.
  • Tests

    • Added comprehensive test coverage for submenu rendering, including nested item normalization, active state propagation, and template handling.

Review Change Stack

@codecov

codecov Bot commented Mar 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (a602b53) to head (cbd5ea1).

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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 into Helper\Normalizer::menu() to normalize parent items when nested rendering is enabled.
  • Update Menu::renderItems() to recursively render nested lists when submenu(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.

Comment thread src/Menu.php
Comment thread src/Helper/Normalizer.php
@WarLikeLaux

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown
✅ Actions performed

Full review triggered.

@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The PR adds a submenu() method to the Menu widget enabling nested menu items to render as plain HTML lists instead of dropdown widgets. Changes include Normalizer enhancements for parent item normalization, Menu property/setter/rendering logic, seven comprehensive test cases, immutability verification, and CHANGELOG documentation.

Changes

Menu Submenu Nested List Feature

Layer / File(s) Summary
Normalizer submenu parameter and parent item handling
src/Helper/Normalizer.php, tests/Helper/NormalizerTest.php
Normalizer::menu() accepts a new $submenu parameter and, when enabled, normalizes parent menu items by populating link/display fields and removing icon/encode keys from items with nested children.
Menu submenu property and fluent setter
src/Menu.php
Menu widget adds a private $submenu boolean property and exposes a fluent submenu(bool $value): self method to toggle submenu rendering mode.
Menu render and renderItems conditional submenu rendering
src/Menu.php
render() passes the submenu flag to Normalizer::menu(), and renderItems() conditionally renders nested items via dropdown (when disabled) or recursive nested lists (when enabled) with wrapping via tagName, itemsTag, and itemsContainer.
Menu submenu feature test coverage
tests/Menu/MenuTest.php
Seven test methods verify submenu rendering, required configuration validation (itemsTag and tagName), interaction with itemsContainer(false), active item propagation via currentPath, and template support with and without container wrapping.
Immutability verification and changelog
tests/Menu/ImmutableTest.php, CHANGELOG.md
Immutability test confirms submenu() returns a new Menu instance, and changelog documents the new feature for enhancement #137.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A burrow of menus, nested deep and true,
No dropdowns needed—lists shine through!
Parent and child in harmony dance,
Each item gets its proper chance. 🌿✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add submenu() method to Menu for nested plain lists' is clear, concise, and directly describes the main feature addition in the pull request. It accurately summarizes the primary change: introducing a submenu() method that enables rendering menu items as nested plain lists.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between a602b53 and a1a3612.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • src/Helper/Normalizer.php
  • src/Menu.php
  • tests/Helper/NormalizerTest.php
  • tests/Menu/ImmutableTest.php
  • tests/Menu/MenuTest.php

Comment thread src/Helper/Normalizer.php
Comment thread src/Menu.php
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants