mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-07-04 05:00:00 +08:00
fix(app-shell-tab-bar): preserve drag handler and transform style under ContextMenuTrigger asChild
`ContextMenuTrigger asChild` clones the tab button element with merged
props (onContextMenu, ref, etc). Both PinnedTabButton and NormalTabButton
were spreading `{...rest}` AFTER the drag handler and transform style,
so any prop injected by the trigger would overwrite drag.onPointerDown
and the translateX/transition/zIndex/opacity that useTabDrag relies on,
breaking tab drag/reorder.
Move `{...rest}` to the start of the JSX props so the drag handler,
transform style, and drag-related classes always win on a key collision.
For PinnedTabButton (which doesn't omit `style`/`className` from its
incoming props) also merge any incoming style/className through so
trigger-side styling is preserved alongside the drag values.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: suyao <sy20010504@gmail.com>
This commit is contained in:
@@ -114,7 +114,10 @@ type PinnedTabButtonProps = {
|
||||
const PinnedTabButton = ({ tab, isActive, onSelect, drag, tabRef, tone, ref, ...rest }: PinnedTabButtonProps) => {
|
||||
return (
|
||||
<Tooltip placement="bottom" content={tab.title} delay={600}>
|
||||
{/* Spread `rest` (which carries injected ContextMenuTrigger props) first so the */}
|
||||
{/* drag handler / transform style / drag classes always win on a key collision. */}
|
||||
<button
|
||||
{...rest}
|
||||
ref={(el) => {
|
||||
tabRef(el)
|
||||
if (typeof ref === 'function') ref(el)
|
||||
@@ -126,6 +129,7 @@ const PinnedTabButton = ({ tab, isActive, onSelect, drag, tabRef, tone, ref, ...
|
||||
onClick={onSelect}
|
||||
title={tab.title}
|
||||
style={{
|
||||
...rest.style,
|
||||
transform: `translateX(${drag.translateX}px)`,
|
||||
transition: drag.isDragging || drag.noTransition ? 'none' : 'transform 200ms ease',
|
||||
zIndex: drag.isDragging ? 50 : 'auto',
|
||||
@@ -134,9 +138,9 @@ const PinnedTabButton = ({ tab, isActive, onSelect, drag, tabRef, tone, ref, ...
|
||||
className={cn(
|
||||
'flex h-7 w-7 items-center justify-center rounded-full transition-colors duration-150',
|
||||
drag.isDragging ? 'cursor-grabbing' : 'cursor-default',
|
||||
isActive ? tone.activeClass : tone.hoverClass
|
||||
)}
|
||||
{...rest}>
|
||||
isActive ? tone.activeClass : tone.hoverClass,
|
||||
rest.className
|
||||
)}>
|
||||
<TabIcon tab={tab} size={14} />
|
||||
</button>
|
||||
</Tooltip>
|
||||
@@ -198,7 +202,10 @@ const NormalTabButton = ({
|
||||
const showIconOverlayClose = isCloseable && showClose && isNarrow
|
||||
|
||||
return (
|
||||
// Spread `rest` (which carries injected ContextMenuTrigger props) first so the
|
||||
// drag handler / transform style / drag classes always win on a key collision.
|
||||
<button
|
||||
{...rest}
|
||||
ref={setRefs}
|
||||
data-tab-id={tab.id}
|
||||
type="button"
|
||||
@@ -215,8 +222,7 @@ const NormalTabButton = ({
|
||||
showRightClose ? 'pr-1 pl-2' : 'px-2',
|
||||
drag.isDragging ? 'cursor-grabbing' : 'cursor-default',
|
||||
isActive ? tone.activeClass : tone.hoverClass
|
||||
)}
|
||||
{...rest}>
|
||||
)}>
|
||||
{/* Icon — on narrow tabs, X overlay replaces icon on hover (Chrome-style) */}
|
||||
<div className="relative flex h-[13px] w-[13px] shrink-0 items-center justify-center">
|
||||
<TabIcon tab={tab} size={13} className={cn(showIconOverlayClose && 'group-hover:hidden')} />
|
||||
|
||||
Reference in New Issue
Block a user