Skip to content
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

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

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from

Conversation

hashiqi12138
Copy link
Contributor

@hashiqi12138 hashiqi12138 commented Mar 12, 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?

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

  • New Features

    • Enhanced the navigation menu to support customizable icons for menu items, available across various configurations and levels.
    • Introduced new components utilizing modern patterns to showcase icon functionality.
  • Style

    • Updated visual styling with new theme variables for icon size, color, spacing, and hover effects, improving the user interface.
  • Tests

    • Added automated tests to ensure icons render correctly and slot-based customization takes effect.

Sorry, something went wrong.

Copy link

coderabbitai bot commented Mar 12, 2025

Walkthrough

The changes extend the navigation menu functionality by adding an icon property across multiple components and files. A new slot and interface modifications are introduced to support customizable icons. New Vue components and demos showcase the icon feature, while updates in tests and CSS files ensure proper rendering and styling. The renderless package is updated to include the icon property in its data structure and types, and additional CSS variables and classes are added to manage icon appearance.

Changes

File(s) Change Summary
examples/.../apis/nav-menu.js Added new icon slot in the exported object and updated IDataItem interface with optional icon property.
examples/.../nav-menu/menu-icon-composition-api.vue
examples/.../nav-menu/menu-icon.vue
examples/.../nav-menu/menu-icon.spec.ts
Introduced new Vue components and a Playwright test that incorporate menu icons using Composition API, slot-based customization, and conditional icon rendering.
examples/.../nav-menu/webdoc/nav-menu.js Added a new demo entry (demoId: 'menu-icon') to showcase the menu icon functionality.
packages/renderless/src/nav-menu/index.ts
packages/renderless/types/nav-menu.type.ts
Updated data initialization to include the icon property and modified the menu item type to support an optional icon; adjusted tooltip width calculation.
packages/theme/src/nav-menu/index.less
packages/theme/src/nav-menu/vars.less
Added a new .menu-icon class and new CSS variables for icon margin, size, and color (including hover state) to enhance icon styling.
packages/vue/src/nav-menu/__tests__/nav-menu.test.tsx
packages/vue/src/nav-menu/src/pc.vue
Updated tests to include new icon components (IconShare) and modified the PC navigation component to conditionally render icons using slots or default components.

Sequence Diagram(s)

Loading
sequenceDiagram
    participant U as User
    participant NM as NavMenu Component
    participant RL as Renderless Logic
    participant IC as Icon Component

    U->>NM: Interact with menu item
    NM->>RL: Build menu data (including optional icon)
    RL-->>NM: Return menu item data with `icon`
    alt Icon exists
        NM->>IC: Render custom icon via slot/default component
    else No icon
        NM-->>NM: Render menu without icon
    end
    NM-->>U: Display updated menu with icon support

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • zzcr

Poem

I hopped through code with joyful delight,
Adding icons that shine soft and bright.
Each menu now sports a stylish new face,
With slots and tests keeping up the pace.
Hop on, dear coder, for a magical byte!
🐰✨

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.

 ERR_PNPM_OPTIONAL_DEPS_REQUIRE_PROD_DEPS  Optional dependencies cannot be installed without production dependencies

✨ 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 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 the enhancement New feature or request (功能增强) label Mar 12, 2025
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
examples/sites/demos/pc/app/nav-menu/menu-icon.vue
examples/sites/demos/pc/app/nav-menu/webdoc/nav-menu.js
新增了菜单图标的演示和文档说明。
packages/renderless/src/nav-menu/index.ts
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属性和插槽的测试用例。
packages/vue/src/nav-menu/src/pc.vue 在组件中实现了icon属性和插槽的功能。

@@ -577,7 +578,7 @@ export const handleTitleMouseenter =
const text = target.textContent
const font = window.getComputedStyle(target).font
const rect = target.getBoundingClientRect()

Choose a reason for hiding this comment

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

The adjustment from rect.width + 2 to rect.width + 4 in the omitText function might affect text truncation behavior. Ensure that this change does not unintentionally alter the display of text in the navigation menu.

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

