Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat(dropdown): [dropdown] Add visible attribute, support user-defined panel display and hide #2825

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

Closed
wants to merge 4 commits into from

Conversation

chenxi-20
Copy link
Collaborator

@chenxi-20 chenxi-20 commented Jan 20, 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?

Issue Number: N/A

What is the new behavior?

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

  • New Features

    • Added manual control for dropdown menu visibility via new v-model:visible property
    • Introduced ability to programmatically show/hide dropdown menu
  • Documentation

    • Added demo and documentation for manual dropdown visibility control
  • Tests

    • Created new test case for verifying dropdown visibility interactions

@chenxi-20 chenxi-20 added the enhancement New feature or request (功能增强) label Jan 20, 2025
Copy link

coderabbitai bot commented Jan 20, 2025

Walkthrough

This pull request introduces a new v-model:visible property to the dropdown component, enabling manual control over its visibility. The changes span multiple files across the project, including component implementations, renderless logic, type definitions, and documentation. The modification allows developers to programmatically manage the dropdown's display state, taking precedence over the existing trigger property and providing more flexible interaction options.

Changes

File Change Summary
examples/sites/demos/apis/dropdown.js Added v-model:visible prop with boolean type and default false
examples/sites/demos/pc/app/dropdown/visible-composition-api.vue New Vue component demonstrating dropdown visibility control using Composition API
examples/sites/demos/pc/app/dropdown/visible.vue New Vue component showing dropdown visibility management
examples/sites/demos/pc/app/dropdown/visible.spec.ts Added Playwright test for manual dropdown visibility control
examples/sites/demos/pc/app/dropdown/webdoc/dropdown.js Added new demo entry for manual visibility control
packages/renderless/src/dropdown/index.ts Updated function signatures to include emit and added visibility state handling logic
packages/renderless/src/dropdown/vue.ts Modified renderless function to handle new visibility state management
packages/renderless/types/dropdown.type.ts Added visibleIsBoolean and trigger properties to IDropdownState interface
packages/vue/src/dropdown/src/index.ts Added visible and menuOptions properties to dropdownProps
packages/vue/src/dropdown/src/pc.vue Introduced visible prop and update:visible emit event

Sequence Diagram

sequenceDiagram
    participant User
    participant DropdownComponent
    participant ParentComponent

    User->>DropdownComponent: Click to toggle
    DropdownComponent->>ParentComponent: Emit update:visible event
    ParentComponent->>DropdownComponent: Update visible prop
    DropdownComponent->>DropdownComponent: Update visibility state
Loading

Possibly related PRs

Suggested reviewers

  • zzcr

Poem

🐰 A dropdown's dance, now controlled with grace,
Visibility bows to the developer's embrace
With v-model:visible, a magical key
Revealing and hiding, as nimble as can be!
Hop, skip, and show - the dropdown's new might! 🎉

Finishing Touches

  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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. (Beta)
  • @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.

@github-actions github-actions bot removed the enhancement New feature or request (功能增强) label Jan 20, 2025
Copy link

Walkthrough

This PR introduces a new feature to manually control the visibility of dropdown menus using the v-model:visible property. It adds new components and modifies existing ones to support this functionality, ensuring that manual control takes precedence over the trigger setting.

Changes

File Summary
examples/sites/demos/apis/dropdown.js Added v-model:visible property to control dropdown visibility manually.
examples/sites/demos/pc/app/dropdown/visible-composition-api.vue New component demonstrating the use of v-model:visible for dropdown visibility.
examples/sites/demos/pc/app/dropdown/visible.spec.ts New test file for manual visibility control of dropdowns.
examples/sites/demos/pc/app/dropdown/visible.vue New component for dropdown visibility control.
examples/sites/demos/pc/app/dropdown/webdoc/dropdown.js Documentation update for manual visibility control feature.
packages/renderless/src/dropdown/index.ts Logic update to support v-model:visible for dropdowns.
packages/renderless/src/dropdown/vue.ts Added computed property for boolean visibility check.
packages/renderless/types/dropdown.type.ts Type update to include visibleIsBoolean.
packages/vue/src/dropdown/src/index.ts Added visible property to dropdown props.
packages/vue/src/dropdown/src/pc.vue Updated dropdown component to handle visible property.

await page.goto('dropdown#visible')

const wrap = page.locator('#visible')
const dropDownMenu = page.locator('body > .tiny-dropdown-menu').locator('visible=true')

Choose a reason for hiding this comment

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

The selector body > .tiny-dropdown-menu with locator('visible=true') may not work as expected if the visible attribute is not directly reflected in the DOM. Consider verifying the selector logic.

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

@chenxi-20 chenxi-20 changed the title Feat/dropdown visible 20250107 feat(dropdown): [dropdown] Add visible attribute, support user-defined panel display and hide Jan 20, 2025
@github-actions github-actions bot added the enhancement New feature or request (功能增强) label Jan 20, 2025
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: 2

🧹 Nitpick comments (10)
examples/sites/demos/pc/app/dropdown/visible.spec.ts (3)

3-5: Consider adding more descriptive test title and error handling.

