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.
WalkthroughThis update introduces new features and refactors for dropdown menus, suggestion popovers, and sender components. It adds manual and controlled visibility options, new event handlers (notably Changes
Sequence Diagram(s)Controlled Dropdown Menu FlowsequenceDiagram
participant User
participant Button
participant DropdownMenu
User->>Button: Clicks trigger button
Button->>DropdownMenu: Toggle `show` prop (manual control)
DropdownMenu-->>Button: Emits `click-outside` if user clicks outside
Button->>DropdownMenu: Handles event, logs, closes menu if needed
Suggestion Pills "Show More" LogicsequenceDiagram
participant User
participant SuggestionPills
participant PillsContainer
participant FloatingItems
User->>SuggestionPills: Adds or interacts with pills
SuggestionPills->>PillsContainer: Calculate visible items width
alt Not all fit
SuggestionPills->>FloatingItems: Move overflow pills to floating container
SuggestionPills->>User: Show "show more" button
else All fit
SuggestionPills->>User: No "show more" button
end
Sender Stop Button CustomizationsequenceDiagram
participant User
participant Sender
participant ActionButtons
User->>Sender: Triggers loading state
Sender->>ActionButtons: Passes `stopText` prop
ActionButtons->>User: Renders stop button (icon or text+icon)
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/dropdown-menu/basic.vueOops! Something went wrong! :( ESLint: 9.29.0 Error: The 'jiti' library is required for loading TypeScript configuration files. Make sure to install it. packages/components/src/sender/components/ActionButtons.vueOops! Something went wrong! :( ESLint: 9.29.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.29.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: 2
🔭 Outside diff range comments (1)
packages/components/src/suggestion-pills/index.vue (1)
103-110: Remove incorrect click handling logic.The current logic prevents item clicks for items at or after
hiddenIndex, which doesn't align with the new width-based approach and creates inconsistent behavior with floating items. All item clicks should emit the event:const handleClick = (ev: MouseEvent, item: SuggestionPillItem, index: number) => { - if (hasShowMoreBtn.value && index >= hiddenIndex.value) { - ev.stopPropagation() - toggleIsShowingMore() - return - } emit('item-click', item) }
🧹 Nitpick comments (1)
packages/components/src/sender/index.less (1)
79-79: Consider alternatives to!importantfor textarea min-height.While the
!importantflag ensures consistent textarea sizing, it can make future style customizations difficult. Consider if this can be achieved through more specific selectors or CSS cascade order.If
!importantis necessary due to conflicts with TinyUI components, consider documenting this in a comment:- min-height: var(--tr-sender-textarea-min-height) !important; // 最小高度与单行保持一致 + min-height: var(--tr-sender-textarea-min-height) !important; // Override TinyUI default - required for consistent sizing
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (26)
docs/demos/dropdown-menu/basic.vue(2 hunks)docs/demos/suggestion/pills-popper-config.vue(4 hunks)docs/demos/suggestion/popover-trigger.vue(2 hunks)docs/src/components/dropdown-menu.md(2 hunks)docs/src/components/sender.md(2 hunks)docs/src/components/suggestion-popover.md(2 hunks)docs/src/releases/update-log.md(1 hunks)packages/components/package.json(1 hunks)packages/components/src/action-group/ActionGroup.vue(1 hunks)packages/components/src/dropdown-menu/index.type.ts(2 hunks)packages/components/src/dropdown-menu/index.vue(3 hunks)packages/components/src/flow-layout-buttons/index.vue(1 hunks)packages/components/src/sender/components/ActionButtons.vue(2 hunks)packages/components/src/sender/index.less(2 hunks)packages/components/src/sender/index.type.ts(2 hunks)packages/components/src/sender/index.vue(3 hunks)packages/components/src/sender/vars.less(1 hunks)packages/components/src/suggestion-pills/components/PillButtonWrapper.vue(2 hunks)packages/components/src/suggestion-pills/index.type.ts(1 hunks)packages/components/src/suggestion-pills/index.vue(3 hunks)packages/components/src/suggestion-popover/index.type.ts(1 hunks)packages/components/src/suggestion-popover/index.vue(7 hunks)packages/components/tsconfig.json(1 hunks)packages/components/vite.config.ts(2 hunks)packages/kit/package.json(1 hunks)packages/svgs/package.json(1 hunks)
🧰 Additional context used
🧠 Learnings (3)
docs/demos/suggestion/popover-trigger.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.
packages/components/src/dropdown-menu/index.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.
packages/components/src/suggestion-popover/index.vue (1)
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 (62)
packages/components/src/action-group/ActionGroup.vue (1)
67-73: LGTM! Clean refactoring of outside click handling.The refactoring from manual containment checks to using the
ignoreoption makes the code more declarative and maintainable. This approach is cleaner and aligns with similar patterns used across other components.packages/components/src/dropdown-menu/index.type.ts (4)
8-15: Good API enhancement with manual control support.The addition of
showandtriggerprops provides better control over dropdown visibility, with clear documentation about when each prop is effective.
27-28: Well-designed event addition.The new
click-outsideevent with proper typing enhances the component's event handling capabilities.
30-33: Modern event props pattern.The new
DropdownMenuEventPropsinterface follows modern Vue composition patterns for event handlers.
36-44: Proper deprecation strategy.Good use of JSDoc
@deprecatedannotations to maintain backward compatibility while guiding users toward the new event handling approach.packages/svgs/package.json (1)
3-3: Version bump looks good.The coordinated version update to 0.2.10 aligns with the release objectives.
packages/components/package.json (1)
3-3: Consistent version update.The version bump to 0.2.10 is consistent with the coordinated release across all packages.
packages/kit/package.json (1)
3-3: Release version coordination complete.The version update to 0.2.10 completes the coordinated release across all packages in the monorepo.
packages/components/src/sender/vars.less (1)
234-234: LGTM!The CSS custom property follows the established naming convention and is properly scoped within the compact mode class. The value reference is consistent with other compact mode variable usage.
packages/components/tsconfig.json (1)
27-30: LGTM!The TypeScript path alias configuration follows standard conventions. The
"~/*": ["./src/*"]mapping is a common pattern that will enable cleaner import statements throughout the codebase.packages/components/src/sender/index.type.ts (2)
48-48: LGTM!The
stopTextproperty addition follows the existing interface pattern with appropriate optional typing and clear documentation.
65-65: LGTM!Consistent addition of the
stopTextproperty to the ActionButtonsProps interface, maintaining the same typing and documentation as the SenderProps interface.packages/components/src/sender/index.vue (2)
35-35: LGTM!The default value for
stopTextis appropriately set to an empty string, which aligns with the optional behavior described in the type definition.
542-542: LGTM!The
stopTextprop is consistently passed to theaction-buttonscomponent in both single and multiple input modes, ensuring complete feature coverage across all UI states.Also applies to: 593-593
packages/components/src/flow-layout-buttons/index.vue (1)
116-122: LGTM!The refactoring to use the
ignoreoption simplifies the outside click detection logic and makes the code more maintainable. Including bothdropDownRefandmoreButtonRefin the ignore array ensures proper behavior when clicking on the dropdown or its trigger.packages/components/src/suggestion-pills/components/PillButtonWrapper.vue (3)
21-23: LGTM: Consistent event handling enhancements.The addition of
@openand@click-outsideevent handlers forSuggestionPopoveraligns well with the enhanced manual control features mentioned in the PR objectives.
35-35: Good addition of click-outside event for DropdownMenu.This maintains consistency with the SuggestionPopover component and provides the same manual control capabilities.
25-25: ```shell
#!/bin/bashDescription: Search for pointerup and click usages in all Vue components without relying on rg’s built-in types
echo "Searching for '@PointerUp' in .vue files:"
rg -n "@PointerUp" --glob '*.vue' -C3echo -e "\nSearching for '@click' in Pill/PillButton components:"
rg -n "@click" --glob '*.vue' -C3 | grep -E 'Pill|Button'</details> <details> <summary>docs/src/components/suggestion-popover.md (2)</summary> `43-55`: **LGTM: Improved table formatting for better readability.** The Props table formatting has been made more consistent and compact while maintaining all the necessary information. --- `77-77`: **Good documentation of the new click-outside event.** The event documentation is clear and properly specifies the `MouseEvent` parameter type, making it easy for developers to implement handlers. </details> <details> <summary>packages/components/src/sender/index.less (1)</summary> `707-714`: **Well-structured icon-only button styling.** The `.action-buttons__cancel--icon-only` class properly resets background, padding, and height to achieve the icon-only appearance. The style properties are logically organized and maintainable. </details> <details> <summary>docs/src/components/sender.md (2)</summary> `32-36`: **Clear demonstration of the new stopText functionality.** The updated examples effectively show how to use the `stopText` prop with a practical Chinese text example "停止回答" (Stop responding). --- `252-252`: **Good API documentation for the stopText prop.** The prop documentation is clear and follows the established table format. The default value "仅显示图标" (Icon only) accurately describes the behavior when no text is provided. </details> <details> <summary>packages/components/vite.config.ts (2)</summary> `1-1`: **Import statement organization looks good.** The reordering of imports follows a logical pattern (external libraries first, then Node.js modules, then relative imports) which improves code readability. Also applies to: 5-8 --- `53-56`: **Useful alias configuration for simplified imports.** The `'~': './src'` alias mapping will enable cleaner import statements throughout the codebase. Using `fileURLToPath(new URL('./src', import.meta.url))` is the correct modern approach for ES modules path resolution. Ensure the corresponding TypeScript configuration includes the same alias for proper type checking: ```typescript // In tsconfig.json { "compilerOptions": { "paths": { "~/*": ["./src/*"] } } }docs/demos/suggestion/popover-trigger.vue (3)
3-12: LGTM: Event handlers properly demonstrate new functionality.The addition of event handlers for
open,close,item-click, andclick-outsideevents effectively demonstrates the enhanced SuggestionPopover capabilities. The console logging is appropriate for demo purposes.
13-22: LGTM: Manual trigger demo shows controlled visibility.The manual trigger example properly demonstrates the new controlled visibility feature with the
showprop and manual trigger mode, along with the newclick-outsideevent handling.
33-33: LGTM: Console logging added to handleClose.The console log addition is consistent with the other event logging in the demo.
packages/components/src/sender/components/ActionButtons.vue (2)
54-57: LGTM: Well-designed optional prop with clear documentation.The
stopTextprop is properly typed as optional and includes clear JSDoc documentation. The default value ofundefinedcorrectly indicates when only the icon should be shown.
194-196: LGTM: Conditional rendering and styling implementation is correct.The implementation properly:
- Applies
action-buttons__cancel--icon-onlyclass when no text is provided- Updates alt text to "停止" (more accurate than "加载中")
- Conditionally renders the text span based on
stopTextpresenceThis maintains backward compatibility while adding the new customization option.
docs/demos/dropdown-menu/basic.vue (2)
5-14: LGTM: Manual trigger demo properly demonstrates new functionality.The second dropdown menu example effectively shows the manual trigger mode with:
- Controlled visibility via the
showprop- Manual trigger mode with
trigger="manual"- Click-outside event handling
- Manual toggle functionality
This is a clear demonstration of the new controlled visibility feature.
29-33: LGTM: Reactive state and event handler implementation is correct.The
showreactive variable andhandleClickOutsidehandler properly support the manual trigger demo. The console logging is appropriate for demonstration purposes.docs/src/releases/update-log.md (1)
4-22: LGTM: Changelog entries accurately document the changes.The version entries properly document:
- Version 0.2.10: Sender input box improvements including loading state input and
stopTextprop- Version 0.2.9: SuggestionPills iOS Safari fix
- Version 0.2.8: Sender scrollbar issue fix
- Version 0.2.7: Suggestion Popover shadow DOM scroll fix
These descriptions align with the code changes observed in the PR.
docs/src/components/dropdown-menu.md (2)
21-27: LGTM: API documentation accurately reflects new features.The props table properly documents:
- Addition of "默认值" column for clarity
- New
showprop for controlled visibility- New
triggerprop with default value'click'- Proper formatting and descriptions
The documentation clearly explains the new manual trigger functionality.
41-44: LGTM: Events table properly documents new click-outside event.The events table correctly documents the new
click-outsideevent with proper parameter typing (MouseEvent) and clear description. The formatting is consistent with the existing event documentation.packages/components/src/dropdown-menu/index.vue (4)
8-8: LGTM: Default trigger prop value.The default
trigger: 'click'maintains backward compatibility while enabling the new manual control mode.
16-32: Well-designed controlled/uncontrolled pattern.The computed property approach with custom getter/setter effectively centralizes the trigger mode logic. When
triggeris'manual', the component becomes controlled via the externalshowprop, otherwise it uses internal state. This design prevents accidental state mutations in manual mode.
51-58: Improved outside click handling with dedicated event.The refactored handler properly emits a
'click-outside'event before closing the menu, enabling parent components to handle outside clicks. Theignoreoption correctly excludes the trigger element from outside click detection.
82-82: Verify the event change from click to pointerup.The change from
@clickto@pointerupmay affect user interaction behavior, especially for accessibility (keyboard navigation) and touch devices.#!/bin/bash # Description: Check if other components in the codebase use similar event patterns # Expected: Find consistent usage of pointerup across dropdown and popover components echo "Searching for pointerup usage in components:" rg -A 2 -B 2 "@pointerup" packages/components/src/ echo -e "\nSearching for click event handlers in similar components:" rg -A 2 -B 2 "@click.*toggle|@click.*show" packages/components/src/packages/components/src/suggestion-popover/index.type.ts (3)
54-55: LGTM: Added click-outside event type.The new
'click-outside'event properly typed withMouseEventparameter maintains consistency with the dropdown menu component.
57-63: Well-structured event props interface.The new
SuggestionPopoverEventPropsinterface provides optional callback props for all events, enabling cleaner prop-based event handling compared to the emit-based approach.
65-86: Proper deprecation with clear migration guidance.The deprecation warnings correctly guide users to migrate from the old event handler properties to the new callback props. The
clickOutsideevent handler addition maintains backward compatibility.packages/components/src/suggestion-popover/index.vue (6)
2-9: LGTM: Updated imports for throttling fix.The addition of
watchThrottledimport supports the shadow DOM throttling workaround mentioned in the changes.
96-105: Good workaround for shadow DOM throttling issue.The manual throttling using
watchThrottledinstead ofuseScroll's built-in throttle option effectively addresses the shadow DOM compatibility issue. The throttle configuration (100ms, leading and trailing) maintains smooth scrolling feedback.
150-158: Clean utility function for event emission.The
emitClickTriggerEventsfunction properly centralizes the logic for emitting 'open'/'close' events based on the currentshowstate, but only whentriggeris 'click'. This prevents unwanted events in manual mode.
160-168: Improved outside click handling.The refactored handler emits the new
'click-outside'event, closes the popover, and calls the centralized event emission function. Theignoreoption correctly excludes the trigger element.
220-220: Consistent with dropdown menu component.The change from
@clickto@pointerupmaintains consistency with the dropdown menu component, but verify this doesn't break accessibility.
288-288: Good responsive design improvement.The
max-height: 100dvhconstraint prevents the popover from exceeding viewport height, improving usability on smaller screens.packages/components/src/suggestion-pills/index.type.ts (3)
2-8: LGTM: Updated imports for event props integration.The imports correctly include the new event props interfaces from both dropdown menu and suggestion popover components.
10-28: Well-structured type separation.The split of
SuggestionPillActionintoSuggestionPillPopoverActionandSuggestionPillMenuActionprovides better type safety by combining specific props with their corresponding event props. The deprecation warnings guide users to the new event handler approach.
29-29: Clean union type update.The updated union type maintains the same interface while leveraging the new separated types underneath.
docs/demos/suggestion/pills-popper-config.vue (6)
15-16: LGTM: Added dynamic functionality.The new button and handler demonstrate dynamic pill management capabilities.
46-49: Excellent demonstration of new event props pattern.The action configurations properly showcase the new callback props (
onItemClick,onClickOutside) with manual trigger control, demonstrating the improved event handling approach.Also applies to: 67-76
93-99: Clean utility for managing multiple poppers.The
closeAllPopperfunction provides a centralized way to manage visibility state across all pill actions, demonstrating proper state management with the new controlled mode.
117-127: Good demonstration of exclusive menu visibility.The logic ensures only one menu is open at a time while properly toggling the clicked item's visibility, showcasing effective usage of the manual trigger mode.
131-139: Proper outside click handling with element exclusions.The updated handler correctly excludes both the switch and add button from triggering outside click behavior, while properly closing all poppers. This demonstrates good UX practices.
141-163: Well-implemented dynamic item addition.The function properly creates new pill items with the correct action configuration, maintaining consistency with existing items and demonstrating the flexibility of the new system.
packages/components/src/suggestion-pills/index.vue (5)
16-16: LGTM! Good use of defineModel.The
showAllmodel property is correctly implemented using Vue 3.4+ defineModel syntax with an appropriate default value.
20-24: Good architectural improvement with width-based logic.The addition of
floatingItemsRefand the width-based comparison logic viacontainerFullWidthandhasShowMoreBtnprovides more accurate visibility control than the previous index-based approach.
40-44: Well-implemented helper function.The
getAllItemElementsfunction correctly gathers elements from both containers with proper null safety.
125-126: Template changes correctly implement the new architecture.The separation of static and floating items in the template is well-implemented, with proper use of the new computed properties and refs.
Also applies to: 132-134
74-89: Fix width calculation and remove redundant watching.Two issues to address:
- The reduce function adds a gap after every item, including the last one
- Watching both
props.itemsandprops.items?.lengthis redundantwatch( - () => [props.items, props.items?.length], + () => props.items, () => { nextTick(() => { if (!containerRef.value) { return } // 计算容器最大宽度 const children = getAllItemElements() const gap = parseFloat(getComputedStyle(containerRef.value).rowGap) || 0 - containerFullWidth.value = children.map((el) => el.offsetWidth).reduce((acc, cur) => acc + cur + gap) + const widths = children.map((el) => el.offsetWidth) + containerFullWidth.value = widths.reduce((acc, cur, idx) => + acc + cur + (idx > 0 ? gap : 0), 0) }) }, { immediate: true }, )Likely an incorrect or invalid review comment.
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Style
Chores