feat: tune session sidebar tooltip timing
Adds a shared sidebar tooltip provider with delayed open and instant close behavior Removes per-button tooltip delays so sidebar actions feel more consistent Aligns session sidebar hover interactions with the opencode-style tooltip experience
This commit is contained in:
@@ -592,13 +592,12 @@ const SessionSidebarComponent: React.FC<SessionSidebarProps> = ({
|
|||||||
}, [mobileVariant, openNewSessionDraft, setSessionSwitcherOpen]);
|
}, [mobileVariant, openNewSessionDraft, setSessionSwitcherOpen]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// One shared tooltip provider for the whole sidebar: session tooltips open
|
// One shared tooltip provider for the whole sidebar, matching the opencode
|
||||||
// instantly, and moving between rows hands the tooltip over (grouping)
|
// sidebar feel: 400ms before the first tooltip opens, instant close on
|
||||||
// instead of replaying the exit/enter animation for each row.
|
// leave, and grouping — moving between rows within 600ms hands the tooltip
|
||||||
// closeDelay bridges the small gap between rows: the tooltip survives the
|
// over to the next row without replaying the open delay or exit/enter
|
||||||
// pointer crossing row margins, and the grouping timeout hands it over to
|
// animation.
|
||||||
// the next row without an exit/enter cycle.
|
<TooltipProvider delay={400} closeDelay={0} timeout={300}>
|
||||||
<TooltipProvider delay={0} closeDelay={150} timeout={600}>
|
|
||||||
<div
|
<div
|
||||||
ref={sessionSearchContainerRef}
|
ref={sessionSearchContainerRef}
|
||||||
className={cn(
|
className={cn(
|
||||||
|
|||||||
@@ -1200,7 +1200,7 @@ function SessionGroupSectionBase(props: SessionGroupSectionProps): React.ReactNo
|
|||||||
</div>
|
</div>
|
||||||
{group.isArchivedBucket && allGroupSessions.length > 0 ? (
|
{group.isArchivedBucket && allGroupSessions.length > 0 ? (
|
||||||
<div className={cn('absolute right-0.5 top-1/2 -translate-y-1/2 z-10 transition-opacity', alwaysShowActions ? 'opacity-100' : 'opacity-0 group-hover/gh:opacity-100 group-focus-within/gh:opacity-100')}>
|
<div className={cn('absolute right-0.5 top-1/2 -translate-y-1/2 z-10 transition-opacity', alwaysShowActions ? 'opacity-100' : 'opacity-0 group-hover/gh:opacity-100 group-focus-within/gh:opacity-100')}>
|
||||||
<Tooltip delayDuration={500}>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -1223,7 +1223,7 @@ function SessionGroupSectionBase(props: SessionGroupSectionProps): React.ReactNo
|
|||||||
) : null}
|
) : null}
|
||||||
{group.directory && !group.isMain && group.worktree ? (
|
{group.directory && !group.isMain && group.worktree ? (
|
||||||
<div className={cn('absolute right-7 top-1/2 -translate-y-1/2 z-10 transition-opacity', alwaysShowActions ? 'opacity-100' : 'opacity-0 group-hover/gh:opacity-100 group-focus-within/gh:opacity-100')}>
|
<div className={cn('absolute right-7 top-1/2 -translate-y-1/2 z-10 transition-opacity', alwaysShowActions ? 'opacity-100' : 'opacity-0 group-hover/gh:opacity-100 group-focus-within/gh:opacity-100')}>
|
||||||
<Tooltip delayDuration={500}>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -1247,7 +1247,7 @@ function SessionGroupSectionBase(props: SessionGroupSectionProps): React.ReactNo
|
|||||||
) : null}
|
) : null}
|
||||||
{group.directory ? (
|
{group.directory ? (
|
||||||
<div className={cn('absolute right-0.5 top-1/2 -translate-y-1/2 z-10 transition-opacity', alwaysShowActions ? 'opacity-100' : 'opacity-0 group-hover/gh:opacity-100 group-focus-within/gh:opacity-100')}>
|
<div className={cn('absolute right-0.5 top-1/2 -translate-y-1/2 z-10 transition-opacity', alwaysShowActions ? 'opacity-100' : 'opacity-0 group-hover/gh:opacity-100 group-focus-within/gh:opacity-100')}>
|
||||||
<Tooltip delayDuration={500}>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
@@ -342,7 +342,7 @@ export const SortableProjectItem: React.FC<SortableProjectItemProps> = ({
|
|||||||
showCreateButtons ? 'right-7' : 'right-0.5',
|
showCreateButtons ? 'right-7' : 'right-0.5',
|
||||||
)}>
|
)}>
|
||||||
{showCreateButtons && isRepo && !hideDirectoryControls && onNewWorktreeSession ? (
|
{showCreateButtons && isRepo && !hideDirectoryControls && onNewWorktreeSession ? (
|
||||||
<Tooltip delayDuration={500}>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -398,7 +398,7 @@ export const SortableProjectItem: React.FC<SortableProjectItemProps> = ({
|
|||||||
|
|
||||||
{showCreateButtons && onNewSession ? (
|
{showCreateButtons && onNewSession ? (
|
||||||
<div className="absolute right-0.5 top-1/2 z-10 -translate-y-1/2">
|
<div className="absolute right-0.5 top-1/2 z-10 -translate-y-1/2">
|
||||||
<Tooltip delayDuration={500}>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ const QuickSessionAction = React.memo(function QuickSessionAction({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip delayDuration={500}>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ export function SidebarHeader(props: Props): React.ReactNode {
|
|||||||
icon inset inside the 24px buttons so the first glyph lines up
|
icon inset inside the 24px buttons so the first glyph lines up
|
||||||
with the New-session icon above (16px from the sidebar edge). */}
|
with the New-session icon above (16px from the sidebar edge). */}
|
||||||
<div className="ml-[3px] flex items-center gap-1.5">
|
<div className="ml-[3px] flex items-center gap-1.5">
|
||||||
<Tooltip delayDuration={500}>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -104,7 +104,7 @@ export function SidebarHeader(props: Props): React.ReactNode {
|
|||||||
<TooltipContent side="bottom" sideOffset={4}><p>{t('sessions.sidebar.header.actions.addProject')}</p></TooltipContent>
|
<TooltipContent side="bottom" sideOffset={4}><p>{t('sessions.sidebar.header.actions.addProject')}</p></TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<Tooltip delayDuration={500}>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -118,7 +118,7 @@ export function SidebarHeader(props: Props): React.ReactNode {
|
|||||||
<TooltipContent side="bottom" sideOffset={4}><p>{t('sessions.sidebar.header.actions.scheduledTasks')}</p></TooltipContent>
|
<TooltipContent side="bottom" sideOffset={4}><p>{t('sessions.sidebar.header.actions.scheduledTasks')}</p></TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<Tooltip delayDuration={500}>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -133,7 +133,7 @@ export function SidebarHeader(props: Props): React.ReactNode {
|
|||||||
<TooltipContent side="bottom" sideOffset={4}><p>{t('sessions.sidebar.header.actions.newMultiRun')}</p></TooltipContent>
|
<TooltipContent side="bottom" sideOffset={4}><p>{t('sessions.sidebar.header.actions.newMultiRun')}</p></TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<Tooltip delayDuration={500}>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -149,7 +149,7 @@ export function SidebarHeader(props: Props): React.ReactNode {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-1.5">
|
<div className="flex items-center gap-1.5">
|
||||||
<Tooltip delayDuration={500}>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -164,7 +164,7 @@ export function SidebarHeader(props: Props): React.ReactNode {
|
|||||||
<TooltipContent side="bottom" sideOffset={4}><p>{t('sessions.sidebar.header.actions.searchSessions')}</p></TooltipContent>
|
<TooltipContent side="bottom" sideOffset={4}><p>{t('sessions.sidebar.header.actions.searchSessions')}</p></TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<Tooltip delayDuration={500}>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -186,7 +186,7 @@ export function SidebarHeader(props: Props): React.ReactNode {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<Tooltip delayDuration={500}>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<button
|
<button
|
||||||
|
|||||||
Reference in New Issue
Block a user