Merge remote-tracking branch 'origin/main'

This commit is contained in:
Mohamed Boudra
2026-08-04 13:13:22 +02:00
25 changed files with 201 additions and 619 deletions
@@ -111,6 +111,7 @@ import {
SidebarWorkspaceTrailingActionOverlay,
SidebarWorkspaceTrailingActionSlot,
} from "@/components/sidebar/sidebar-workspace-row-content";
import { useOpenKebabMenuVisibility } from "@/components/sidebar/use-open-kebab-menu-visibility";
import { selectWorkspaceScriptSummary } from "@/components/sidebar/workspace-meta-row";
import {
SidebarWorkspaceTrailingContent,
@@ -665,6 +666,7 @@ function WorkspaceRowRightGroup({
isTouchPlatform,
showShortcut,
});
const kebab = useOpenKebabMenuVisibility(showKebabInSlot);
return (
<>
@@ -676,9 +678,10 @@ function WorkspaceRowRightGroup({
<SidebarWorkspaceTrailingActionBase visible={showTrailing}>
<SidebarWorkspaceTrailingContent workspace={workspace} trailing={trailing} />
</SidebarWorkspaceTrailingActionBase>
<SidebarWorkspaceTrailingActionOverlay visible={showKebabInSlot} scrim={showScrim}>
<SidebarWorkspaceTrailingActionOverlay visible={kebab.showKebab} scrim={showScrim}>
{onArchive ? (
<SidebarWorkspaceMenu
{...kebab.menuProps}
workspaceKey={workspace.workspaceKey}
onCopyPath={onCopyPath}
onCopyBranchName={onCopyBranchName}
@@ -41,6 +41,7 @@ import {
SidebarWorkspaceTrailingActionSlot,
sidebarWorkspaceRowStyles,
} from "@/components/sidebar/sidebar-workspace-row-content";
import { useOpenKebabMenuVisibility } from "@/components/sidebar/use-open-kebab-menu-visibility";
import { getSidebarRowBackdrop } from "@/components/sidebar/sidebar-row-backdrop";
import { selectWorkspaceScriptSummary } from "@/components/sidebar/workspace-meta-row";
import {
@@ -813,14 +814,16 @@ function StatusWorkspaceActionSlot({
archivePendingLabel?: string;
archiveShortcutKeys?: ShortcutKey[][] | null;
}) {
const kebab = useOpenKebabMenuVisibility(showKebab);
return (
<SidebarWorkspaceTrailingActionSlot reserveWidth={reserveSlotWidth}>
<SidebarWorkspaceTrailingActionBase visible={showBase}>
<SidebarWorkspaceTrailingContent workspace={workspace} trailing={trailing} />
</SidebarWorkspaceTrailingActionBase>
<SidebarWorkspaceTrailingActionOverlay visible={showKebab} scrim={showScrim}>
{showKebab && onArchive ? (
<SidebarWorkspaceTrailingActionOverlay visible={kebab.showKebab} scrim={showScrim}>
{kebab.showKebab && onArchive ? (
<SidebarWorkspaceMenu
{...kebab.menuProps}
workspaceKey={workspace.workspaceKey}
onCopyPath={onCopyPath}
onCopyBranchName={onCopyBranchName}
@@ -71,9 +71,18 @@ export interface SidebarWorkspaceMenuProps {
isPinned?: boolean;
onTogglePin?: () => void;
openInFileManagerPath?: string | null;
/**
* Lifted so the row that reveals the kebab can keep it mounted while its menu is up. See
* `useOpenKebabMenuVisibility`.
*/
open?: boolean;
onOpenChange?: (open: boolean) => void;
}
interface SidebarWorkspaceMenuItemsProps extends Omit<SidebarWorkspaceMenuProps, "onArchive"> {
interface SidebarWorkspaceMenuItemsProps extends Omit<
SidebarWorkspaceMenuProps,
"onArchive" | "open" | "onOpenChange"
> {
onArchive?: () => void;
}
@@ -202,10 +211,12 @@ export function SidebarWorkspaceMenu({
isPinned,
onTogglePin,
openInFileManagerPath,
open,
onOpenChange,
}: SidebarWorkspaceMenuProps) {
const { t } = useTranslation();
return (
<DropdownMenu compactMode="sheet">
<DropdownMenu compactMode="sheet" open={open} onOpenChange={onOpenChange}>
<DropdownMenuTrigger
hitSlop={8}
style={triggerStyle}
@@ -32,6 +32,7 @@ import {
SidebarWorkspaceTrailingActionOverlay,
SidebarWorkspaceTrailingActionSlot,
} from "@/components/sidebar/sidebar-workspace-row-content";
import { useOpenKebabMenuVisibility } from "@/components/sidebar/use-open-kebab-menu-visibility";
import { getSidebarRowBackdrop } from "@/components/sidebar/sidebar-row-backdrop";
import { selectWorkspaceScriptSummary } from "@/components/sidebar/workspace-meta-row";
import {
@@ -420,6 +421,7 @@ function WorkspaceRowTrailingActions({
isTouchPlatform,
showShortcut,
});
const kebab = useOpenKebabMenuVisibility(showKebabInSlot);
return (
<>
@@ -431,9 +433,10 @@ function WorkspaceRowTrailingActions({
<SidebarWorkspaceTrailingActionBase visible={showTrailing}>
<SidebarWorkspaceTrailingContent workspace={workspace} trailing={trailing} />
</SidebarWorkspaceTrailingActionBase>
<SidebarWorkspaceTrailingActionOverlay visible={showKebabInSlot} scrim={showScrim}>
<SidebarWorkspaceTrailingActionOverlay visible={kebab.showKebab} scrim={showScrim}>
{onArchive ? (
<SidebarWorkspaceMenu
{...kebab.menuProps}
workspaceKey={workspace.workspaceKey}
onCopyPath={onCopyPath}
onCopyBranchName={onCopyBranchName}
@@ -0,0 +1,20 @@
import { useMemo, useState } from "react";
/**
* Keeps a row's kebab in its slot for as long as the menu it opened is up.
*
* The kebab is revealed by hover, and the surface it opens can take the pointer off the row —
* on a compact layout the sheet slides up over it. The row then reads as un-hovered, the
* trailing overlay unmounts its own trigger mid-gesture, and the open menu is left with no
* state that can close it: on a sheet that strands a full-screen backdrop over the app until
* reload. Lifting the menu's open state to the component that decides whether to render it is
* what stops the row from pulling the ground out from under it.
*/
export function useOpenKebabMenuVisibility(showKebab: boolean): {
showKebab: boolean;
menuProps: { open: boolean; onOpenChange: (open: boolean) => void };
} {
const [open, setOpen] = useState(false);
const menuProps = useMemo(() => ({ open, onOpenChange: setOpen }), [open]);
return { showKebab: showKebab || open, menuProps };
}