This is an automated email from the ASF dual-hosted git repository.
choo121600 pushed a commit to branch v3-2-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v3-2-test by this push:
new 42f2e4e7cba [v3-2-test] UI: Show DAG name in browser tab title
(#67169) (#67399)
42f2e4e7cba is described below
commit 42f2e4e7cba6790955321f57bcc7dd84e4446ed6
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Mon May 25 03:49:52 2026 +0900
[v3-2-test] UI: Show DAG name in browser tab title (#67169) (#67399)
(cherry picked from commit ea7481d7d59b0eb129f8b39c848a24aa111e7ca3)
Co-authored-by: Subham <[email protected]>
---
.../src/airflow/ui/src/layouts/BaseLayout.tsx | 5 ----
airflow-core/src/airflow/ui/src/pages/Dag/Dag.tsx | 4 +++-
airflow-core/src/airflow/ui/src/utils/index.ts | 1 +
.../ui/src/utils/{index.ts => useDocumentTitle.ts} | 27 +++++++++++++++-------
4 files changed, 23 insertions(+), 14 deletions(-)
diff --git a/airflow-core/src/airflow/ui/src/layouts/BaseLayout.tsx
b/airflow-core/src/airflow/ui/src/layouts/BaseLayout.tsx
index 062caca76d3..f40cea8c54c 100644
--- a/airflow-core/src/airflow/ui/src/layouts/BaseLayout.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/BaseLayout.tsx
@@ -29,7 +29,6 @@ import { useConfig } from "src/queries/useConfig";
import { Nav } from "./Nav";
export const BaseLayout = ({ children }: PropsWithChildren) => {
- const instanceName = useConfig("instance_name");
const { i18n } = useTranslation();
const { data: pluginData } = usePluginServiceGetPlugins();
const theme = useConfig("theme") as unknown as { icon?: string;
icon_dark_mode?: string } | undefined;
@@ -39,10 +38,6 @@ export const BaseLayout = ({ children }: PropsWithChildren)
=> {
.flatMap((plugin) => plugin.react_apps)
.filter((reactApp: ReactAppResponse) => reactApp.destination === "base")
?? [];
- if (typeof instanceName === "string") {
- document.title = instanceName;
- }
-
useEffect(() => {
const html = document.documentElement;
diff --git a/airflow-core/src/airflow/ui/src/pages/Dag/Dag.tsx
b/airflow-core/src/airflow/ui/src/pages/Dag/Dag.tsx
index 95634cb9245..aa7e421b3a8 100644
--- a/airflow-core/src/airflow/ui/src/pages/Dag/Dag.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Dag/Dag.tsx
@@ -32,7 +32,7 @@ import { usePluginTabs } from "src/hooks/usePluginTabs";
import { useRequiredActionTabs } from "src/hooks/useRequiredActionTabs";
import { DetailsLayout } from "src/layouts/Details/DetailsLayout";
import { useRefreshOnNewDagRuns } from "src/queries/useRefreshOnNewDagRuns";
-import { isStatePending, useAutoRefresh } from "src/utils";
+import { isStatePending, useAutoRefresh, useDocumentTitle } from "src/utils";
import { DagNotFound } from "./DagNotFound";
import { Header } from "./Header";
@@ -86,6 +86,8 @@ export const Dag = () => {
},
);
+ useDocumentTitle(dag?.dag_display_name ?? dagId);
+
// Ensures continuous refresh to detect new runs when there's no
// pending state and new runs are initiated from other page
useRefreshOnNewDagRuns(dagId, hasPendingRuns, dag?.is_paused);
diff --git a/airflow-core/src/airflow/ui/src/utils/index.ts
b/airflow-core/src/airflow/ui/src/utils/index.ts
index 486cc4bee66..c15a50f6dd7 100644
--- a/airflow-core/src/airflow/ui/src/utils/index.ts
+++ b/airflow-core/src/airflow/ui/src/utils/index.ts
@@ -22,6 +22,7 @@ export { getDuration, renderDuration } from "./datetimeUtils";
export { createErrorToaster, getErrorStatus } from "./errorHandling";
export { getMetaKey } from "./getMetaKey";
export { useContainerWidth } from "./useContainerWidth";
+export { useDocumentTitle } from "./useDocumentTitle";
export { useFiltersHandler, type FilterableSearchParamsKeys } from
"./useFiltersHandler";
export * from "./query";
export { STATE_PRIORITY, sortStateEntries } from "./stateUtils";
diff --git a/airflow-core/src/airflow/ui/src/utils/index.ts
b/airflow-core/src/airflow/ui/src/utils/useDocumentTitle.ts
similarity index 58%
copy from airflow-core/src/airflow/ui/src/utils/index.ts
copy to airflow-core/src/airflow/ui/src/utils/useDocumentTitle.ts
index 486cc4bee66..e94f0d9c18c 100644
--- a/airflow-core/src/airflow/ui/src/utils/index.ts
+++ b/airflow-core/src/airflow/ui/src/utils/useDocumentTitle.ts
@@ -16,12 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
+import { useEffect } from "react";
-export { capitalize } from "./capitalize";
-export { getDuration, renderDuration } from "./datetimeUtils";
-export { createErrorToaster, getErrorStatus } from "./errorHandling";
-export { getMetaKey } from "./getMetaKey";
-export { useContainerWidth } from "./useContainerWidth";
-export { useFiltersHandler, type FilterableSearchParamsKeys } from
"./useFiltersHandler";
-export * from "./query";
-export { STATE_PRIORITY, sortStateEntries } from "./stateUtils";
+import { useConfig } from "src/queries/useConfig";
+
+export const useDocumentTitle = (pageTitle?: string | null) => {
+ const instanceConfig = useConfig("instance_name");
+ const instanceName = typeof instanceConfig === "string" ? instanceConfig :
"Airflow";
+
+ useEffect(() => {
+ const previousTitle = document.title;
+
+ if (typeof pageTitle === "string" && pageTitle.length > 0) {
+ document.title = `${pageTitle} - ${instanceName}`;
+ }
+
+ return () => {
+ document.title = previousTitle;
+ };
+ }, [pageTitle, instanceName]);
+};