id === widget.id);
const index = widgets.findIndex(({ id }) => id === widget.id);
+ // Where it is now, mid-move included, for screen readers.
+ const position = displayed.findIndex(
+ ({ id }) => id === widget.id,
+ );
const definition = getFeedWidgetDefinition(widget.kind);
const Component = getFeedWidgetComponent(widget.kind);
if (!Component || !shownWidget) {
return null;
}
+ const isDragged = dragId === widget.id;
+ const isLifted = liftedId === widget.id;
+ const sizes = sizesForScreen(widget.kind, isPhone);
+ // On a phone the menu resizes: a corner grip is a poor touch
+ // target, and its preview could reach a span the phone never
+ // shows, writing a size to every other screen.
+ const canResize = !isPhone && sizes.length > 1;
return (
-
+ {isDragged && (
+
)}
- >
-
editing.onItemKeyDown(event, widget)}
+ onPointerDown={(event) =>
+ editing.onItemPointerDown(event, widget.id)
+ }
+ onPointerMove={editing.onItemPointerMove}
+ onPointerUp={editing.onItemPointerUp}
+ onPointerCancel={editing.onItemPointerCancel}
+ onClickCapture={editing.onItemClickCapture}
+ onContextMenu={editing.onItemContextMenu}
+ style={gridArea(placement)}
+ className={classNames(
+ 'group/widget relative flex min-h-0 min-w-0 snap-start rounded-16 outline-none',
+ 'focus-visible:ring-2 focus-visible:ring-accent-cabbage-default',
+ // No long-press callout: a hold on a widget enters edit
+ // mode, and in edit mode it starts a drag.
+ '[-webkit-touch-callout:none]',
+ isEditing && 'cursor-grab touch-pan-x select-none',
+ isEditing &&
+ !isBusy &&
+ !isGalleryOpen &&
+ 'feed-widget-jiggle',
+ isDragged &&
+ 'pointer-events-none z-3 cursor-grabbing shadow-3',
+ isLifted &&
+ 'z-2 scale-[1.03] shadow-3 transition-transform duration-150',
+ flashId === widget.id && 'feed-widget-flash',
+ )}
>
-
-
-
-
- {isEditing && (
- <>
-
-
0}
- canMoveRight={index < widgets.length - 1}
- onAction={(action) => onMenuAction(widget, action)}
- />
- >
- )}
-
+
+
+
+
+
+ {isEditing && !isDragged && (
+ <>
+
+
event.stopPropagation()}
+ >
+ 0}
+ canMoveRight={index < widgets.length - 1}
+ onAction={(action) => onMenuAction(widget, action)}
+ />
+
+ {canResize &&
+ !isGalleryOpen &&
+ railCorners.map((corner) => (
+
+ editing.onResizeStart(
+ event,
+ shownWidget,
+ corner,
+ )
+ }
+ onPointerMove={editing.onResizeMove}
+ onPointerUp={editing.onResizeEnd}
+ onPointerCancel={editing.onResizeCancel}
+ className={classNames(
+ 'feed-widget-controls-in absolute z-2 size-7 touch-none border-text-primary transition-transform duration-150 before:absolute before:-inset-2 hover:scale-110 motion-reduce:transition-none',
+ cornerClassName[corner],
+ )}
+ />
+ ))}
+ {resizing?.id === widget.id && (
+ <>
+
+
+
+ {feedWidgetSizeLabel[resizing.size]}
+
+
+ >
+ )}
+ >
+ )}
+
+
);
})}
{canAdd && (
diff --git a/packages/shared/src/features/feedWidgets/FeedWidgetRailHeader.tsx b/packages/shared/src/features/feedWidgets/FeedWidgetRailHeader.tsx
index bfa9b776a2..3a118cddae 100644
--- a/packages/shared/src/features/feedWidgets/FeedWidgetRailHeader.tsx
+++ b/packages/shared/src/features/feedWidgets/FeedWidgetRailHeader.tsx
@@ -47,7 +47,7 @@ export const FeedWidgetRailHeader = ({