Conversation
* refactor: update event handling in dropdown and suggestion components - Changed event listeners from `@click` to `@pointerup` in DropdownMenu and PillButtonWrapper components for improved responsiveness. - Added `max-height` style to suggestion popover for better layout control. * feat: add manual trigger and click-outside handling to dropdown and suggestion components - Introduced a `manual` trigger option for DropdownMenu and SuggestionPopover to allow external control of visibility. - Implemented `@click-outside` event to close the dropdown and popover when clicking outside. - Updated documentation to include new properties and event details for both components.
* feat: enhance DropdownMenu with hover trigger support - Added support for 'hover' trigger in the DropdownMenu component, allowing menus to display on hover events. - Updated documentation to reflect the new trigger options and their descriptions. - Refactored event handling to manage hover states and click events more effectively. - Improved styling variables for better customization of dropdown appearance. * feat: add TODO for safePolygon implementation in DropdownMenu hover trigger
…elease-0.2-into-dev
WalkthroughThis update introduces a new Changes
Sequence Diagram(s)sequenceDiagram
participant App
participant DropdownMenu
participant TrBasePopper
participant TeleportTarget
App->>DropdownMenu: Render with trigger="hover" or "click"
DropdownMenu->>TrBasePopper: Pass trigger slot, content slot, trigger events
TrBasePopper->>TeleportTarget: Compute target for popper placement
TrBasePopper-->>DropdownMenu: Emits events (e.g., click-outside)
TrBasePopper-->>App: Renders trigger and dropdown at correct position
sequenceDiagram
participant App
participant SuggestionPills
App->>SuggestionPills: Render with overflowMode and autoScrollOnHover props
SuggestionPills->>App: Render pills, listen for mouseenter on pill
App-->>SuggestionPills: Mouse enters pill
SuggestionPills->>SuggestionPills: If scroll mode & autoScrollOnHover, scroll pill into view
Possibly related PRs
Suggested reviewers
Poem
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
docs/demos/suggestion/pills-popper.vueOops! Something went wrong! :( ESLint: 9.30.0 Error: The 'jiti' library is required for loading TypeScript configuration files. Make sure to install it. docs/demos/suggestion/pills-popper-config.vueOops! Something went wrong! :( ESLint: 9.30.0 Error: The 'jiti' library is required for loading TypeScript configuration files. Make sure to install it. docs/demos/dropdown-menu/basic.vueOops! Something went wrong! :( ESLint: 9.30.0 Error: The 'jiti' library is required for loading TypeScript configuration files. Make sure to install it.
✨ Finishing Touches
🧪 Generate 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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. 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 (
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (4)
packages/components/src/shared/composables/useTeleportTarget.ts (1)
12-12: Fix typo in variable name.There's a typo in the variable name
referentceEl. It should bereferenceEl.- const referentceEl = unrefElement(reference) + const referenceEl = unrefElement(reference)Also update line 13:
- const rootNode = referentceEl?.getRootNode?.() + const rootNode = referenceEl?.getRootNode?.()packages/components/src/suggestion-pills/index.vue (1)
216-220: Consider adding scrollbar styling for consistency.The overflow-scroll class enables scrolling, but you might want to style the scrollbar for better visual consistency across browsers.
Consider adding custom scrollbar styling:
&.overflow-scroll { overflow-x: auto; scroll-behavior: smooth; + scrollbar-width: thin; + scrollbar-color: #dbdbdb transparent; + + &::-webkit-scrollbar { + height: 4px; + } + + &::-webkit-scrollbar-thumb { + background-color: #dbdbdb; + border-radius: 2px; + } }packages/components/src/dropdown-menu/index.vue (1)
45-45: Consider implementing the TODO for better hover UX.The comment mentions using
@floating-ui/dom'ssafePolygon()utility for improved hover behavior.Would you like me to create an issue to track implementing the
safePolygon()utility for smoother hover interactions?packages/components/src/base-popper/index.vue (1)
44-56: Consider improving Fragment handling robustness.The current Fragment handling only processes the first VNode and assumes it's the only Fragment. This may not handle complex slot content correctly.
Consider this more robust approach:
const triggerVNodes = computed(() => { const triggerSlot = slots.trigger?.() const vnodes = triggerSlot ? (Array.isArray(triggerSlot) ? triggerSlot : [triggerSlot]) : [] - // 如果第一个 vnode 是 Fragment 类型,并且 children 是数组,则返回 children(只渲染第一个 v-for Fragment) - if (vnodes[0].type === Fragment && Array.isArray(vnodes[0].children)) { - return vnodes[0].children - } + // Flatten all Fragments to their children + const flattened: VNode[] = [] + for (const vnode of vnodes) { + if (vnode.type === Fragment && Array.isArray(vnode.children)) { + flattened.push(...vnode.children as VNode[]) + } else { + flattened.push(vnode) + } + } + return flattened.length ? flattened : vnodes - return vnodes })
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (21)
docs/demos/dropdown-menu/basic.vue(2 hunks)docs/demos/suggestion/pills-popper-config.vue(2 hunks)docs/demos/suggestion/pills-popper.vue(1 hunks)docs/src/components/dropdown-menu.md(1 hunks)docs/src/components/suggestion-pills.md(2 hunks)docs/src/releases/update-log.md(1 hunks)packages/components/package.json(1 hunks)packages/components/src/base-popper/index.ts(1 hunks)packages/components/src/base-popper/index.vue(1 hunks)packages/components/src/dropdown-menu/index.type.ts(2 hunks)packages/components/src/dropdown-menu/index.vue(5 hunks)packages/components/src/shared/composables/index.ts(1 hunks)packages/components/src/shared/composables/useTeleportTarget.ts(1 hunks)packages/components/src/suggestion-pills/components/PillButtonWrapper.vue(3 hunks)packages/components/src/suggestion-pills/index.type.ts(1 hunks)packages/components/src/suggestion-pills/index.vue(4 hunks)packages/components/src/suggestion-popover/index.vue(1 hunks)packages/components/tsconfig.json(0 hunks)packages/components/vite.config.ts(0 hunks)packages/kit/package.json(1 hunks)packages/svgs/package.json(1 hunks)
💤 Files with no reviewable changes (2)
- packages/components/vite.config.ts
- packages/components/tsconfig.json
🧰 Additional context used
🧠 Learnings (13)
📓 Common learnings
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:131-133
Timestamp: 2025-05-27T03:35:11.008Z
Learning: In the SuggestionPopover component (packages/components/src/suggestion-popover/index.vue), the click handler can be bound unconditionally because the `show` computed property has a custom setter that prevents state mutations when `props.trigger === 'manual'`. This design centralizes trigger mode logic in the computed property rather than requiring conditional checks in event handlers.
packages/components/src/base-popper/index.ts (2)
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:131-133
Timestamp: 2025-05-27T03:35:11.008Z
Learning: In the SuggestionPopover component (packages/components/src/suggestion-popover/index.vue), the click handler can be bound unconditionally because the `show` computed property has a custom setter that prevents state mutations when `props.trigger === 'manual'`. This design centralizes trigger mode logic in the computed property rather than requiring conditional checks in event handlers.
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:0-0
Timestamp: 2025-05-27T03:45:56.392Z
Learning: In Vue components using VueUse's onClickOutside, calling stopPropagation() in the onClickOutside handler can prevent subsequent click event handlers on the same element from being triggered. This means that clicking a trigger element while a popover is open can successfully close the popover without immediately reopening it, even when the onClickOutside only listens to the popover element and not the trigger element.
packages/components/src/suggestion-popover/index.vue (2)
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:131-133
Timestamp: 2025-05-27T03:35:11.008Z
Learning: In the SuggestionPopover component (packages/components/src/suggestion-popover/index.vue), the click handler can be bound unconditionally because the `show` computed property has a custom setter that prevents state mutations when `props.trigger === 'manual'`. This design centralizes trigger mode logic in the computed property rather than requiring conditional checks in event handlers.
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:0-0
Timestamp: 2025-05-27T03:45:56.392Z
Learning: In Vue components using VueUse's onClickOutside, calling stopPropagation() in the onClickOutside handler can prevent subsequent click event handlers on the same element from being triggered. This means that clicking a trigger element while a popover is open can successfully close the popover without immediately reopening it, even when the onClickOutside only listens to the popover element and not the trigger element.
docs/demos/suggestion/pills-popper.vue (1)
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:131-133
Timestamp: 2025-05-27T03:35:11.008Z
Learning: In the SuggestionPopover component (packages/components/src/suggestion-popover/index.vue), the click handler can be bound unconditionally because the `show` computed property has a custom setter that prevents state mutations when `props.trigger === 'manual'`. This design centralizes trigger mode logic in the computed property rather than requiring conditional checks in event handlers.
docs/demos/dropdown-menu/basic.vue (2)
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:131-133
Timestamp: 2025-05-27T03:35:11.008Z
Learning: In the SuggestionPopover component (packages/components/src/suggestion-popover/index.vue), the click handler can be bound unconditionally because the `show` computed property has a custom setter that prevents state mutations when `props.trigger === 'manual'`. This design centralizes trigger mode logic in the computed property rather than requiring conditional checks in event handlers.
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:0-0
Timestamp: 2025-05-27T03:45:56.392Z
Learning: In Vue components using VueUse's onClickOutside, calling stopPropagation() in the onClickOutside handler can prevent subsequent click event handlers on the same element from being triggered. This means that clicking a trigger element while a popover is open can successfully close the popover without immediately reopening it, even when the onClickOutside only listens to the popover element and not the trigger element.
docs/src/releases/update-log.md (1)
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:131-133
Timestamp: 2025-05-27T03:35:11.008Z
Learning: In the SuggestionPopover component (packages/components/src/suggestion-popover/index.vue), the click handler can be bound unconditionally because the `show` computed property has a custom setter that prevents state mutations when `props.trigger === 'manual'`. This design centralizes trigger mode logic in the computed property rather than requiring conditional checks in event handlers.
packages/components/src/suggestion-pills/components/PillButtonWrapper.vue (2)
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:131-133
Timestamp: 2025-05-27T03:35:11.008Z
Learning: In the SuggestionPopover component (packages/components/src/suggestion-popover/index.vue), the click handler can be bound unconditionally because the `show` computed property has a custom setter that prevents state mutations when `props.trigger === 'manual'`. This design centralizes trigger mode logic in the computed property rather than requiring conditional checks in event handlers.
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:0-0
Timestamp: 2025-05-27T03:45:56.392Z
Learning: In Vue components using VueUse's onClickOutside, calling stopPropagation() in the onClickOutside handler can prevent subsequent click event handlers on the same element from being triggered. This means that clicking a trigger element while a popover is open can successfully close the popover without immediately reopening it, even when the onClickOutside only listens to the popover element and not the trigger element.
docs/src/components/dropdown-menu.md (1)
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:131-133
Timestamp: 2025-05-27T03:35:11.008Z
Learning: In the SuggestionPopover component (packages/components/src/suggestion-popover/index.vue), the click handler can be bound unconditionally because the `show` computed property has a custom setter that prevents state mutations when `props.trigger === 'manual'`. This design centralizes trigger mode logic in the computed property rather than requiring conditional checks in event handlers.
docs/demos/suggestion/pills-popper-config.vue (2)
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:131-133
Timestamp: 2025-05-27T03:35:11.008Z
Learning: In the SuggestionPopover component (packages/components/src/suggestion-popover/index.vue), the click handler can be bound unconditionally because the `show` computed property has a custom setter that prevents state mutations when `props.trigger === 'manual'`. This design centralizes trigger mode logic in the computed property rather than requiring conditional checks in event handlers.
Learnt from: SonyLeo
PR: opentiny/tiny-robot#119
File: packages/components/src/attachments/index.less:213-213
Timestamp: 2025-06-18T09:29:47.974Z
Learning: 在 packages/components/src/attachments/index.less 中,.tr-file-card__close 的背景色使用了硬编码的 rgb(194, 194, 194),但这个UI元素(关闭按钮)将会被直接替换为图标,所以不需要抽取为CSS变量。
packages/components/src/dropdown-menu/index.type.ts (2)
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:131-133
Timestamp: 2025-05-27T03:35:11.008Z
Learning: In the SuggestionPopover component (packages/components/src/suggestion-popover/index.vue), the click handler can be bound unconditionally because the `show` computed property has a custom setter that prevents state mutations when `props.trigger === 'manual'`. This design centralizes trigger mode logic in the computed property rather than requiring conditional checks in event handlers.
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:0-0
Timestamp: 2025-05-27T03:45:56.392Z
Learning: In Vue components using VueUse's onClickOutside, calling stopPropagation() in the onClickOutside handler can prevent subsequent click event handlers on the same element from being triggered. This means that clicking a trigger element while a popover is open can successfully close the popover without immediately reopening it, even when the onClickOutside only listens to the popover element and not the trigger element.
packages/components/src/dropdown-menu/index.vue (3)
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:131-133
Timestamp: 2025-05-27T03:35:11.008Z
Learning: In the SuggestionPopover component (packages/components/src/suggestion-popover/index.vue), the click handler can be bound unconditionally because the `show` computed property has a custom setter that prevents state mutations when `props.trigger === 'manual'`. This design centralizes trigger mode logic in the computed property rather than requiring conditional checks in event handlers.
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:0-0
Timestamp: 2025-05-27T03:45:56.392Z
Learning: In Vue components using VueUse's onClickOutside, calling stopPropagation() in the onClickOutside handler can prevent subsequent click event handlers on the same element from being triggered. This means that clicking a trigger element while a popover is open can successfully close the popover without immediately reopening it, even when the onClickOutside only listens to the popover element and not the trigger element.
Learnt from: SonyLeo
PR: opentiny/tiny-robot#119
File: packages/components/src/attachments/index.less:213-213
Timestamp: 2025-06-18T09:29:47.974Z
Learning: 在 packages/components/src/attachments/index.less 中,.tr-file-card__close 的背景色使用了硬编码的 rgb(194, 194, 194),但这个UI元素(关闭按钮)将会被直接替换为图标,所以不需要抽取为CSS变量。
packages/components/src/suggestion-pills/index.vue (2)
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:131-133
Timestamp: 2025-05-27T03:35:11.008Z
Learning: In the SuggestionPopover component (packages/components/src/suggestion-popover/index.vue), the click handler can be bound unconditionally because the `show` computed property has a custom setter that prevents state mutations when `props.trigger === 'manual'`. This design centralizes trigger mode logic in the computed property rather than requiring conditional checks in event handlers.
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:0-0
Timestamp: 2025-05-27T03:45:56.392Z
Learning: In Vue components using VueUse's onClickOutside, calling stopPropagation() in the onClickOutside handler can prevent subsequent click event handlers on the same element from being triggered. This means that clicking a trigger element while a popover is open can successfully close the popover without immediately reopening it, even when the onClickOutside only listens to the popover element and not the trigger element.
packages/components/src/base-popper/index.vue (2)
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:131-133
Timestamp: 2025-05-27T03:35:11.008Z
Learning: In the SuggestionPopover component (packages/components/src/suggestion-popover/index.vue), the click handler can be bound unconditionally because the `show` computed property has a custom setter that prevents state mutations when `props.trigger === 'manual'`. This design centralizes trigger mode logic in the computed property rather than requiring conditional checks in event handlers.
Learnt from: gene9831
PR: opentiny/tiny-robot#59
File: packages/components/src/suggestion-popover/index.vue:0-0
Timestamp: 2025-05-27T03:45:56.392Z
Learning: In Vue components using VueUse's onClickOutside, calling stopPropagation() in the onClickOutside handler can prevent subsequent click event handlers on the same element from being triggered. This means that clicking a trigger element while a popover is open can successfully close the popover without immediately reopening it, even when the onClickOutside only listens to the popover element and not the trigger element.
🔇 Additional comments (52)
packages/components/package.json (1)
3-3: Version bump looks good — don’t forget the release housekeeping
The increment to0.2.11is consistent with the other packages.
Please make sure the CHANGELOG is updated and a matching git tag is pushed so that automated publishing can pick it up.packages/svgs/package.json (1)
3-3: SVG package version aligned
No issues spotted. Confirm that this package is included in the release notes and publish workflow alongside the others.packages/kit/package.json (1)
3-3: Kit package version bump acknowledged
Everything is consistent. Ensure lock-files (if any) and root work-space references are updated before publishing.packages/components/src/suggestion-pills/index.type.ts (1)
52-63: LGTM! Well-documented type extensions.The new properties
overflowModeandautoScrollOnHoverare properly typed with clear JSDoc documentation and appropriate default values. The implementation aligns well with the enhanced overflow functionality described in the AI summary.packages/components/src/shared/composables/useTeleportTarget.ts (1)
4-29: Excellent composable implementation for teleport target resolution.The logic correctly handles both Shadow DOM and regular DOM scenarios with appropriate fallbacks. The special handling for the 'body' selector is a nice optimization. The comprehensive JSDoc documentation makes the behavior clear.
packages/components/src/suggestion-popover/index.vue (1)
220-220: Good change to standardize trigger interaction.Switching from
@pointerupto@clickprovides more predictable and standard user interaction behavior. This aligns with the custom setter logic in theshowcomputed property that centralizes trigger mode handling.packages/components/src/base-popper/index.ts (1)
1-5: Standard component export pattern.Clean and simple component wrapper following Vue.js conventions with appropriate naming (
TrBasePopper).packages/components/src/shared/composables/index.ts (1)
1-1: Appropriate barrel export for new composable.Standard re-export pattern to make the new
useTeleportTargetcomposable available through the shared composables index.docs/demos/suggestion/pills-popper.vue (1)
15-19: LGTM! Correctly updated to use the new trigger slot API.The change from direct child to the named
#triggerslot aligns with the DropdownMenu API breaking changes documented in the changelog.docs/demos/dropdown-menu/basic.vue (3)
3-5: LGTM! Correctly updated to use the new trigger slot API.The existing dropdown menu correctly migrated from direct child to the named
#triggerslot.
15-17: LGTM! Manual trigger example properly updated.The manual trigger dropdown correctly uses the new
#triggerslot while maintaining the manual trigger functionality.
19-31: LGTM! Excellent demonstration of the new hover trigger feature.The new section effectively demonstrates the
trigger="hover"functionality with proper usage of the#triggerslot. The horizontal layout with flexbox provides a clear visual example.docs/src/releases/update-log.md (1)
4-12: LGTM! Comprehensive changelog entry for breaking changes.The changelog entry clearly documents all the breaking changes and new features in version 0.2.10, including:
- New hover trigger support for DropdownMenu
- API changes (slot and prop modifications)
- New SuggestionPills overflow and auto-scroll features
This provides clear guidance for users upgrading to the new version.
packages/components/src/suggestion-pills/components/PillButtonWrapper.vue (4)
9-12: LGTM! Event emission signature correctly updated.The event signatures are properly updated to emit only
MouseEventfor bothclickandmouseenterevents, which supports the new auto-scroll functionality in the parent SuggestionPills component.
26-26: LGTM! Consistent event emission in popover context.The PillButton within SuggestionPopover correctly emits both click and mouseenter events with the updated signature.
38-40: LGTM! Correctly updated to use new DropdownMenu trigger slot API.The DropdownMenu usage properly migrated to the named
#triggerslot while maintaining consistent event emission.
42-48: LGTM! Fallback case properly handles updated events.The fallback PillButton rendering correctly emits both events with the updated signature and maintains style binding.
docs/src/components/dropdown-menu.md (3)
21-25: LGTM! Props documentation accurately reflects the new API.The props table correctly documents:
- The new
'hover'trigger mode alongside existing modes- Proper descriptions for each trigger type
- Removal of obsolete props (minWidth, topOffset)
31-33: LGTM! Slots documentation correctly updated for new API.The slots section properly documents the change from default slot to the named
triggerslot, with correct TypeScript type annotation.
39-42: LGTM! Events documentation clearly explains behavior constraints.The events section correctly documents that
click-outsideonly fires for 'click' or 'manual' trigger modes, which is important for developers to understand the event behavior.packages/components/src/dropdown-menu/index.type.ts (4)
1-1: LGTM!The VNode import is correctly added and used in the trigger slot definition.
17-17: Good addition of hover trigger mode.The new 'hover' trigger mode expands the component's flexibility and aligns with the implementation.
21-21: Well-structured slot API change.The change from a generic default slot to a specifically typed trigger slot improves type safety and API clarity.
26-29: Excellent documentation for the click-outside event.The comment clearly specifies when this event fires, which helps developers understand its behavior.
docs/demos/suggestion/pills-popper-config.vue (3)
5-6: Correct usage of new SuggestionPills props.The demo properly binds the new
overflowModeandautoScrollOnHoverprops.
41-45: Well-structured overflow mode options.The radio group options correctly match the allowed values for the
overflowModeprop.
18-28: Clean UI layout for demonstrating new features.The controls are well-organized with proper spacing and clear labels.
docs/src/components/suggestion-pills.md (2)
54-60: Comprehensive documentation for new props.The table clearly documents the new
overflowModeandautoScrollOnHoverprops with appropriate types and descriptions.
103-129: Improved type definitions with better structure.Breaking down
SuggestionPillActioninto specificSuggestionPillPopoverActionandSuggestionPillMenuActiontypes improves clarity and type safety.packages/components/src/suggestion-pills/index.vue (4)
10-10: Good default value for overflowMode.Setting 'expand' as the default maintains backward compatibility.
25-25: Correct logic for conditional show more button.The button is properly hidden when in scroll mode.
123-149: Well-implemented auto-scroll functionality.The scroll logic correctly handles both left and right hidden cases with smooth scrolling behavior.
151-155: Efficient hover handling.The mouseenter handler properly checks the conditions before triggering scroll behavior.
packages/components/src/dropdown-menu/index.vue (4)
2-4: Clean refactoring to use TrBasePopper.The migration to TrBasePopper significantly simplifies the positioning logic.
44-58: Good hover trigger implementation.The hover logic with appropriate delays prevents flickering when moving between trigger and dropdown.
101-108: Excellent use of CSS variables.The CSS variables approach improves theming flexibility and maintainability.
73-98: Clean template structure with TrBasePopper.The template is much simpler and more maintainable with the base popper handling positioning.
packages/components/src/base-popper/index.vue (15)
1-16: LGTM: Well-structured imports and necessary ESLint disable.The ESLint disable for
no-explicit-anyis justified given the generic event handler system. All imports are relevant and properly organized.
18-20: Good use of inheritAttrs: false.This correctly prevents automatic attribute inheritance, allowing manual control over where attributes are applied (to the popper element).
22-22: Flexible and appropriate type definition.The TriggerEvents type correctly handles the variety of possible DOM event handlers with proper capitalization pattern matching.
24-37: Well-designed props interface.The props provide good flexibility with:
- Multiple placement options covering common scenarios
- Flexible offset configuration (number or axis-specific object)
- Clear boolean flags for behavior control
- Proper default values
39-42: Proper slot type definitions.The slot definitions correctly handle both single VNode and VNode array scenarios for flexible content rendering.
58-83: Robust ref management system.The implementation properly handles:
- Both Vue component instances and native DOM elements
- Array length synchronization with proper cleanup
- Post-flush timing to ensure DOM updates are complete
- Clear warning messages for unsupported element types
85-99: Well-designed indexed event handling system.The implementation correctly:
- Validates event handler naming with proper regex pattern
- Injects trigger index into event calls for multi-trigger scenarios
- Creates isolated handler sets for each trigger element
101-111: Clean offset normalization logic.The computed property properly handles both number and object offset formats with sensible defaults.
113-114: Proper use of VueUse composables for element tracking.The border-box sizing option ensures accurate dimension calculations including borders and padding.
116-151: Sophisticated positioning logic with modern overflow prevention.The implementation features:
- Proper position calculations for all placement options
- Smart overflow prevention using CSS
clamp()and viewport units- Correct handling of bottom positioning with calc()
- Accurate center positioning calculations
The string-based placement matching using
includes()works correctly for the defined placement options.
153-162: Necessary bounds update on visibility change.The watcher correctly recalculates element bounds when the popper becomes visible, ensuring accurate positioning after DOM updates.
164-164: Appropriate use of teleport target composable.Using the trigger reference to determine the teleport target ensures proper positioning context, including Shadow DOM support.
166-170: Well-designed component exposure.Exposing both individual and array trigger references along with the popper ref provides flexibility for advanced use cases.
173-187: Well-structured template with proper Vue patterns.The template correctly implements:
- Indexed ref setting and event handler binding
- Proper key management for v-for rendering
- Conditional teleport rendering to avoid unnecessary DOM
- Attribute forwarding to the popper element
- Transition wrapper integration
190-194: Appropriate minimal styling.The fixed positioning is essential for popper functionality, and scoped styling prevents conflicts.
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Chores