The test title in Chinese may not be accessible to all developers. Also, the error handling could be more specific about the expected errors.

-test('手动控制显隐', async ({ page }) => {
-  page.on('pageerror', (exception) => expect(exception).toBeNull())
+test('should control dropdown visibility manually', async ({ page }) => {
+  page.on('pageerror', (exception) => {
+    console.error('Page error:', exception);
+    expect(exception).toBeNull();
+  })

7-8: Consider adding timeout for element location.

The locator might fail if the page loads slowly. Consider adding a timeout or wait condition.

-  const wrap = page.locator('#visible')
-  const dropDownMenu = page.locator('body > .tiny-dropdown-menu').locator('visible=true')
+  const wrap = await page.locator('#visible').waitFor({ state: 'attached', timeout: 5000 })
+  const dropDownMenu = await page.locator('body > .tiny-dropdown-menu')
+    .locator('visible=true')
+    .waitFor({ state: 'attached', timeout: 5000 })

16-20: Add assertions for menu item interaction.

The test clicks outside and on a menu item but doesn't verify the expected behavior beyond visibility.

Consider adding assertions for:

  1. Selected item state
  2. Any emitted events
  3. Callback execution
examples/sites/demos/pc/app/dropdown/visible.vue (2)

31-48: Consider enhancing options data structure.

The options array could be more maintainable and type-safe.

+interface DropdownOption {
+  label: string;
+  disabled?: boolean;
+  value?: string | number;
+}

 data() {
   return {
     visible: true,
-    options: [
+    options: <DropdownOption[]>[
       {
-        label: '黄金糕'
+        label: '黄金糕',
+        value: 'golden_cake'
       },
       // ... other options
     ]
   }
 }

52-54: Add debounce to click handler.

The visibility toggle might need debouncing to prevent rapid state changes.

+import { debounce } from 'lodash-es'

 methods: {
-  handleClick() {
+  handleClick: debounce(function() {
     this.visible = !this.visible
-  }
+  }, 300)
 }
packages/renderless/types/dropdown.type.ts (1)

23-23: Enhance type definitions with documentation.

The new type definitions would benefit from JSDoc comments explaining their purpose and usage.

+/** Array of menu items that can be empty, undefined, or null */
 menuItems: NodeListOf<HTMLElement> | undefined | null | []

+/** Defines how the dropdown is triggered - either by click or hover */
 trigger: 'click' | 'hover'
+/** Indicates if the visible prop is explicitly set as a boolean */
 visibleIsBoolean: boolean

Also applies to: 31-32

examples/sites/demos/pc/app/dropdown/visible-composition-api.vue (4)

24-24: Consider initializing visible state as false.

The initial state is set to true, which means the dropdown will be visible when the component mounts. This might not be the expected default behavior for most use cases.

-const visible = ref(true)
+const visible = ref(false)

8-9: Use unique identifiers as keys instead of array indices.

Using array indices as keys can lead to unexpected behavior when the array is modified (items added/removed/reordered).

Consider adding unique IDs to your options:

 const options = [
   {
+    id: 1,
     label: '黄金糕'
   },
   // ... other options with unique IDs
 ]

Then use these IDs as keys:

-v-for="(item, index) in options"
-:key="index"
+v-for="item in options"
+:key="item.id"

48-50: Consider using min-height instead of fixed height.

A fixed height might cause content overflow or unnecessary empty space. Using min-height would allow the container to grow based on content while maintaining a minimum size.

 .box {
-  height: 150px;
+  min-height: 150px;
 }

3-4: Simplify click handler by leveraging v-model directly.

The current implementation uses a separate click handler to toggle visibility. Since you're using v-model, you can bind the click event directly to toggle the value.

-<div @click="handleClick">点击{{ visible ? '隐藏' : '显示' }}</div>
+<div @click="visible = !visible">点击{{ visible ? '隐藏' : '显示' }}</div>

-const handleClick = () => {
-  visible.value = !visible.value
-}

Also applies to: 42-44

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 7d1fbeb and 43fb544.

📒 Files selected for processing (10)
  • examples/sites/demos/apis/dropdown.js (1 hunks)
  • examples/sites/demos/pc/app/dropdown/visible-composition-api.vue (1 hunks)
  • examples/sites/demos/pc/app/dropdown/visible.spec.ts (1 hunks)
  • examples/sites/demos/pc/app/dropdown/visible.vue (1 hunks)
  • examples/sites/demos/pc/app/dropdown/webdoc/dropdown.js (1 hunks)
  • packages/renderless/src/dropdown/index.ts (7 hunks)
  • packages/renderless/src/dropdown/vue.ts (3 hunks)
  • packages/renderless/types/dropdown.type.ts (1 hunks)
  • packages/vue/src/dropdown/src/index.ts (1 hunks)
  • packages/vue/src/dropdown/src/pc.vue (4 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: PR Unit Test
  • GitHub Check: PR E2E Test (pnpm test:e2e3)
🔇 Additional comments (13)
packages/renderless/src/dropdown/vue.ts (3)

64-65: LGTM! Well-structured computed property addition.

The new visibleIsBoolean computed property correctly determines if the component is in controlled mode, enabling proper v-model support.


74-76: LGTM! Consistent method signature updates.

The method signatures are consistently updated to include the emit parameter, enabling proper event handling for the new v-model functionality.

Also applies to: 79-79


92-96: LGTM! Robust visibility state management.

The watch logic elegantly handles both controlled and uncontrolled modes:

  • Watches props.visible when in controlled mode
  • Falls back to watching internal state.visible otherwise
packages/vue/src/dropdown/src/pc.vue (4)

36-40: LGTM! Well-defined prop type.

The visible prop is correctly defined with:

  • Type: [Boolean, undefined]
  • Default: undefined
  • Clear comment indicating it's a new addition

109-110: LGTM! Proper v-model event.

The update:visible event is correctly added to support v-model functionality.


123-125: LGTM! Clean visibility class logic.

The visibility class is correctly determined based on the component's mode:

  • Uses visible prop in controlled mode
  • Falls back to state.visible in uncontrolled mode

221-221: LGTM! Conditional clickoutside directive.

The v-clickoutside directive is correctly conditional based on visibleIsBoolean, preventing conflicts in controlled mode.

packages/renderless/src/dropdown/index.ts (4)

48-59: LGTM! Robust show method implementation.

The show method correctly handles both modes:

  • Emits update:visible event in controlled mode
  • Updates internal state with timeout in uncontrolled mode

75-86: LGTM! Consistent hide method implementation.

The hide method mirrors the show method's behavior:

  • Emits update:visible event in controlled mode
  • Updates internal state with timeout in uncontrolled mode

96-101: LGTM! Clean click handler implementation.

The click handler properly handles both modes:

  • Emits the correct state
  • Updates visibility only in uncontrolled mode

286-290: LGTM! Proper mounted hook logic.

The mounted hook correctly:

  • Registers click-outside handler only in uncontrolled mode
  • Broadcasts initial visibility in controlled mode when visible
examples/sites/demos/pc/app/dropdown/webdoc/dropdown.js (1)

114-126: LGTM! Well-documented demo entry.

The new demo entry is complete with:

  • Clear descriptions in both languages
  • Proper explanation of the visible attribute's behavior
  • Note about priority over trigger property
examples/sites/demos/apis/dropdown.js (1)

221-231: LGTM! Well-documented property addition.

The new v-model:visible property is well-documented with clear descriptions in both languages, proper type definition, and mode specification.

Comment on lines +3 to +16
<tiny-dropdown v-model:visible="visible">
<div @click="handleClick">点击{{ visible ? '隐藏' : '显示' }}</div>
<template #dropdown>
<tiny-dropdown-menu>
<tiny-dropdown-item
v-for="(item, index) in options"
:key="index"
:label="item.label"
:disabled="item.disabled"
:item-data="item"
></tiny-dropdown-item>
</tiny-dropdown-menu>
</template>
</tiny-dropdown>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance accessibility and user experience.

The dropdown implementation could benefit from improved accessibility features.

 <tiny-dropdown v-model:visible="visible">
-  <div @click="handleClick">点击{{ visible ? '隐藏' : '显示' }}</div>
+  <div 
+    @click="handleClick"
+    role="button"
+    tabindex="0"
+    :aria-expanded="visible"
+    :aria-controls="dropdownId"
+    @keydown.enter="handleClick"
+    @keydown.space.prevent="handleClick"
+  >
+    点击{{ visible ? '隐藏' : '显示' }}
+  </div>
   <template #dropdown>
-    <tiny-dropdown-menu>
+    <tiny-dropdown-menu :id="dropdownId">

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +8 to +11
visible: {
type: [Boolean, undefined],
default: undefined
},
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve type definition for visible prop.

The type definition for visible could be more precise.

-  visible: {
-    type: [Boolean, undefined],
-    default: undefined
-  },
+  visible: {
+    type: Boolean,
+    default: undefined,
+    required: false
+  },
📝 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
visible: {
type: [Boolean, undefined],
default: undefined
},
visible: {
type: Boolean,
default: undefined,
required: false
},

@@ -218,6 +218,17 @@ export default {
pcDemo: 'split-button',
mfDemo: ''
},
{
name: 'v-model:visible',
Copy link
Member

Choose a reason for hiding this comment

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

新增的属性需要标明添加的版本


const params = { visible: state.visible }
let triggerElm = null
// TINY-TODO tiny-dropdown类名整改,统一tiny-组件名为前缀
const triggerClass = 'tiny-dropdown__trigger tiny-dropdown-trigger'
const visibleClass = state.visible ? 'tiny-dropdown--visible tiny-dropdown-visible' : ''
// tiny新增visible判断
const addVisibleClass = state.visibleIsBoolean ? visible : state.visible
Copy link
Member

Choose a reason for hiding this comment

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

模板改动需要升级dropdown组件的补丁版本号

@chenxi-20 chenxi-20 closed this Jan 20, 2025
@kagol kagol deleted the feat/dropdown-visible-20250107 branch April 14, 2025 12:25
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.

2 participants