-
Notifications
You must be signed in to change notification settings - Fork 312
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
Conversation
WalkthroughThis pull request introduces a new Changes
Sequence DiagramsequenceDiagram
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
Possibly related PRs
Suggested reviewers
Poem
Finishing Touches
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? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
WalkthroughThis PR introduces a new feature to manually control the visibility of dropdown menus using the Changes
|
await page.goto('dropdown#visible') | ||
|
||
const wrap = page.locator('#visible') | ||
const dropDownMenu = page.locator('body > .tiny-dropdown-menu').locator('visible=true') |
There was a problem hiding this comment.
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.
[e2e-test-warn] 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 |
There was a problem hiding this 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:
- Selected item state
- Any emitted events
- 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: booleanAlso 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
📒 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
otherwisepackages/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.
<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> |
There was a problem hiding this comment.
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.
visible: { | ||
type: [Boolean, undefined], | ||
default: undefined | ||
}, |
There was a problem hiding this comment.
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.
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', |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
模板改动需要升级dropdown组件的补丁版本号
PR
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
Issue Number: N/A
What is the new behavior?
Does this PR introduce a breaking change?
Other information
Summary by CodeRabbit
New Features
v-model:visible
propertyDocumentation
Tests