Skip to content

feat(nav-menu): [nav-menu] 新增 icon 属性及icon slot,支持配置菜单图标 #3181

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from

Conversation

hashiqi12138
Copy link
Contributor

@hashiqi12138 hashiqi12138 commented Mar 25, 2025

PR

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our Commit Message Guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

What is the current behavior?

新增 icon 属性及icon slot,支持配置菜单图标

Issue Number: ##3104

What is the new behavior?

新增 icon 属性及icon slot,支持配置菜单图标

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

  • New Features

    • Navigation menus now support customizable icons for each item, with flexible display options.
    • New demo views highlight icon integration and slot-based customization for a richer navigation experience.
  • Tests

    • Added tests to verify proper rendering and behavior of menu icons, ensuring that custom icons display as intended.
  • Style

    • Updated visual styling for menu icons, including refined hover effects and adjustable sizing and spacing for enhanced appearance.

Sorry, something went wrong.

Copy link

coderabbitai bot commented Mar 25, 2025

Walkthrough

This pull request introduces an icon slot to the navigation menu component and updates related interfaces to accept an optional icon property. New Vue component files and demos have been added to showcase menu icon functionality, along with tests verifying proper icon rendering and slot precedence. Additionally, updates in the renderless and theme packages incorporate the icon property in data structures and styling. These modifications enable customizable menu icons in both the API and the rendered UI.

Changes

File(s) Summary
examples/sites/demos/apis/nav-menu.js Added a new icon slot with properties (defaultValue, desc, mode, pcDemo) in the API definition and updated the IDataItem interface to include an optional icon property.
examples/sites/demos/pc/app/nav-menu/menu-icon-composition-api.vue,
examples/sites/demos/pc/app/nav-menu/menu-icon.vue,
examples/sites/demos/pc/app/nav-menu/menu-icon.spec.ts,
examples/sites/demos/pc/app/nav-menu/webdoc/nav-menu.js
Introduced new Vue components implementing a navigation menu with icon support, added a new demo entry for menu icons, and created tests to verify icon and slot rendering.
packages/renderless/src/nav-menu/index.ts,
packages/renderless/types/nav-menu.type.ts
Updated data initialization to include the icon property and modified tooltip width calculation; enhanced type definitions by adding an optional icon property to the menu item interface.
packages/theme/src/nav-menu/index.less,
packages/theme/src/nav-menu/vars.less
Added a new .menu-icon class and several CSS custom properties to style navigation menu icons, including margin, size, and color with hover effects.
packages/vue/src/nav-menu/__tests__/nav-menu.test.tsx,
packages/vue/src/nav-menu/src/pc.vue
Extended test files with new icon components to verify icon rendering and slot priority; updated the component markup to conditionally render icons before item titles based on slot presence or the icon attribute.

Sequence Diagram(s)

Loading
sequenceDiagram
  participant U as User
  participant N as NavMenu Component
  participant D as DataItem
  
  U->>N: Request menu rendering
  N->>D: Retrieve menu item data (with optional icon)
  alt Icon slot provided
    N->>N: Render custom icon from slot
  else if item.icon exists
    N->>N: Render default icon from data attribute
  else
    N->>N: Render item without icon
  end
  N->>U: Display menu with appropriate icon

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • zzcr

Poem

I'm a bouncy bunny in the code,
Hopping through slots with a happy mode.
Icons now dance next to each line,
In menus so cool, perfectly designed.
With carrots and code, I celebrate this load!
🐰💻

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

examples/sites/demos/apis/nav-menu.js

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-vue".