@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. By adding and modifying codes in multiple files, the configuration and display functions of menu icons are realized.

Changes

File Summary
examples/sites/demos/apis/nav-menu.js Added description and demonstration configuration of the 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/webdoc/nav-menu.js
Added a demonstration and documentation for menu icons.
packages/renderless/src/nav-menu/index.ts
packages/renderless/types/nav-menu.type.ts
Modified the data structure to support the icon property.
packages/theme/src/nav-menu/index.less
packages/theme/src/nav-menu/vars.less
Added styles related to menu icons.
packages/vue/src/nav-menu/__tests__/nav-menu.test.tsx Added test cases for icon properties and slots.
packages/vue/src/nav-menu/src/pc.vue The functions of the icon property and slot are implemented in the 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)
packages/renderless/types/nav-menu.type.ts (1)

16-16: Consider using a more specific type instead of any

Using any type for the icon property reduces type safety. Consider using a more specific type like Component | string | null to better represent what the icon property can contain, which would provide better type checking and IDE autocompletion for developers.

-  icon?: any
+  icon?: Component | string | null
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4c9a00a and 9922932.

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

3-11: Test looks good for the basic functionality

The test correctly verifies the visibility of both the menu icon and its SVG element. This covers the basic functionality of the new feature.

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

55-66: New demo entry looks good

The demo entry for the menu icon feature is well-structured and consistent with other demo entries in the file. The descriptions are clear and provided in both Chinese and English.

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

131-140: New slot definition looks good

The icon slot is properly defined with clear descriptions in both languages, consistent with other slot definitions.

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

1-5: Clean template structure with proper component usage.

The template is well-structured, using a simple container div with the preview class and properly binding the menuData to the TinyNavMenu component.


7-11: Appropriate imports and setup configuration.

The component correctly imports necessary dependencies:

  • Vue's ref for reactive state management
  • TinyNavMenu component from the library
  • Icon components that will be used in the menu data

12-139: Well-structured menu data with proper icon implementation.

The menu data is properly structured as a reactive ref array with nested items. Icons are correctly implemented at various levels of the menu hierarchy:

  1. Root level (line 17)
  2. First-level children (line 28)
  3. Deep nested items (lines 51 and 57)

This provides a comprehensive demonstration of icon usage at different menu levels.


142-150: Appropriate styling with good practices.

The CSS is properly scoped to the component and includes:

  1. A minimum height for the preview container to ensure proper display
  2. Removal of text decoration on hover for links inside the menu, improving visual consistency

These styles work well with the component's functionality.

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

1-14: Comprehensive demonstration of both icon implementation methods.

The template effectively showcases two approaches to implement icons:

  1. Configuration mode (line 4): Using the icon property directly in the menu data
  2. Slot mode (lines 7-12): Using a named slot with conditional rendering based on item state

This provides users with flexibility in how they implement icons in their menus.


16-25: Proper component registration and icon implementation.

The script correctly:

  1. Imports the necessary components
  2. Registers both the main component and the icon components
  3. Uses the icon factory functions properly

This approach makes the icons available for both the configuration and slot modes.


26-157: Well-organized data structure with icon configuration.

The data method returns a well-structured menu configuration with icons assigned to various items. The implementation matches what we see in the Composition API example, providing consistency across examples.


161-173: Clean and purposeful CSS styling.

The CSS is properly scoped and includes:

  1. Consistent minimum height for the preview
  2. Appropriate margin between multiple menu instances (line 167)
  3. Removal of text decoration on hover for menu links

These styles enhance the visual presentation of the demo.

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

40-45: Well-implemented icon rendering for main menu items.

The implementation correctly:

  1. Conditionally renders a div with class "menu-icon" when either slots.icon or item.icon exists
  2. Uses a named slot with appropriate props passed (item, index, selected state)
  3. Provides a default fallback that renders the item.icon as a component
  4. Applies appropriate CSS classes for styling

This approach provides flexibility while maintaining backward compatibility.


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

The same pattern is correctly replicated for the "more" menu, ensuring consistent behavior and appearance. The component passes the appropriate context to the slot (item, index, selected state).


129-139: Proper icon handling for group titles in the sub-menu.

The icon implementation for group titles in the sub-menu follows the same pattern as other menu items, providing consistency throughout the component. All necessary context is passed to the slot.


160-165: Consistent icon implementation for sub-menu items.

The same pattern is applied to sub-menu items, maintaining consistency across all levels of the menu. This ensures that icons can be used at any level of the menu hierarchy.

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

172-174: Proper data structure update to support the icon property.

The buildData function now correctly includes the icon property from the menu item, enabling the icon functionality in the renderless implementation. This change ensures that icons specified in the data are properly passed to the component.


581-582: Tooltip width adjustment for better text display.

The width adjustment in the omitText function call has been modified from +2 to +4 pixels, providing more space for the tooltip text. This subtle change improves the user experience by reducing the chance of text being unnecessarily truncated.

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

60-69: Looks good! Well structured icon styling.

The .menu-icon class implementation provides consistent styling for icons within menu items. The use of CSS variables follows the project's convention and maintains a clean, maintainable approach.


78-80: Proper handling of SVG hover states.

The hover state styling for SVG elements follows best practices by changing the fill color using the designated CSS variable.


87-89: Consistent selected state styling.

The selected state styling for SVG icons matches the hover state, maintaining visual consistency when menu items are selected.


199-202: Properly implemented icon styling for selected state in more menu.

The use of !important here is appropriate since it ensures the selected state takes precedence in the component hierarchy.


230-240: Well-implemented icon styling for more menu items.

The styling for icons in the more menu follows the same pattern as the main menu, maintaining consistency throughout the component.


289-299: Consistent implementation for sub-menu title icons.

The styling for icons in sub-menu titles matches the pattern used elsewhere, ensuring visual consistency.


305-307: Proper styling for selected state in sub-menu titles.

The SVG fill color change for selected sub-menu titles maintains visual consistency with other selected states.


336-346: Good addition of underline effect on hover.

Adding the underline effect enhances the visual feedback for users when hovering over menu items.


365-374: Consistent icon styling for sub-items.

The icon styling for sub-items follows the same pattern as other menu items, maintaining visual consistency.


391-393: Proper selected state styling for sub-items.

The SVG fill color change for selected sub-items maintains visual consistency with other selected states.


401-403: Appropriate hover state styling for sub-items.

The hover state styling for sub-items' SVG elements follows the same pattern as other hover states.


480-482: Good vertical alignment for more-button SVGs.

Setting the vertical alignment ensures proper visual alignment of SVG icons in the more button.

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

78-85: Well-defined CSS variables for icon styling.

The addition of these icon-related CSS variables follows best practices:

  1. Proper naming convention consistent with existing variables
  2. Clear comments explaining the purpose of each variable
  3. Reuse of base variables (--tv-space-base, --tv-icon-size, etc.) for consistency
  4. Separation of concerns with dedicated variables for different states (normal and hover)

This approach ensures the icon styling can be easily customized through the theming system.

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

1-1: Properly imported the new icon component.

The import statement has been updated to include the new IconShare component alongside the existing IconTotal.


9-11: Good practice creating component instances.

Creating component instances before using them in tests improves readability and makes the tests more maintainable.


206-217: Well-structured mock data for icon testing.

The mock data includes variations with and without icons, which will help test different scenarios:

  1. An item with an icon component
  2. An item with an empty icon property

This provides good coverage for the new feature.


229-234: Good basic test for icon rendering.

This test verifies that the icon component is properly rendered when specified in the data. The test is concise and focuses on a single aspect of functionality.


260-271: Proper testing of icon slot functionality.

This test verifies that the icon slot works correctly, ensuring that custom icons can be provided through the slot mechanism.


272-284: Important test for slot priority.

This test verifies that slot content takes precedence over the icon attribute, which is an important behavior to confirm. The assertions are clear and thorough, checking both the presence of the slotted icon and the absence of the attribute icon.

@@ -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 type declaration

There is a typo in the type declaration 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

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

2 participants