This is an automated email from the ASF dual-hosted git repository.

pierrejeambrun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new a3ec1c59f5a Move grid focus state to store (#54393)
a3ec1c59f5a is described below

commit a3ec1c59f5af83deba650376ecbfa9cb8d44f26b
Author: Pierre Jeambrun <[email protected]>
AuthorDate: Tue Aug 12 18:58:05 2025 +0200

    Move grid focus state to store (#54393)
---
 .../airflow/ui/src/layouts/Details/Grid/Grid.tsx   | 22 ++++++++++-------
 .../ui/src/layouts/Details/Grid/useGridStore.ts    | 28 ++++++++++++++++++++++
 2 files changed, 41 insertions(+), 9 deletions(-)

diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Grid.tsx 
b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Grid.tsx
index f631fc57e46..f8a618015c3 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Grid.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Grid.tsx
@@ -35,6 +35,7 @@ import { Bar } from "./Bar";
 import { DurationAxis } from "./DurationAxis";
 import { DurationTick } from "./DurationTick";
 import { TaskNames } from "./TaskNames";
+import { useGridStore } from "./useGridStore";
 import { flattenNodes } from "./utils";
 
 dayjs.extend(dayjsDuration);
@@ -59,7 +60,7 @@ type Props = {
 export const Grid = ({ limit }: Props) => {
   const { t: translate } = useTranslation("dag");
   const gridRef = useRef<HTMLDivElement>(null);
-  const [isGridFocused, setIsGridFocused] = useState(false);
+  const { isGridFocused, setIsGridFocused } = useGridStore();
 
   const [selectedIsVisible, setSelectedIsVisible] = useState<boolean | 
undefined>();
   const [hasActiveRun, setHasActiveRun] = useState<boolean | undefined>();
@@ -104,14 +105,17 @@ export const Grid = ({ limit }: Props) => {
 
   const { flatNodes } = useMemo(() => flattenNodes(dagStructure, 
openGroupIds), [dagStructure, openGroupIds]);
 
-  const setGridFocus = useCallback((focused: boolean) => {
-    setIsGridFocused(focused);
-    if (focused) {
-      gridRef.current?.focus();
-    } else {
-      gridRef.current?.blur();
-    }
-  }, []);
+  const setGridFocus = useCallback(
+    (focused: boolean) => {
+      setIsGridFocused(focused);
+      if (focused) {
+        gridRef.current?.focus();
+      } else {
+        gridRef.current?.blur();
+      }
+    },
+    [setIsGridFocused],
+  );
 
   const { mode, setMode } = useNavigation({
     enabled: isGridFocused,
diff --git 
a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/useGridStore.ts 
b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/useGridStore.ts
new file mode 100644
index 00000000000..7f580649932
--- /dev/null
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/useGridStore.ts
@@ -0,0 +1,28 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { create } from "zustand";
+
+export const useGridStore = create<{ isGridFocused: boolean; setIsGridFocused: 
(value: boolean) => void }>(
+  (set) => ({
+    // isGridFocused is shared between different pages (Run, GroupInstance, 
MappedInstance, TaskInstance, etc.).
+    // This will avoid many prop drilling and allow proper refocus of the grid 
when navigating between these pages via grid links.
+    isGridFocused: false,
+    setIsGridFocused: (value: boolean) => set({ isGridFocused: value }),
+  }),
+);

Reply via email to