` through the
+ * `renderGridOverlay` prop. Receives the grid's resolved column
+ * count, gap, row height, and `isActive` flag; this implementation
+ * drops the row dividers, swaps to an info tone, labels each column
+ * track with its index, and fades in/out on `isActive` toggles. The
+ * grid always mounts the overlay; the consumer owns the visual and
+ * its transition.
+ *
+ * @param props Render props supplied by the grid.
+ * @param props.columns Number of column tracks to mirror.
+ * @param props.gapPx Gap between tracks in pixels.
+ * @param props.isActive Whether the overlay should be visible.
+ */
+function NumberedOverlay( {
+ columns,
+ gapPx,
+ isActive,
+}: GridOverlayRenderProps ) {
+ return (
+
+ { Array.from( { length: columns } ).map( ( _, i ) => (
+
+
+ { i + 1 }
+
+
+ ) ) }
+
+ );
+}
+
+/**
+ * Replaces the package's default edit-mode overlay with a custom
+ * visual through the `renderGridOverlay` prop. The grid mounts the
+ * supplied component as a sibling behind the tiles whenever
+ * `editMode` is on, passing the resolved `{ columns, gapPx,
+ * rowHeight }` so the override can reproduce the column and row
+ * tracks pixel-accurately without re-deriving them.
+ *
+ * Here the override (see `NumberedOverlay` above) swaps the warning
+ * tone for info, drops the row dividers, and labels each column
+ * track with its index. Pass `renderGridOverlay={ () => null }` to
+ * suppress the overlay entirely while keeping `editMode` interactions
+ * on.
+ */
+export const CustomGridOverlayStory: Story = {
+ name: 'Custom Grid Overlay',
+ args: {
+ columns: 12,
+ spacing: 4,
+ rowHeight: 80,
+ editMode: true,
+ layout: [
+ { key: 'a', width: 3, height: 1 },
+ { key: 'b', width: 5, height: 1 },
+ { key: 'c', width: 4, height: 1 },
+ { key: 'd', width: 2, height: 2 },
+ { key: 'e', width: 6, height: 1 },
+ ],
+ },
+ render: function CustomGridOverlayRender( args ) {
+ const [ layout, setLayout ] = useState< DashboardGridLayoutItem[] >(
+ args.layout
+ );
+
+ const tiles = useMemo(
+ () => [
+
+ A
+ ,
+
+ B
+ ,
+
+ C
+ ,
+
+ D
+ ,
+
+ E
+ ,
+ ],
+ []
+ );
+
+ return (
+
+ { tiles }
+
+ );
+ },
+};
diff --git a/packages/grid/src/dashboard-grid/types.ts b/packages/grid/src/dashboard-grid/types.ts
index 360505873d6976..b23c09c583b35c 100644
--- a/packages/grid/src/dashboard-grid/types.ts
+++ b/packages/grid/src/dashboard-grid/types.ts
@@ -3,6 +3,7 @@
*/
import type {
DragPreviewRenderProps,
+ GridOverlayRenderProps,
ResizeDelta,
ResizeHandleRenderProps,
} from '../shared/types';
@@ -209,6 +210,17 @@ interface BaseDashboardGridProps
* properties documented in the README.
*/
renderDragPreview?: React.ComponentType< DragPreviewRenderProps >;
+
+ /**
+ * Override the default edit-mode overlay (diagonal stripes plus
+ * dashed column and row tracks) with a custom component. The grid
+ * supplies the resolved column count, gap, and row height; the
+ * consumer is responsible for the visual.
+ *
+ * The overlay only renders when `editMode` is true. When omitted,
+ * the package's default visual is used.
+ */
+ renderGridOverlay?: React.ComponentType< GridOverlayRenderProps >;
}
interface FixedDashboardGridProps extends BaseDashboardGridProps {
diff --git a/packages/grid/src/dashboard-lanes/index.tsx b/packages/grid/src/dashboard-lanes/index.tsx
index 033f65cd658a25..1339b124d6ef3e 100644
--- a/packages/grid/src/dashboard-lanes/index.tsx
+++ b/packages/grid/src/dashboard-lanes/index.tsx
@@ -37,6 +37,7 @@ import {
*/
import { LanesItem } from './lanes-item';
import { useLanePlacement } from './use-lane-placement';
+import { GridOverlay } from '../shared/grid-overlay';
import type { DashboardLanesLayoutItem, DashboardLanesProps } from './types';
import type { ResizeDelta } from '../shared/types';
import styles from './lanes.module.css';
@@ -97,6 +98,7 @@ export const DashboardLanes = forwardRef< HTMLDivElement, DashboardLanesProps >(
onPreviewLayout,
renderResizeHandle,
renderDragPreview,
+ renderGridOverlay,
...divProps
} = props;
@@ -421,6 +423,25 @@ export const DashboardLanes = forwardRef< HTMLDivElement, DashboardLanesProps >(
) : null;
+ // Edit-mode background visual. Lanes are content-driven
+ // vertically, so the overlay only mirrors columns; the default
+ // can be replaced wholesale via `renderGridOverlay`. Rendered
+ // unconditionally so the overlay can cross-fade on edit-mode
+ // toggles; `isActive` drives the opacity transition inside the
+ // overlay. Memoized so drag/resize re-renders skip
+ // reconciliation while inputs are stable.
+ const Overlay = renderGridOverlay ?? GridOverlay;
+ const gridOverlay = useMemo(
+ () => (
+
+ ),
+ [ Overlay, editMode, effectiveColumns, gapPx ]
+ );
+
return (