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 <boudra.moha@gmail.com>
This commit is contained in:
co-authored by
Mohamed Boudra
parent
e309d82b41
commit
35c582913d
@@ -89,6 +89,12 @@ function SortableItem<T>({
|
|||||||
}),
|
}),
|
||||||
[combinedTransform, transition, isDragging],
|
[combinedTransform, transition, isDragging],
|
||||||
);
|
);
|
||||||
|
const {
|
||||||
|
role: _dragRole,
|
||||||
|
tabIndex: _dragTabIndex,
|
||||||
|
"aria-roledescription": _dragRoleDescription,
|
||||||
|
...dragHandleAttributes
|
||||||
|
} = attributes as unknown as Record<string, unknown>;
|
||||||
|
|
||||||
const info: DraggableRenderItemInfo<T> = {
|
const info: DraggableRenderItemInfo<T> = {
|
||||||
item,
|
item,
|
||||||
@@ -97,7 +103,7 @@ function SortableItem<T>({
|
|||||||
isActive: activeId === id,
|
isActive: activeId === id,
|
||||||
dragHandleProps: useDragHandle
|
dragHandleProps: useDragHandle
|
||||||
? {
|
? {
|
||||||
attributes: attributes as unknown as Record<string, unknown>,
|
attributes: dragHandleAttributes,
|
||||||
listeners: listeners as unknown as Record<string, unknown>,
|
listeners: listeners as unknown as Record<string, unknown>,
|
||||||
setActivatorNodeRef: setActivatorNodeRef as unknown as (node: unknown) => void,
|
setActivatorNodeRef: setActivatorNodeRef as unknown as (node: unknown) => void,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { router, usePathname } from "expo-router";
|
import { router, usePathname } from "expo-router";
|
||||||
import { FolderPlus, MessagesSquare, Settings } from "lucide-react-native";
|
import { FolderPlus, MessagesSquare, Settings, X } from "lucide-react-native";
|
||||||
import {
|
import {
|
||||||
type Dispatch,
|
type Dispatch,
|
||||||
memo,
|
memo,
|
||||||
@@ -679,6 +679,25 @@ function MobileSidebar({
|
|||||||
isActive={isSessionsActive}
|
isActive={isSessionsActive}
|
||||||
testID="sidebar-sessions"
|
testID="sidebar-sessions"
|
||||||
/>
|
/>
|
||||||
|
<Pressable
|
||||||
|
style={styles.mobileCloseButton}
|
||||||
|
onPress={closeToAgent}
|
||||||
|
testID="sidebar-close"
|
||||||
|
nativeID="sidebar-close"
|
||||||
|
accessible
|
||||||
|
accessibilityRole="button"
|
||||||
|
accessibilityLabel="Close sidebar"
|
||||||
|
hitSlop={8}
|
||||||
|
>
|
||||||
|
{({ hovered, pressed }) => (
|
||||||
|
<X
|
||||||
|
size={theme.iconSize.md}
|
||||||
|
color={
|
||||||
|
hovered || pressed ? theme.colors.foreground : theme.colors.foregroundMuted
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Pressable>
|
||||||
|
|
||||||
{isInitialLoad ? (
|
{isInitialLoad ? (
|
||||||
<SidebarAgentListSkeleton />
|
<SidebarAgentListSkeleton />
|
||||||
@@ -888,6 +907,18 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
flex: 1,
|
flex: 1,
|
||||||
minHeight: 0,
|
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: {
|
desktopSidebarBorder: {
|
||||||
borderRightWidth: 1,
|
borderRightWidth: 1,
|
||||||
borderRightColor: theme.colors.border,
|
borderRightColor: theme.colors.border,
|
||||||
|
|||||||
@@ -594,7 +594,7 @@ function ProjectKebabMenu({
|
|||||||
<DropdownMenuTrigger
|
<DropdownMenuTrigger
|
||||||
hitSlop={8}
|
hitSlop={8}
|
||||||
style={projectKebabStyle}
|
style={projectKebabStyle}
|
||||||
accessibilityRole="button"
|
accessibilityRole={platformIsWeb ? undefined : "button"}
|
||||||
accessibilityLabel="Project actions"
|
accessibilityLabel="Project actions"
|
||||||
testID={`sidebar-project-kebab-${projectKey}`}
|
testID={`sidebar-project-kebab-${projectKey}`}
|
||||||
>
|
>
|
||||||
@@ -725,7 +725,7 @@ function WorkspaceKebabMenu({
|
|||||||
<DropdownMenuTrigger
|
<DropdownMenuTrigger
|
||||||
hitSlop={8}
|
hitSlop={8}
|
||||||
style={workspaceKebabStyle}
|
style={workspaceKebabStyle}
|
||||||
accessibilityRole="button"
|
accessibilityRole={platformIsWeb ? undefined : "button"}
|
||||||
accessibilityLabel="Workspace actions"
|
accessibilityLabel="Workspace actions"
|
||||||
testID={`sidebar-workspace-kebab-${workspaceKey}`}
|
testID={`sidebar-workspace-kebab-${workspaceKey}`}
|
||||||
>
|
>
|
||||||
@@ -895,7 +895,7 @@ function NewWorktreeButton({
|
|||||||
style={pressableStyle}
|
style={pressableStyle}
|
||||||
onPress={handlePress}
|
onPress={handlePress}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
accessibilityRole="button"
|
accessibilityRole={platformIsWeb ? undefined : "button"}
|
||||||
accessibilityLabel={`Create a new workspace for ${displayName}`}
|
accessibilityLabel={`Create a new workspace for ${displayName}`}
|
||||||
testID={testID}
|
testID={testID}
|
||||||
>
|
>
|
||||||
@@ -1187,6 +1187,12 @@ function ProjectHeaderRow({
|
|||||||
drag,
|
drag,
|
||||||
menuController,
|
menuController,
|
||||||
});
|
});
|
||||||
|
const {
|
||||||
|
role: _dragRole,
|
||||||
|
tabIndex: _dragTabIndex,
|
||||||
|
"aria-roledescription": _dragRoleDescription,
|
||||||
|
...dragAttributes
|
||||||
|
} = dragHandleProps?.attributes ?? {};
|
||||||
|
|
||||||
const handlePress = useCallback(() => {
|
const handlePress = useCallback(() => {
|
||||||
if (interaction.didLongPressRef.current) {
|
if (interaction.didLongPressRef.current) {
|
||||||
@@ -1250,7 +1256,7 @@ function ProjectHeaderRow({
|
|||||||
if (menuController) {
|
if (menuController) {
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
{...dragHandleProps?.attributes}
|
{...dragAttributes}
|
||||||
{...dragHandleProps?.listeners}
|
{...dragHandleProps?.listeners}
|
||||||
ref={dragHandleProps?.setActivatorNodeRef as unknown as Ref<View>}
|
ref={dragHandleProps?.setActivatorNodeRef as unknown as Ref<View>}
|
||||||
onPointerEnter={handlePointerEnter}
|
onPointerEnter={handlePointerEnter}
|
||||||
@@ -1258,6 +1264,7 @@ function ProjectHeaderRow({
|
|||||||
>
|
>
|
||||||
<ContextMenuTrigger
|
<ContextMenuTrigger
|
||||||
enabledOnMobile={false}
|
enabledOnMobile={false}
|
||||||
|
accessibilityRole="button"
|
||||||
style={projectRowStyle}
|
style={projectRowStyle}
|
||||||
onPressIn={interaction.handlePressIn}
|
onPressIn={interaction.handlePressIn}
|
||||||
onTouchMove={interaction.handleTouchMove}
|
onTouchMove={interaction.handleTouchMove}
|
||||||
@@ -1273,13 +1280,14 @@ function ProjectHeaderRow({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
{...dragHandleProps?.attributes}
|
{...dragAttributes}
|
||||||
{...dragHandleProps?.listeners}
|
{...dragHandleProps?.listeners}
|
||||||
ref={dragHandleProps?.setActivatorNodeRef as unknown as Ref<View>}
|
ref={dragHandleProps?.setActivatorNodeRef as unknown as Ref<View>}
|
||||||
onPointerEnter={handlePointerEnter}
|
onPointerEnter={handlePointerEnter}
|
||||||
onPointerLeave={handlePointerLeave}
|
onPointerLeave={handlePointerLeave}
|
||||||
>
|
>
|
||||||
<Pressable
|
<Pressable
|
||||||
|
accessibilityRole="button"
|
||||||
style={projectRowStyle}
|
style={projectRowStyle}
|
||||||
onPressIn={interaction.handlePressIn}
|
onPressIn={interaction.handlePressIn}
|
||||||
onTouchMove={interaction.handleTouchMove}
|
onTouchMove={interaction.handleTouchMove}
|
||||||
@@ -1328,6 +1336,12 @@ function WorkspaceRowInner({
|
|||||||
drag,
|
drag,
|
||||||
menuController,
|
menuController,
|
||||||
});
|
});
|
||||||
|
const {
|
||||||
|
role: _dragRole,
|
||||||
|
tabIndex: _dragTabIndex,
|
||||||
|
"aria-roledescription": _dragRoleDescription,
|
||||||
|
...dragAttributes
|
||||||
|
} = dragHandleProps?.attributes ?? {};
|
||||||
|
|
||||||
const handlePress = useCallback(() => {
|
const handlePress = useCallback(() => {
|
||||||
if (interaction.didLongPressRef.current) {
|
if (interaction.didLongPressRef.current) {
|
||||||
@@ -1369,7 +1383,7 @@ function WorkspaceRowInner({
|
|||||||
return (
|
return (
|
||||||
<WorkspaceHoverCard workspace={workspace} prHint={prHint} isDragging={isDragging}>
|
<WorkspaceHoverCard workspace={workspace} prHint={prHint} isDragging={isDragging}>
|
||||||
<View
|
<View
|
||||||
{...dragHandleProps?.attributes}
|
{...dragAttributes}
|
||||||
{...dragHandleProps?.listeners}
|
{...dragHandleProps?.listeners}
|
||||||
ref={dragHandleProps?.setActivatorNodeRef as unknown as Ref<View>}
|
ref={dragHandleProps?.setActivatorNodeRef as unknown as Ref<View>}
|
||||||
style={styles.workspaceRowContainer}
|
style={styles.workspaceRowContainer}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
type ReactElement,
|
type ReactElement,
|
||||||
type ReactNode,
|
type ReactNode,
|
||||||
} from "react";
|
} 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 Animated, { FadeIn, FadeOut } from "react-native-reanimated";
|
||||||
import { StyleSheet, withUnistyles } from "react-native-unistyles";
|
import { StyleSheet, withUnistyles } from "react-native-unistyles";
|
||||||
import { CircleCheck, CircleDot, CircleX, ExternalLink } from "lucide-react-native";
|
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 { openExternalUrl } from "@/utils/open-external-url";
|
||||||
import { PrBadge } from "@/components/sidebar-workspace-list";
|
import { PrBadge } from "@/components/sidebar-workspace-list";
|
||||||
import { useHoverSafeZone } from "@/hooks/use-hover-safe-zone";
|
import { useHoverSafeZone } from "@/hooks/use-hover-safe-zone";
|
||||||
|
import { useIsCompactFormFactor } from "@/constants/layout";
|
||||||
|
import { isWeb } from "@/constants/platform";
|
||||||
|
|
||||||
interface Rect {
|
interface Rect {
|
||||||
x: number;
|
x: number;
|
||||||
@@ -84,8 +86,9 @@ export function WorkspaceHoverCard({
|
|||||||
isDragging,
|
isDragging,
|
||||||
children,
|
children,
|
||||||
}: PropsWithChildren<WorkspaceHoverCardProps>): ReactNode {
|
}: PropsWithChildren<WorkspaceHoverCardProps>): ReactNode {
|
||||||
// Desktop-only: skip on non-web platforms
|
const isCompact = useIsCompactFormFactor();
|
||||||
if (Platform.OS !== "web") {
|
|
||||||
|
if (!isWeb || isCompact) {
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user