(The package "eslint-plugin-vue" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-vue@latest --save-dev

The plugin "eslint-plugin-vue" was referenced from the config file in ".eslintrc.js » @antfu/eslint-config » @antfu/eslint-config-vue".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

examples/sites/demos/pc/app/nav-menu/menu-icon-composition-api.vue

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-vue".

(The package "eslint-plugin-vue" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-vue@latest --save-dev

The plugin "eslint-plugin-vue" was referenced from the config file in ".eslintrc.js » @antfu/eslint-config » @antfu/eslint-config-vue".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

examples/sites/demos/pc/app/nav-menu/menu-icon.spec.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-vue".

(The package "eslint-plugin-vue" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-vue@latest --save-dev

The plugin "eslint-plugin-vue" was referenced from the config file in ".eslintrc.js » @antfu/eslint-config » @antfu/eslint-config-vue".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

  • 6 others
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Sorry, something went wrong.

@github-actions github-actions bot added bug Something isn't working enhancement New feature or request (功能增强) labels Mar 25, 2025
Copy link

[e2e-test-warn]
The component to be tested is missing.

The title of the Pull request should look like "fix(vue-renderless): [action-menu, alert] fix xxx bug".

Please make sure you've read our contributing guide

Copy link

Walkthrough

此PR为nav-menu组件新增了icon属性和icon插槽,允许用户自定义菜单图标。此功能增强了菜单的可配置性和视觉表现力。

Changes

文件 概要
examples/sites/demos/apis/nav-menu.js 添加了icon属性的描述和默认值。
examples/sites/demos/pc/app/nav-menu/menu-icon-composition-api.vue 新增了一个示例,展示如何使用icon属性配置菜单图标。
examples/sites/demos/pc/app/nav-menu/menu-icon.spec.ts 添加了测试用例,验证菜单图标的显示。
examples/sites/demos/pc/app/nav-menu/menu-icon.vue 新增了一个示例,展示如何使用icon插槽配置菜单图标。
examples/sites/demos/pc/app/nav-menu/webdoc/nav-menu.js 添加了关于icon属性的文档说明。
packages/renderless/src/nav-menu/index.ts 在菜单项中添加了icon属性。
packages/renderless/types/nav-menu.type.ts 更新了类型定义,支持icon属性。
packages/theme/src/nav-menu/index.less 添加了样式以支持菜单图标的显示和悬浮效果。
packages/theme/src/nav-menu/vars.less 定义了菜单图标的样式变量。
packages/vue/src/nav-menu/__tests__/nav-menu.test.tsx 添加了测试用例,验证icon插槽的优先级高于icon属性。
packages/vue/src/nav-menu/src/pc.vue 在菜单组件中实现了icon属性和插槽的支持。

@@ -153,6 +163,7 @@ interface IMenuItem {
interface IDataItem {
title: string
url: string
icon?: Commonent

Choose a reason for hiding this comment

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

The type Commonent seems to be a typo. It should likely be Component. Please correct this to avoid potential runtime errors.

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


Walkthrough

This PR has added an icon attribute and an icon slot for the nav-menu component, allowing users to customize menu icons. This feature enhances the configurability and visual expression of the menu.

Changes

Documents Summary
examples/sites/demos/apis/nav-menu.js Added description and default values ​​for the icon property.
examples/sites/demos/pc/app/nav-menu/menu-icon-composition-api.vue Added an example showing how to configure the menu icon using the icon property.
examples/sites/demos/pc/app/nav-menu/menu-icon.spec.ts Added a test case to verify the display of the menu icon.
examples/sites/demos/pc/app/nav-menu/menu-icon.vue Added an example showing how to configure the menu icon using the icon slot.
examples/sites/demos/pc/app/nav-menu/webdoc/nav-menu.js Added documentation for the icon property.
packages/renderless/src/nav-menu/index.ts Added the icon property to the menu item.
packages/renderless/types/nav-menu.type.ts Updated type definition and support the icon property.
packages/theme/src/nav-menu/index.less Added styles to support the display and levitation effects of menu icons.
packages/theme/src/nav-menu/vars.less Defines the style variables for the menu icon.
packages/vue/src/nav-menu/__tests__/nav-menu.test.tsx Added a test case to verify that the icon slot has a higher priority than the icon property.
packages/vue/src/nav-menu/src/pc.vue Support for the icon property and slot are implemented in the menu component.

Copy link

@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)
examples/sites/demos/pc/app/nav-menu/menu-icon.spec.ts (1)

1-11: Test case looks good, but could be more comprehensive

The test verifies icon visibility, which is a good start. However, consider adding more test cases to verify different icon behaviors such as:

  • Testing with different icon types
  • Checking icon rendering in child menu items
  • Verifying icon slot overrides the icon property
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9cf817a and 0377eb4.

📒 Files selected for processing (11)
  • examples/sites/demos/apis/nav-menu.js (2 hunks)
  • examples/sites/demos/pc/app/nav-menu/menu-icon-composition-api.vue (1 hunks)
  • examples/sites/demos/pc/app/nav-menu/menu-icon.spec.ts (1 hunks)
  • examples/sites/demos/pc/app/nav-menu/menu-icon.vue (1 hunks)
  • examples/sites/demos/pc/app/nav-menu/webdoc/nav-menu.js (1 hunks)
  • packages/renderless/src/nav-menu/index.ts (2 hunks)
  • packages/renderless/types/nav-menu.type.ts (1 hunks)
  • packages/theme/src/nav-menu/index.less (8 hunks)
  • packages/theme/src/nav-menu/vars.less (1 hunks)
  • packages/vue/src/nav-menu/__tests__/nav-menu.test.tsx (4 hunks)
  • packages/vue/src/nav-menu/src/pc.vue (4 hunks)
🔇 Additional comments (36)
packages/renderless/types/nav-menu.type.ts (1)

16-16: Good addition of icon property to menuItemType interface

The addition of the icon?: any property to the menuItemType interface allows menu items to include icons, enhancing the visual presentation of the navigation menu.

examples/sites/demos/pc/app/nav-menu/webdoc/nav-menu.js (1)

57-68: Demo entry properly added with translations

The new demo entry for menu icons has been correctly added with proper translations for both name and description. This ensures users can understand how to use the new icon feature.

examples/sites/demos/apis/nav-menu.js (1)

131-140: Icon slot properly defined with descriptions

The icon slot is properly defined with clear descriptions in both Chinese and English, and correctly linked to the corresponding demo.

examples/sites/demos/pc/app/nav-menu/menu-icon-composition-api.vue (4)

1-5: Good use of the Vue 3 Composition API for this demo component.

The template structure is clean and straightforward, clearly demonstrating the new icon functionality.


7-11: Appropriate imports for the demo implementation.

The component correctly imports the necessary dependencies including Vue's ref, the TinyNavMenu component, and the icons needed for the demo.


12-139: Well-structured menuData with proper icon implementation.

The menuData structure demonstrates the new icon functionality effectively by:

  1. Using different icon components (iconTotal, iconGenerating)
  2. Showing icons at various nesting levels of the menu
  3. Omitting icons from some items to show both states

This provides a comprehensive example for users to understand how to implement menu icons.


142-150: Clean and appropriate styling.

The styling maintains consistency with the component's design while ensuring proper display in the demo environment.

examples/sites/demos/pc/app/nav-menu/menu-icon.vue (4)

1-14: Excellent demonstration of both icon configuration approaches.

The template effectively showcases two implementation methods:

  1. Configuration mode (配置模式): Using the icon property in data
  2. Slot mode (slot 模式): Using the #icon slot with conditional rendering

This dual approach provides users with flexibility in how they implement icons.


16-25: Well-structured component registration.

The component properly imports and registers the required dependencies. Notably, the icon components are registered correctly to enable their use both in the template slot and in the data structure.


26-157: Comprehensive menuData structure with icons.

The data structure demonstrates the new icon functionality at multiple levels of the menu hierarchy. This provides a thorough example of how to implement icons in different scenarios.


161-173: Appropriate styling for the demo.

The styling ensures proper display of the menu components with adequate spacing and hover behavior.

packages/theme/src/nav-menu/index.less (12)

62-71: Well-defined base styling for menu icons.

The .menu-icon styling properly handles the display and alignment of icons within menu items. The CSS rules follow best practices for SVG rendering:

  • Using inline-block for display
  • Setting appropriate vertical alignment
  • Using CSS variables for consistent spacing and sizes

79-83: Proper hover state styling for icons.

The hover state correctly changes the SVG fill color using the theme variable, ensuring consistent theme integration.


89-91: Consistent selected state styling for icons.

The selected state styling matches the hover state for the SVG fill color, providing a cohesive user experience.


201-204: Important override for selected state in more menu.

Using !important here is actually appropriate since this rule needs to take precedence over potentially conflicting rules from other selectors.


232-241: Consistent replication of icon styling for popmenu.

The styling for icons in the popmenu matches the main menu, ensuring a consistent look and feel across different menu states.


291-300: Proper icon styling for group titles.

The styling for icons in group titles is consistent with other menu items, maintaining visual harmony.


307-309: Selected state for group titles properly handles icon styling.

The icon color changes appropriately when a group title is selected.


337-348: Nice hover effect for submenu items.

The underline effect on hover adds a nice visual cue for users, improving the interactive experience.


367-376: Consistent icon styling for submenu items.

The styling for icons in submenu items matches the rest of the component, ensuring visual consistency.


393-395: Selected state for submenu items properly handles icon styling.

The icon color changes appropriately when a submenu item is selected.


398-406: Consistent hover and active states for submenu items.

The styling for hover, active, and selected states is consistent across all menu item types.


482-484: Proper vertical alignment for menu button icons.

The SVG vertical alignment ensures the icons are properly positioned in the menu button.

packages/vue/src/nav-menu/src/pc.vue (4)

40-46: Well-implemented icon rendering with slot fallback pattern.

The implementation correctly:

  1. Conditionally renders the icon container only when needed
  2. Uses a named slot with relevant props (item, index, selected)
  3. Provides a fallback for the icon component if the slot isn't used

This approach gives users flexibility while keeping the code clean.


94-99: Consistent icon implementation in more menu items.

The icon implementation in the more menu follows the same pattern as the main menu, ensuring consistency across different menu sections.


129-139: Proper icon implementation in submenu group titles.

The group title icons use the same slot/fallback pattern, providing consistent behavior across the component.


160-165: Consistent icon implementation in submenu items.

The icon implementation in submenu items maintains the same pattern as other menu items, ensuring a unified approach throughout the component.

packages/theme/src/nav-menu/vars.less (1)

84-91: LGTM! Icon styling variables appropriately defined.

The addition of these CSS custom properties for the menu icons follows the existing pattern and correctly references base design system variables. This ensures consistent styling and makes the component more customizable.

packages/renderless/src/nav-menu/index.ts (2)

172-173: LGTM! Icon property successfully added to the menu item data structure.

The addition of the icon property to the object returned by the buildData function properly extends the data structure to support menu icons.


581-581: Increased text measurement buffer improves tooltip accuracy.

The change from rect.width + 2 to rect.width + 4 provides more buffer space when determining if text needs to be truncated with a tooltip, which can prevent edge cases where text is cut off without showing a tooltip.

packages/vue/src/nav-menu/__tests__/nav-menu.test.tsx (6)

1-1: LGTM! Added IconShare import for new icon functionality.

Properly importing the necessary icon component for testing the new icon feature.


9-10: LGTM! Component instances created for testing.

Created reusable icon component instances that can be used across multiple tests.


206-217: LGTM! Added mock data with icon property.

The new mock data structure properly includes the icon property, providing good test cases with both populated and empty icon values.


229-233: LGTM! Test for icon property rendering.

This test correctly verifies that the icon passed via the data property is properly rendered in the component.


260-270: LGTM! Test for icon slot functionality.

This test properly verifies that the icon slot mechanism works correctly.


272-284: LGTM! Test for slot priority over icon attribute.

This test verifies an important behavior - that when both an icon attribute and slot are provided, the slot content takes precedence. This ensures proper component composition patterns.

@@ -153,6 +163,7 @@ interface IMenuItem {
interface IDataItem {
title: string
url: string
icon?: Commonent
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix typo in IDataItem interface

There's a typo in the type definition for the icon property - "Commonent" should be "Component".

-  icon?: Commonent 
+  icon?: Component 
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
icon?: Commonent
icon?: Component

@zzcr
Copy link
Member

zzcr commented Mar 25, 2025

在标题中可以用:[nav-menu] 触发下e2e测试用例哈,可以参考下其他的mr或者贡献指南

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


In the title, you can use: [nav-menu] to trigger the e2e test case. You can refer to other mr or contribution guides.

@hashiqi12138 hashiqi12138 changed the title feat(nav-menu): 新增 icon 属性及icon slot,支持配置菜单图标 feat(nav-menu): [nav-menu] 新增 icon 属性及icon slot,支持配置菜单图标 Mar 26, 2025
@kagol kagol removed the bug Something isn't working label Mar 31, 2025
'en-US': 'Customize the menu icon'
},
mode: ['pc'],
pcDemo: 'menu-icon'
Copy link
Member

Choose a reason for hiding this comment

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request (功能增强)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants