From 35c582913d1fba5beb5e3c6ee336c01998eb3ac9 Mon Sep 17 00:00:00 2001 From: nikuscs Date: Fri, 15 May 2026 14:38:43 +0100 Subject: [PATCH] fix (app): mobile sidebar web interactions (#900) * fix mobile sidebar web interactions * fix(app): restore button role on sidebar project row --------- Co-authored-by: Mohamed Boudra --- .../app/src/components/draggable-list.web.tsx | 8 ++++- packages/app/src/components/left-sidebar.tsx | 33 ++++++++++++++++++- .../src/components/sidebar-workspace-list.tsx | 26 +++++++++++---- .../src/components/workspace-hover-card.tsx | 9 +++-- 4 files changed, 65 insertions(+), 11 deletions(-) diff --git a/packages/app/src/components/draggable-list.web.tsx b/packages/app/src/components/draggable-list.web.tsx index 911f90e5a..f3601e629 100644 --- a/packages/app/src/components/draggable-list.web.tsx +++ b/packages/app/src/components/draggable-list.web.tsx @@ -89,6 +89,12 @@ function SortableItem({ }), [combinedTransform, transition, isDragging], ); + const { + role: _dragRole, + tabIndex: _dragTabIndex, + "aria-roledescription": _dragRoleDescription, + ...dragHandleAttributes + } = attributes as unknown as Record; const info: DraggableRenderItemInfo = { item, @@ -97,7 +103,7 @@ function SortableItem({ isActive: activeId === id, dragHandleProps: useDragHandle ? { - attributes: attributes as unknown as Record, + attributes: dragHandleAttributes, listeners: listeners as unknown as Record, setActivatorNodeRef: setActivatorNodeRef as unknown as (node: unknown) => void, } diff --git a/packages/app/src/components/left-sidebar.tsx b/packages/app/src/components/left-sidebar.tsx index ca67ef5d4..bcbcd68c8 100644 --- a/packages/app/src/components/left-sidebar.tsx +++ b/packages/app/src/components/left-sidebar.tsx @@ -1,5 +1,5 @@ import { router, usePathname } from "expo-router"; -import { FolderPlus, MessagesSquare, Settings } from "lucide-react-native"; +import { FolderPlus, MessagesSquare, Settings, X } from "lucide-react-native"; import { type Dispatch, memo, @@ -679,6 +679,25 @@ function MobileSidebar({ isActive={isSessionsActive} testID="sidebar-sessions" /> + + {({ hovered, pressed }) => ( + + )} + {isInitialLoad ? ( @@ -888,6 +907,18 @@ const styles = StyleSheet.create((theme) => ({ flex: 1, minHeight: 0, }, + mobileCloseButton: { + position: "absolute", + top: theme.spacing[3], + right: theme.spacing[4], + zIndex: 2, + width: 32, + height: 32, + alignItems: "center", + justifyContent: "center", + borderRadius: theme.borderRadius.lg, + backgroundColor: theme.colors.surfaceSidebar, + }, desktopSidebarBorder: { borderRightWidth: 1, borderRightColor: theme.colors.border, diff --git a/packages/app/src/components/sidebar-workspace-list.tsx b/packages/app/src/components/sidebar-workspace-list.tsx index a186af91e..b386e9a4d 100644 --- a/packages/app/src/components/sidebar-workspace-list.tsx +++ b/packages/app/src/components/sidebar-workspace-list.tsx @@ -594,7 +594,7 @@ function ProjectKebabMenu({ @@ -725,7 +725,7 @@ function WorkspaceKebabMenu({ @@ -895,7 +895,7 @@ function NewWorktreeButton({ style={pressableStyle} onPress={handlePress} disabled={loading} - accessibilityRole="button" + accessibilityRole={platformIsWeb ? undefined : "button"} accessibilityLabel={`Create a new workspace for ${displayName}`} testID={testID} > @@ -1187,6 +1187,12 @@ function ProjectHeaderRow({ drag, menuController, }); + const { + role: _dragRole, + tabIndex: _dragTabIndex, + "aria-roledescription": _dragRoleDescription, + ...dragAttributes + } = dragHandleProps?.attributes ?? {}; const handlePress = useCallback(() => { if (interaction.didLongPressRef.current) { @@ -1250,7 +1256,7 @@ function ProjectHeaderRow({ if (menuController) { return ( } onPointerEnter={handlePointerEnter} @@ -1258,6 +1264,7 @@ function ProjectHeaderRow({ > } onPointerEnter={handlePointerEnter} onPointerLeave={handlePointerLeave} > { if (interaction.didLongPressRef.current) { @@ -1369,7 +1383,7 @@ function WorkspaceRowInner({ return ( } style={styles.workspaceRowContainer} diff --git a/packages/app/src/components/workspace-hover-card.tsx b/packages/app/src/components/workspace-hover-card.tsx index 9d28e3429..1d89935a1 100644 --- a/packages/app/src/components/workspace-hover-card.tsx +++ b/packages/app/src/components/workspace-hover-card.tsx @@ -8,7 +8,7 @@ import { type ReactElement, type ReactNode, } from "react"; -import { Dimensions, Platform, Text, View } from "react-native"; +import { Dimensions, Text, View } from "react-native"; import Animated, { FadeIn, FadeOut } from "react-native-reanimated"; import { StyleSheet, withUnistyles } from "react-native-unistyles"; import { CircleCheck, CircleDot, CircleX, ExternalLink } from "lucide-react-native"; @@ -23,6 +23,8 @@ import type { PrHint } from "@/git/use-pr-status-query"; import { openExternalUrl } from "@/utils/open-external-url"; import { PrBadge } from "@/components/sidebar-workspace-list"; import { useHoverSafeZone } from "@/hooks/use-hover-safe-zone"; +import { useIsCompactFormFactor } from "@/constants/layout"; +import { isWeb } from "@/constants/platform"; interface Rect { x: number; @@ -84,8 +86,9 @@ export function WorkspaceHoverCard({ isDragging, children, }: PropsWithChildren): ReactNode { - // Desktop-only: skip on non-web platforms - if (Platform.OS !== "web") { + const isCompact = useIsCompactFormFactor(); + + if (!isWeb || isCompact) { return children; }