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

choo121600 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 42a85ee1ac9 UI: Add custom RouterLink component (#66945)
42a85ee1ac9 is described below

commit 42a85ee1ac90818566c9487cff20337dbc8cab7b
Author: hojeong park <[email protected]>
AuthorDate: Sat May 16 15:39:27 2026 +0900

    UI: Add custom RouterLink component (#66945)
    
    * UI: Add custom RouterLink component
    
    * UI: Default RouterLink color to info
    
    * UI: Restrict RouterLink composition props
    
    * UI: Apply custom RouterLink component
    
    * UI: Apply custom RouterLink component
---
 .../src/components/AssetExpression/AssetNode.tsx   | 11 ++---
 .../ui/src/components/Assets/TriggeredRuns.tsx     | 17 +++-----
 .../src/components/ui/{index.ts => RouterLink.tsx} | 29 +++++--------
 .../src/airflow/ui/src/components/ui/index.ts      |  1 +
 .../airflow/ui/src/pages/AssetsList/AssetsList.tsx | 11 ++---
 .../ui/src/pages/AssetsList/DependencyPopover.tsx  | 11 +++--
 .../src/airflow/ui/src/pages/Dag/Header.tsx        | 24 +++++------
 .../ui/src/pages/Dag/Overview/DeadlineRow.tsx      | 16 ++++---
 .../ui/src/pages/Dag/Overview/TaskLogPreview.tsx   | 12 +++---
 .../src/airflow/ui/src/pages/Dag/Tasks/Tasks.tsx   | 12 +++---
 airflow-core/src/airflow/ui/src/pages/DagRuns.tsx  | 29 ++++++-------
 .../ui/src/pages/DagsList/AssetSchedule.tsx        | 13 +++---
 .../src/airflow/ui/src/pages/DagsList/DagCard.tsx  | 39 ++++++++---------
 .../airflow/ui/src/pages/DagsList/DagOwners.tsx    |  8 ++--
 .../src/airflow/ui/src/pages/DagsList/DagTags.tsx  |  9 ++--
 .../src/airflow/ui/src/pages/DagsList/DagsList.tsx | 42 ++++++++----------
 .../pages/Dashboard/PoolSummary/PoolSummary.tsx    | 10 ++---
 .../pages/HITLTaskInstances/HITLTaskInstances.tsx  | 44 +++++++++----------
 .../src/airflow/ui/src/pages/Run/Header.tsx        | 16 +++----
 .../ui/src/pages/TaskInstances/TaskInstances.tsx   | 37 +++++++---------
 .../src/airflow/ui/src/pages/XCom/XCom.tsx         | 50 ++++++++++------------
 21 files changed, 195 insertions(+), 246 deletions(-)

diff --git 
a/airflow-core/src/airflow/ui/src/components/AssetExpression/AssetNode.tsx 
b/airflow-core/src/airflow/ui/src/components/AssetExpression/AssetNode.tsx
index 6289309ec59..86a0a2e6e8b 100644
--- a/airflow-core/src/airflow/ui/src/components/AssetExpression/AssetNode.tsx
+++ b/airflow-core/src/airflow/ui/src/components/AssetExpression/AssetNode.tsx
@@ -16,10 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Box, Text, HStack, Link } from "@chakra-ui/react";
+import { Box, Text, HStack } from "@chakra-ui/react";
 import { FiDatabase } from "react-icons/fi";
 import { PiRectangleDashed } from "react-icons/pi";
-import { Link as RouterLink } from "react-router-dom";
+
+import { RouterLink } from "src/components/ui";
 
 import Time from "../Time";
 import type { AssetSummary, NextRunEvent } from "./types";
@@ -47,9 +48,9 @@ export const AssetNode = ({
       {"alias" in asset ? (
         <Text fontSize="sm">{asset.alias.name}</Text>
       ) : (
-        <Link asChild color="fg.info" display="block" py={2}>
-          <RouterLink 
to={`/assets/${asset.asset.id}`}>{asset.asset.name}</RouterLink>
-        </Link>
+        <RouterLink display="block" py={2} to={`/assets/${asset.asset.id}`}>
+          {asset.asset.name}
+        </RouterLink>
       )}
     </HStack>
     {event?.lastUpdate === undefined ? undefined : (
diff --git 
a/airflow-core/src/airflow/ui/src/components/Assets/TriggeredRuns.tsx 
b/airflow-core/src/airflow/ui/src/components/Assets/TriggeredRuns.tsx
index 1efb1ec8c54..478cce36323 100644
--- a/airflow-core/src/airflow/ui/src/components/Assets/TriggeredRuns.tsx
+++ b/airflow-core/src/airflow/ui/src/components/Assets/TriggeredRuns.tsx
@@ -16,12 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Button, Flex, Link, Text } from "@chakra-ui/react";
+import { Button, Flex, Text } from "@chakra-ui/react";
 import { useTranslation } from "react-i18next";
-import { Link as RouterLink } from "react-router-dom";
 
 import type { DagRunAssetReference, DagRunState } from 
"openapi/requests/types.gen";
-import { Popover } from "src/components/ui";
+import { Popover, RouterLink } from "src/components/ui";
 
 import { StateBadge } from "../StateBadge";
 
@@ -40,11 +39,9 @@ export const TriggeredRuns = ({ dagRuns }: Props) => {
     <Flex gap={1}>
       <Text>{`${translate("triggered")} ${translate("dagRun_one")}`}: </Text>
       <StateBadge state={dagRuns[0]?.state as DagRunState} />
-      <Link asChild color="fg.info">
-        <RouterLink 
to={`/dags/${dagRuns[0]?.dag_id}/runs/${dagRuns[0]?.run_id}`}>
-          {dagRuns[0]?.dag_id}
-        </RouterLink>
-      </Link>
+      <RouterLink 
to={`/dags/${dagRuns[0]?.dag_id}/runs/${dagRuns[0]?.run_id}`}>
+        {dagRuns[0]?.dag_id}
+      </RouterLink>
     </Flex>
   ) : (
     // eslint-disable-next-line jsx-a11y/no-autofocus
@@ -60,9 +57,7 @@ export const TriggeredRuns = ({ dagRuns }: Props) => {
           {dagRuns.map((dagRun) => (
             <Flex gap={1} key={dagRun.dag_id} my={2}>
               <StateBadge state={dagRun.state as DagRunState} />
-              <Link asChild color="fg.info">
-                <RouterLink 
to={`/dags/${dagRun.dag_id}/runs/${dagRun.run_id}`}>{dagRun.dag_id}</RouterLink>
-              </Link>
+              <RouterLink 
to={`/dags/${dagRun.dag_id}/runs/${dagRun.run_id}`}>{dagRun.dag_id}</RouterLink>
             </Flex>
           ))}
         </Popover.Body>
diff --git a/airflow-core/src/airflow/ui/src/components/ui/index.ts 
b/airflow-core/src/airflow/ui/src/components/ui/RouterLink.tsx
similarity index 60%
copy from airflow-core/src/airflow/ui/src/components/ui/index.ts
copy to airflow-core/src/airflow/ui/src/components/ui/RouterLink.tsx
index 4adadca3731..59d4a04366c 100644
--- a/airflow-core/src/airflow/ui/src/components/ui/index.ts
+++ b/airflow-core/src/airflow/ui/src/components/ui/RouterLink.tsx
@@ -16,22 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+import { Link as ChakraLink, type LinkProps as ChakraLinkProps } from 
"@chakra-ui/react";
+import { Link as ReactRouterLink, type To } from "react-router-dom";
 
-export * from "./Dialog";
-export * from "./Pagination";
-export * from "./Select";
-export * from "./Alert";
-export * from "./Switch";
-export * from "./Tooltip";
-export * from "./ProgressBar";
-export * from "./Menu";
-export * from "./Accordion";
-export * from "./Toaster";
-export * from "./Breadcrumb";
-export * from "./Clipboard";
-export * from "./Popover";
-export * from "./Checkbox";
-export * from "./ResetButton";
-export * from "./InputWithAddon";
-export * from "./ButtonGroupToggle";
-export * from "./LazyClipboard";
+type RouterLinkProps = {
+  readonly to: To;
+} & Omit<ChakraLinkProps, "as" | "asChild" | "href">;
+
+export const RouterLink = ({ children, to, ...rest }: RouterLinkProps) => (
+  <ChakraLink asChild color="fg.info" {...rest}>
+    <ReactRouterLink to={to}>{children}</ReactRouterLink>
+  </ChakraLink>
+);
diff --git a/airflow-core/src/airflow/ui/src/components/ui/index.ts 
b/airflow-core/src/airflow/ui/src/components/ui/index.ts
index 4adadca3731..8569cce7df8 100644
--- a/airflow-core/src/airflow/ui/src/components/ui/index.ts
+++ b/airflow-core/src/airflow/ui/src/components/ui/index.ts
@@ -35,3 +35,4 @@ export * from "./ResetButton";
 export * from "./InputWithAddon";
 export * from "./ButtonGroupToggle";
 export * from "./LazyClipboard";
+export * from "./RouterLink";
diff --git a/airflow-core/src/airflow/ui/src/pages/AssetsList/AssetsList.tsx 
b/airflow-core/src/airflow/ui/src/pages/AssetsList/AssetsList.tsx
index 95b9420b3d7..9ddbe3d77ee 100644
--- a/airflow-core/src/airflow/ui/src/pages/AssetsList/AssetsList.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/AssetsList/AssetsList.tsx
@@ -16,10 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Flex, Heading, Link, useDisclosure, VStack } from "@chakra-ui/react";
+import { Flex, Heading, useDisclosure, VStack } from "@chakra-ui/react";
 import type { ColumnDef } from "@tanstack/react-table";
 import { useTranslation } from "react-i18next";
-import { useSearchParams, Link as RouterLink } from "react-router-dom";
+import { useSearchParams } from "react-router-dom";
 
 import { useAssetServiceGetAssets } from "openapi/queries";
 import type { AssetResponse } from "openapi/requests/types.gen";
@@ -30,6 +30,7 @@ import { ExpandCollapseButtons } from 
"src/components/ExpandCollapseButtons";
 import RenderedJsonField from "src/components/RenderedJsonField";
 import { SearchBar } from "src/components/SearchBar";
 import Time from "src/components/Time";
+import { RouterLink } from "src/components/ui";
 import { SearchParamsKeys, type SearchParamsKeysType } from 
"src/constants/searchParams";
 import { useAdvancedSearch } from "src/hooks/useAdvancedSearch";
 import { CreateAssetEvent } from "src/pages/Asset/CreateAssetEvent";
@@ -45,9 +46,9 @@ const createColumns = (
   {
     accessorKey: "name",
     cell: ({ row: { original } }: AssetRow) => (
-      <Link asChild color="fg.info" fontWeight="bold">
-        <RouterLink to={`/assets/${original.id}`}>{original.name}</RouterLink>
-      </Link>
+      <RouterLink fontWeight="bold" to={`/assets/${original.id}`}>
+        {original.name}
+      </RouterLink>
     ),
     header: () => translate("name"),
   },
diff --git 
a/airflow-core/src/airflow/ui/src/pages/AssetsList/DependencyPopover.tsx 
b/airflow-core/src/airflow/ui/src/pages/AssetsList/DependencyPopover.tsx
index 9eee5e46404..9eba94f2647 100644
--- a/airflow-core/src/airflow/ui/src/pages/AssetsList/DependencyPopover.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/AssetsList/DependencyPopover.tsx
@@ -16,12 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Button, Link } from "@chakra-ui/react";
+import { Button } from "@chakra-ui/react";
 import { useTranslation } from "react-i18next";
-import { Link as RouterLink } from "react-router-dom";
 
 import type { DagScheduleAssetReference, TaskOutletAssetReference } from 
"openapi/requests/types.gen";
-import { Popover } from "src/components/ui";
+import { Popover, RouterLink } from "src/components/ui";
 
 type Props = {
   readonly dependencies: Array<DagScheduleAssetReference | 
TaskOutletAssetReference>;
@@ -57,9 +56,9 @@ export const DependencyPopover = ({ dependencies, type }: 
Props) => {
             }
 
             return (
-              <Link asChild color="fg.info" display="block" key={key} py={2}>
-                <RouterLink to={link}>{label}</RouterLink>
-              </Link>
+              <RouterLink display="block" key={key} py={2} to={link}>
+                {label}
+              </RouterLink>
             );
           })}
         </Popover.Body>
diff --git a/airflow-core/src/airflow/ui/src/pages/Dag/Header.tsx 
b/airflow-core/src/airflow/ui/src/pages/Dag/Header.tsx
index 7367e7ea0a8..c18671b3c6b 100644
--- a/airflow-core/src/airflow/ui/src/pages/Dag/Header.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Dag/Header.tsx
@@ -16,10 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Link } from "@chakra-ui/react";
 import { useTranslation } from "react-i18next";
 import { FiBookOpen } from "react-icons/fi";
-import { useParams, Link as RouterLink } from "react-router-dom";
+import { useParams } from "react-router-dom";
 
 import type { DAGDetailsResponse, DagRunState } from 
"openapi/requests/types.gen";
 import { DagIcon } from "src/assets/DagIcon";
@@ -32,6 +31,7 @@ import { DagVersion } from "src/components/DagVersion";
 import DisplayMarkdownButton from "src/components/DisplayMarkdownButton";
 import { HeaderCard } from "src/components/HeaderCard";
 import { TogglePause } from "src/components/TogglePause";
+import { RouterLink } from "src/components/ui";
 
 import { DagOwners } from "../DagsList/DagOwners";
 import { DagTags } from "../DagsList/DagTags";
@@ -93,17 +93,15 @@ export const Header = ({
       label: translate("dagDetails.latestRun"),
       value:
         Boolean(latestRunInfo) && latestRunInfo !== undefined ? (
-          <Link asChild color="fg.info">
-            <RouterLink 
to={`/dags/${latestRunInfo.dag_id}/runs/${latestRunInfo.run_id}`}>
-              <DagRunInfo
-                endDate={latestRunInfo.end_date}
-                logicalDate={latestRunInfo.logical_date}
-                runAfter={latestRunInfo.run_after}
-                startDate={latestRunInfo.start_date}
-                state={latestRunInfo.state}
-              />
-            </RouterLink>
-          </Link>
+          <RouterLink 
to={`/dags/${latestRunInfo.dag_id}/runs/${latestRunInfo.run_id}`}>
+            <DagRunInfo
+              endDate={latestRunInfo.end_date}
+              logicalDate={latestRunInfo.logical_date}
+              runAfter={latestRunInfo.run_after}
+              startDate={latestRunInfo.start_date}
+              state={latestRunInfo.state}
+            />
+          </RouterLink>
         ) : undefined,
     },
     ...nextRunStat,
diff --git a/airflow-core/src/airflow/ui/src/pages/Dag/Overview/DeadlineRow.tsx 
b/airflow-core/src/airflow/ui/src/pages/Dag/Overview/DeadlineRow.tsx
index 011530f082c..3e47861c90d 100644
--- a/airflow-core/src/airflow/ui/src/pages/Dag/Overview/DeadlineRow.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Dag/Overview/DeadlineRow.tsx
@@ -16,16 +16,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Badge, HStack, Link, Text, VStack } from "@chakra-ui/react";
+import { Badge, HStack, Text, VStack } from "@chakra-ui/react";
 import dayjs from "dayjs";
 import duration from "dayjs/plugin/duration";
 import relativeTime from "dayjs/plugin/relativeTime";
 import { useTranslation } from "react-i18next";
 import { FiAlertTriangle, FiClock } from "react-icons/fi";
-import { Link as RouterLink } from "react-router-dom";
 
 import type { DeadlineAlertResponse, DeadlineResponse } from 
"openapi/requests/types.gen";
 import Time from "src/components/Time";
+import { RouterLink } from "src/components/ui";
 
 dayjs.extend(duration);
 dayjs.extend(relativeTime);
@@ -53,11 +53,13 @@ export const DeadlineRow = ({ alert, deadline }: 
DeadlineRowProps) => {
             {deadline.missed ? <FiAlertTriangle /> : <FiClock />}
             {translate(deadline.missed ? "deadlineStatus.missed" : 
"deadlineStatus.upcoming")}
           </Badge>
-          <Link asChild color="fg.info" fontSize="sm" fontWeight="bold">
-            <RouterLink 
to={`/dags/${deadline.dag_id}/runs/${deadline.dag_run_id}`}>
-              {deadline.dag_run_id}
-            </RouterLink>
-          </Link>
+          <RouterLink
+            fontSize="sm"
+            fontWeight="bold"
+            to={`/dags/${deadline.dag_id}/runs/${deadline.dag_run_id}`}
+          >
+            {deadline.dag_run_id}
+          </RouterLink>
         </HStack>
         {reference !== undefined && interval !== undefined ? (
           <Text color="fg.muted" fontSize="xs">
diff --git 
a/airflow-core/src/airflow/ui/src/pages/Dag/Overview/TaskLogPreview.tsx 
b/airflow-core/src/airflow/ui/src/pages/Dag/Overview/TaskLogPreview.tsx
index e4ca4e1e966..efd38e01c5f 100644
--- a/airflow-core/src/airflow/ui/src/pages/Dag/Overview/TaskLogPreview.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Dag/Overview/TaskLogPreview.tsx
@@ -16,15 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Box, Flex, Link, Button } from "@chakra-ui/react";
+import { Box, Flex, Button } from "@chakra-ui/react";
 import { useState } from "react";
 import { useTranslation } from "react-i18next";
-import { Link as RouterLink } from "react-router-dom";
 
 import type { TaskInstanceResponse } from "openapi/requests/types.gen";
 import { ClearTaskInstanceButton } from "src/components/Clear";
 import { StateBadge } from "src/components/StateBadge";
 import Time from "src/components/Time";
+import { RouterLink } from "src/components/ui";
 import { TaskLogContent } from "src/pages/TaskInstance/Logs/TaskLogContent";
 import { useLogs } from "src/queries/useLogs";
 import { getTaskInstanceLink } from "src/utils/links";
@@ -73,11 +73,9 @@ export const TaskLogPreview = ({
               : translate("overview.failedLogs.showLogs")}
           </Button>
           <ClearTaskInstanceButton taskInstance={taskInstance} />
-          <Link asChild color="fg.info" fontSize="sm">
-            <RouterLink to={getTaskInstanceLink(taskInstance)}>
-              {translate("overview.failedLogs.viewFullLogs")}
-            </RouterLink>
-          </Link>
+          <RouterLink fontSize="sm" to={getTaskInstanceLink(taskInstance)}>
+            {translate("overview.failedLogs.viewFullLogs")}
+          </RouterLink>
         </Flex>
       </Flex>
       {isExpanded ? (
diff --git a/airflow-core/src/airflow/ui/src/pages/Dag/Tasks/Tasks.tsx 
b/airflow-core/src/airflow/ui/src/pages/Dag/Tasks/Tasks.tsx
index 154e0394a2c..993044dc851 100644
--- a/airflow-core/src/airflow/ui/src/pages/Dag/Tasks/Tasks.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Dag/Tasks/Tasks.tsx
@@ -16,18 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Box, Link } from "@chakra-ui/react";
+import { Box } from "@chakra-ui/react";
 import type { ColumnDef } from "@tanstack/react-table";
 import type { TFunction } from "i18next";
 import { useTranslation } from "react-i18next";
 import { useParams, useSearchParams } from "react-router-dom";
-import { Link as RouterLink } from "react-router-dom";
 
 import { useTaskServiceGetTasks } from "openapi/queries";
 import type { TaskResponse } from "openapi/requests/types.gen";
 import { DataTable } from "src/components/DataTable";
 import { ErrorAlert } from "src/components/ErrorAlert";
 import { TruncatedText } from "src/components/TruncatedText";
+import { RouterLink } from "src/components/ui";
 import { SearchParamsKeys } from "src/constants/searchParams.ts";
 import { TaskFilters } from "src/pages/Dag/Tasks/TaskFilters/TaskFilters.tsx";
 
@@ -43,11 +43,9 @@ const createColumns = ({
   {
     accessorKey: "task_display_name",
     cell: ({ row: { original } }: TaskRow) => (
-      <Link asChild color="fg.info" fontWeight="bold">
-        <RouterLink to={`/dags/${dagId}/tasks/${original.task_id}`}>
-          <TruncatedText text={original.task_display_name ?? original.task_id 
?? ""} />
-        </RouterLink>
-      </Link>
+      <RouterLink fontWeight="bold" 
to={`/dags/${dagId}/tasks/${original.task_id}`}>
+        <TruncatedText text={original.task_display_name ?? original.task_id ?? 
""} />
+      </RouterLink>
     ),
     enableSorting: false,
     header: translate("common:taskId"),
diff --git a/airflow-core/src/airflow/ui/src/pages/DagRuns.tsx 
b/airflow-core/src/airflow/ui/src/pages/DagRuns.tsx
index 11cb870f77c..bc1aa2f3d14 100644
--- a/airflow-core/src/airflow/ui/src/pages/DagRuns.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/DagRuns.tsx
@@ -16,11 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Flex, HStack, Link, Text } from "@chakra-ui/react";
+import { Flex, HStack, Text } from "@chakra-ui/react";
 import type { ColumnDef } from "@tanstack/react-table";
 import type { TFunction } from "i18next";
 import { useTranslation } from "react-i18next";
-import { Link as RouterLink, useParams, useSearchParams } from 
"react-router-dom";
+import { useParams, useSearchParams } from "react-router-dom";
 
 import { useDagRunServiceGetDagRuns } from "openapi/queries";
 import type { DAGRunResponse } from "openapi/requests/types.gen";
@@ -36,6 +36,7 @@ import { RunTypeIcon } from "src/components/RunTypeIcon";
 import { StateBadge } from "src/components/StateBadge";
 import Time from "src/components/Time";
 import { TruncatedText } from "src/components/TruncatedText";
+import { RouterLink } from "src/components/ui";
 import { SearchParamsKeys, type SearchParamsKeysType } from 
"src/constants/searchParams";
 import { useAdvancedSearchArg } from "src/hooks/useAdvancedSearch";
 import { DagRunsFilters } from "src/pages/DagRunsFilters";
@@ -73,11 +74,9 @@ const runColumns = (translate: TFunction, dagId?: string): 
Array<ColumnDef<DAGRu
         {
           accessorKey: "dag_display_name",
           cell: ({ row: { original } }: DagRunRow) => (
-            <Link asChild color="fg.info">
-              <RouterLink to={`/dags/${original.dag_id}`}>
-                <TruncatedText text={original.dag_display_name} />
-              </RouterLink>
-            </Link>
+            <RouterLink to={`/dags/${original.dag_id}`}>
+              <TruncatedText text={original.dag_display_name} />
+            </RouterLink>
           ),
           enableSorting: false,
           header: translate("dagId"),
@@ -86,22 +85,18 @@ const runColumns = (translate: TFunction, dagId?: string): 
Array<ColumnDef<DAGRu
   {
     accessorKey: "dag_run_id",
     cell: ({ row: { original } }: DagRunRow) => (
-      <Link asChild color="fg.info" fontWeight="bold">
-        <RouterLink 
to={`/dags/${original.dag_id}/runs/${original.dag_run_id}`}>
-          <TruncatedText text={original.dag_run_id} />
-        </RouterLink>
-      </Link>
+      <RouterLink fontWeight="bold" 
to={`/dags/${original.dag_id}/runs/${original.dag_run_id}`}>
+        <TruncatedText text={original.dag_run_id} />
+      </RouterLink>
     ),
     header: translate("dagRunId"),
   },
   {
     accessorKey: "run_after",
     cell: ({ row: { original } }: DagRunRow) => (
-      <Link asChild color="fg.info" fontWeight="bold">
-        <RouterLink 
to={`/dags/${original.dag_id}/runs/${original.dag_run_id}`}>
-          <Time datetime={original.run_after} />
-        </RouterLink>
-      </Link>
+      <RouterLink fontWeight="bold" 
to={`/dags/${original.dag_id}/runs/${original.dag_run_id}`}>
+        <Time datetime={original.run_after} />
+      </RouterLink>
     ),
     header: translate("dagRun.runAfter"),
   },
diff --git a/airflow-core/src/airflow/ui/src/pages/DagsList/AssetSchedule.tsx 
b/airflow-core/src/airflow/ui/src/pages/DagsList/AssetSchedule.tsx
index 78536cc1c1a..f57d8e138d8 100644
--- a/airflow-core/src/airflow/ui/src/pages/DagsList/AssetSchedule.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/DagsList/AssetSchedule.tsx
@@ -16,18 +16,17 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Button, HStack, Link, Text } from "@chakra-ui/react";
+import { Button, HStack, Text } from "@chakra-ui/react";
 import dayjs from "dayjs";
 import { useState } from "react";
 import { useTranslation } from "react-i18next";
 import { FiDatabase } from "react-icons/fi";
-import { Link as RouterLink } from "react-router-dom";
 
 import { useAssetServiceGetDagAssetQueuedEvents, useAssetServiceNextRunAssets 
} from "openapi/queries";
 import { AssetExpression, type ExpressionType } from 
"src/components/AssetExpression";
 import type { NextRunEvent } from "src/components/AssetExpression/types";
 import { TruncatedText } from "src/components/TruncatedText";
-import { Popover } from "src/components/ui";
+import { Popover, RouterLink } from "src/components/ui";
 
 import { PartitionScheduleModal } from "./PartitionScheduleModal";
 
@@ -128,11 +127,9 @@ export const AssetSchedule = ({ assetExpression, dagId, 
timetablePartitioned, ti
     return (
       <HStack>
         <FiDatabase style={{ display: "inline", flexShrink: 0 }} />
-        <Link asChild color="fg.info" display="block" fontSize="sm">
-          <RouterLink to={`/assets/${asset.id}`}>
-            <TruncatedText minWidth={0} text={asset.name ?? asset.uri} />
-          </RouterLink>
-        </Link>
+        <RouterLink display="block" fontSize="sm" to={`/assets/${asset.id}`}>
+          <TruncatedText minWidth={0} text={asset.name ?? asset.uri} />
+        </RouterLink>
       </HStack>
     );
   }
diff --git a/airflow-core/src/airflow/ui/src/pages/DagsList/DagCard.tsx 
b/airflow-core/src/airflow/ui/src/pages/DagsList/DagCard.tsx
index b8dbe516b8a..aefe80c5aaa 100644
--- a/airflow-core/src/airflow/ui/src/pages/DagsList/DagCard.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/DagsList/DagCard.tsx
@@ -16,9 +16,8 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Box, Flex, HStack, SimpleGrid, Link, Spinner } from 
"@chakra-ui/react";
+import { Box, Flex, HStack, SimpleGrid, Spinner } from "@chakra-ui/react";
 import { useTranslation } from "react-i18next";
-import { Link as RouterLink } from "react-router-dom";
 
 import type { DAGWithLatestDagRunsResponse } from "openapi/requests/types.gen";
 import { DeleteDagButton } from "src/components/DagActions/DeleteDagButton";
@@ -28,7 +27,7 @@ import { NeedsReviewBadge } from 
"src/components/NeedsReviewBadge";
 import { Stat } from "src/components/Stat";
 import { TogglePause } from "src/components/TogglePause";
 import { TriggerDAGButton } from "src/components/TriggerDag/TriggerDAGButton";
-import { Tooltip } from "src/components/ui";
+import { RouterLink, Tooltip } from "src/components/ui";
 import { isStatePending, useAutoRefresh } from "src/utils";
 
 import { DagTags } from "./DagTags";
@@ -50,11 +49,9 @@ export const DagCard = ({ dag }: Props) => {
       <Flex alignItems="center" bg="bg.muted" justifyContent="space-between" 
px={3} py={1}>
         <HStack>
           <Tooltip content={dag.description} 
disabled={!Boolean(dag.description)}>
-            <Link asChild color="fg.info" fontWeight="bold">
-              <RouterLink data-testid="dag-id" to={`/dags/${dag.dag_id}`}>
-                {dag.dag_display_name}
-              </RouterLink>
-            </Link>
+            <RouterLink color="fg.info" data-testid="dag-id" fontWeight="bold" 
to={`/dags/${dag.dag_id}`}>
+              {dag.dag_display_name}
+            </RouterLink>
           </Tooltip>
           <DagTags tags={dag.tags} />
         </HStack>
@@ -83,20 +80,18 @@ export const DagCard = ({ dag }: Props) => {
         </Stat>
         <Stat data-testid="latest-run" 
label={translate("dagDetails.latestRun")}>
           {latestRun ? (
-            <Link asChild color="fg.info">
-              <RouterLink 
to={`/dags/${latestRun.dag_id}/runs/${latestRun.run_id}`}>
-                <DagRunInfo
-                  endDate={latestRun.end_date}
-                  logicalDate={latestRun.logical_date}
-                  runAfter={latestRun.run_after}
-                  startDate={latestRun.start_date}
-                  state={latestRun.state}
-                />
-                {isStatePending(latestRun.state) && !dag.is_paused && 
Boolean(refetchInterval) ? (
-                  <Spinner />
-                ) : undefined}
-              </RouterLink>
-            </Link>
+            <RouterLink 
to={`/dags/${latestRun.dag_id}/runs/${latestRun.run_id}`}>
+              <DagRunInfo
+                endDate={latestRun.end_date}
+                logicalDate={latestRun.logical_date}
+                runAfter={latestRun.run_after}
+                startDate={latestRun.start_date}
+                state={latestRun.state}
+              />
+              {isStatePending(latestRun.state) && !dag.is_paused && 
Boolean(refetchInterval) ? (
+                <Spinner />
+              ) : undefined}
+            </RouterLink>
           ) : undefined}
         </Stat>
         <Stat data-testid="next-run" label={translate("dagDetails.nextRun")}>
diff --git a/airflow-core/src/airflow/ui/src/pages/DagsList/DagOwners.tsx 
b/airflow-core/src/airflow/ui/src/pages/DagsList/DagOwners.tsx
index e4102eb22de..c0049c224f6 100644
--- a/airflow-core/src/airflow/ui/src/pages/DagsList/DagOwners.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/DagsList/DagOwners.tsx
@@ -18,9 +18,9 @@
  */
 import { Link } from "@chakra-ui/react";
 import { useTranslation } from "react-i18next";
-import { Link as RouterLink } from "react-router-dom";
 
 import { LimitedItemsList } from "src/components/LimitedItemsList";
+import { RouterLink } from "src/components/ui";
 import { getSafeExternalUrl } from "src/utils/links";
 
 const DEFAULT_OWNERS: Array<string> = [];
@@ -52,9 +52,9 @@ export const DagOwners = ({
         {owner}
       </Link>
     ) : (
-      <Link asChild color="fg.info" key={owner}>
-        <RouterLink to={ownerFilterLink}>{owner}</RouterLink>
-      </Link>
+      <RouterLink key={owner} to={ownerFilterLink}>
+        {owner}
+      </RouterLink>
     );
   });
 
diff --git a/airflow-core/src/airflow/ui/src/pages/DagsList/DagTags.tsx 
b/airflow-core/src/airflow/ui/src/pages/DagsList/DagTags.tsx
index 01a0a207cf3..d978b558705 100644
--- a/airflow-core/src/airflow/ui/src/pages/DagsList/DagTags.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/DagsList/DagTags.tsx
@@ -16,12 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Link } from "@chakra-ui/react";
 import { FiTag } from "react-icons/fi";
-import { Link as RouterLink } from "react-router-dom";
 
 import type { DagTagResponse } from "openapi/requests/types.gen";
 import { LimitedItemsList } from "src/components/LimitedItemsList";
+import { RouterLink } from "src/components/ui";
 import { SearchParamsKeys } from "src/constants/searchParams";
 
 const MAX_TAGS = 3;
@@ -36,9 +35,9 @@ export const DagTags = ({ hideIcon = false, tags }: Props) => 
(
     icon={hideIcon ? undefined : <FiTag data-testid="dag-tag" />}
     interactive
     items={tags.map(({ name }) => (
-      <Link asChild color="fg.info" key={name}>
-        <RouterLink 
to={`/dags?${SearchParamsKeys.TAGS}=${encodeURIComponent(name)}`}>{name}</RouterLink>
-      </Link>
+      <RouterLink key={name} 
to={`/dags?${SearchParamsKeys.TAGS}=${encodeURIComponent(name)}`}>
+        {name}
+      </RouterLink>
     ))}
     maxItems={MAX_TAGS}
   />
diff --git a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx 
b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx
index deda3679f65..29af6d24f28 100644
--- a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx
@@ -16,18 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import {
-  Heading,
-  HStack,
-  Skeleton,
-  VStack,
-  Link,
-  type SelectValueChangeDetails,
-  Box,
-} from "@chakra-ui/react";
+import { Heading, HStack, Skeleton, VStack, type SelectValueChangeDetails, Box 
} from "@chakra-ui/react";
 import type { ColumnDef } from "@tanstack/react-table";
 import { useTranslation } from "react-i18next";
-import { Link as RouterLink, useSearchParams } from "react-router-dom";
+import { useSearchParams } from "react-router-dom";
 import { useLocalStorage } from "usehooks-ts";
 
 import type { DagRunState, DAGWithLatestDagRunsResponse } from 
"openapi/requests/types.gen";
@@ -42,6 +34,7 @@ import { NeedsReviewBadge } from 
"src/components/NeedsReviewBadge";
 import { SearchBar } from "src/components/SearchBar";
 import { TogglePause } from "src/components/TogglePause";
 import { TriggerDAGButton } from "src/components/TriggerDag/TriggerDAGButton";
+import { RouterLink } from "src/components/ui";
 import { DAGS_LIST_DISPLAY_KEY } from "src/constants/localStorage";
 import { SearchParamsKeys, type SearchParamsKeysType } from 
"src/constants/searchParams";
 import { useAdvancedSearch } from "src/hooks/useAdvancedSearch";
@@ -78,9 +71,9 @@ const createColumns = (
   {
     accessorKey: "dag_display_name",
     cell: ({ row: { original } }) => (
-      <Link asChild color="fg.info" fontWeight="bold">
-        <RouterLink 
to={`/dags/${original.dag_id}`}>{original.dag_display_name}</RouterLink>
-      </Link>
+      <RouterLink fontWeight="bold" to={`/dags/${original.dag_id}`}>
+        {original.dag_display_name}
+      </RouterLink>
     ),
     header: () => translate("dagId"),
   },
@@ -113,17 +106,18 @@ const createColumns = (
     accessorKey: "last_run_start_date",
     cell: ({ row: { original } }) =>
       original.latest_dag_runs[0] ? (
-        <Link asChild color="fg.info" fontWeight="bold">
-          <RouterLink 
to={`/dags/${original.dag_id}/runs/${original.latest_dag_runs[0].run_id}`}>
-            <DagRunInfo
-              endDate={original.latest_dag_runs[0].end_date}
-              logicalDate={original.latest_dag_runs[0].logical_date}
-              runAfter={original.latest_dag_runs[0].run_after}
-              startDate={original.latest_dag_runs[0].start_date}
-              state={original.latest_dag_runs[0].state}
-            />
-          </RouterLink>
-        </Link>
+        <RouterLink
+          fontWeight="bold"
+          
to={`/dags/${original.dag_id}/runs/${original.latest_dag_runs[0].run_id}`}
+        >
+          <DagRunInfo
+            endDate={original.latest_dag_runs[0].end_date}
+            logicalDate={original.latest_dag_runs[0].logical_date}
+            runAfter={original.latest_dag_runs[0].run_after}
+            startDate={original.latest_dag_runs[0].start_date}
+            state={original.latest_dag_runs[0].state}
+          />
+        </RouterLink>
       ) : undefined,
     header: () => translate("dagDetails.latestRun"),
   },
diff --git 
a/airflow-core/src/airflow/ui/src/pages/Dashboard/PoolSummary/PoolSummary.tsx 
b/airflow-core/src/airflow/ui/src/pages/Dashboard/PoolSummary/PoolSummary.tsx
index 9955ad82a8d..b306bcfe3cd 100644
--- 
a/airflow-core/src/airflow/ui/src/pages/Dashboard/PoolSummary/PoolSummary.tsx
+++ 
b/airflow-core/src/airflow/ui/src/pages/Dashboard/PoolSummary/PoolSummary.tsx
@@ -16,15 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Box, Heading, Flex, Skeleton, Link } from "@chakra-ui/react";
+import { Box, Heading, Flex, Skeleton } from "@chakra-ui/react";
 import { useTranslation } from "react-i18next";
 import { BiTargetLock } from "react-icons/bi";
-import { Link as RouterLink } from "react-router-dom";
 
 import { type PoolServiceGetPoolsDefaultResponse, 
useAuthLinksServiceGetAuthMenus } from "openapi/queries";
 import { usePoolServiceGetPools } from "openapi/queries/queries";
 import type { ApiError } from "openapi/requests";
 import { PoolBar, UNLIMITED_SLOTS } from "src/components/PoolBar";
+import { RouterLink } from "src/components/ui";
 import { useAutoRefresh } from "src/utils";
 import { type Slots, slotKeys } from "src/utils/slots";
 
@@ -98,9 +98,9 @@ export const PoolSummary = () => {
           </Heading>
         </Flex>
         {hasPoolsAccess ? (
-          <Link asChild color="fg.info" fontSize="xs" h={4}>
-            <RouterLink to="/pools">{translate("managePools")}</RouterLink>
-          </Link>
+          <RouterLink fontSize="xs" h={4} to="/pools">
+            {translate("managePools")}
+          </RouterLink>
         ) : undefined}
       </Flex>
 
diff --git 
a/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLTaskInstances.tsx 
b/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLTaskInstances.tsx
index 4538bc204af..e9e0e86e4d2 100644
--- 
a/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLTaskInstances.tsx
+++ 
b/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLTaskInstances.tsx
@@ -16,11 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Link, VStack } from "@chakra-ui/react";
+import { VStack } from "@chakra-ui/react";
 import type { ColumnDef } from "@tanstack/react-table";
 import type { TFunction } from "i18next";
 import { useTranslation } from "react-i18next";
-import { Link as RouterLink, useParams, useSearchParams } from 
"react-router-dom";
+import { useParams, useSearchParams } from "react-router-dom";
 
 import { useTaskInstanceServiceGetHitlDetails } from "openapi/queries";
 import type { HITLDetail } from "openapi/requests/types.gen";
@@ -30,6 +30,7 @@ import { ErrorAlert } from "src/components/ErrorAlert";
 import { StateBadge } from "src/components/StateBadge";
 import Time from "src/components/Time";
 import { TruncatedText } from "src/components/TruncatedText";
+import { RouterLink } from "src/components/ui";
 import { SearchParamsKeys, type SearchParamsKeysType } from 
"src/constants/searchParams";
 import { useAdvancedSearchArg } from "src/hooks/useAdvancedSearch";
 import { useAutoRefresh } from "src/utils";
@@ -74,11 +75,9 @@ const taskInstanceColumns = ({
   {
     accessorKey: "subject",
     cell: ({ row: { original } }: HITLRow) => (
-      <Link asChild color="fg.info" fontWeight="bold">
-        <RouterLink 
to={`${getTaskInstanceLink(original.task_instance)}/required_actions`}>
-          <TruncatedText text={original.subject} />
-        </RouterLink>
-      </Link>
+      <RouterLink fontWeight="bold" 
to={`${getTaskInstanceLink(original.task_instance)}/required_actions`}>
+        <TruncatedText text={original.subject} />
+      </RouterLink>
     ),
     header: translate("subject"),
   },
@@ -88,11 +87,9 @@ const taskInstanceColumns = ({
         {
           accessorKey: "task_instance.dag_id",
           cell: ({ row: { original } }: HITLRow) => (
-            <Link asChild color="fg.info">
-              <RouterLink to={`/dags/${original.task_instance.dag_id}`}>
-                <TruncatedText text={original.task_instance.dag_display_name} 
/>
-              </RouterLink>
-            </Link>
+            <RouterLink to={`/dags/${original.task_instance.dag_id}`}>
+              <TruncatedText text={original.task_instance.dag_display_name} />
+            </RouterLink>
           ),
           enableSorting: false,
           header: translate("common:dagId"),
@@ -104,13 +101,11 @@ const taskInstanceColumns = ({
         {
           accessorKey: "run_id",
           cell: ({ row: { original } }: HITLRow) => (
-            <Link asChild color="fg.info">
-              <RouterLink
-                
to={`/dags/${original.task_instance.dag_id}/runs/${original.task_instance.dag_run_id}`}
-              >
-                <TruncatedText text={original.task_instance.dag_run_id} />
-              </RouterLink>
-            </Link>
+            <RouterLink
+              
to={`/dags/${original.task_instance.dag_id}/runs/${original.task_instance.dag_run_id}`}
+            >
+              <TruncatedText text={original.task_instance.dag_run_id} />
+            </RouterLink>
           ),
           header: translate("common:dagRunId"),
         },
@@ -130,11 +125,12 @@ const taskInstanceColumns = ({
         {
           accessorKey: "task_display_name",
           cell: ({ row: { original } }: HITLRow) => (
-            <Link asChild color="fg.info" fontWeight="bold">
-              <RouterLink 
to={`${getTaskInstanceLink(original.task_instance)}/required_actions`}>
-                <TruncatedText text={original.task_instance.task_display_name} 
/>
-              </RouterLink>
-            </Link>
+            <RouterLink
+              fontWeight="bold"
+              
to={`${getTaskInstanceLink(original.task_instance)}/required_actions`}
+            >
+              <TruncatedText text={original.task_instance.task_display_name} />
+            </RouterLink>
           ),
           header: translate("common:taskId"),
         },
diff --git a/airflow-core/src/airflow/ui/src/pages/Run/Header.tsx 
b/airflow-core/src/airflow/ui/src/pages/Run/Header.tsx
index 6b29ba51873..3f83146927c 100644
--- a/airflow-core/src/airflow/ui/src/pages/Run/Header.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Run/Header.tsx
@@ -16,11 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { HStack, Text, Box, Link } from "@chakra-ui/react";
+import { HStack, Text, Box } from "@chakra-ui/react";
 import { useState } from "react";
 import { useTranslation } from "react-i18next";
 import { FiBarChart } from "react-icons/fi";
-import { Link as RouterLink } from "react-router-dom";
 
 import { useDeadlinesServiceGetDagDeadlineAlerts } from "openapi/queries";
 import type { DAGRunResponse } from "openapi/requests/types.gen";
@@ -32,6 +31,7 @@ import { LimitedItemsList } from 
"src/components/LimitedItemsList";
 import { MarkRunAsButton } from "src/components/MarkAs";
 import { RunTypeIcon } from "src/components/RunTypeIcon";
 import Time from "src/components/Time";
+import { RouterLink } from "src/components/ui";
 import { SearchParamsKeys } from "src/constants/searchParams";
 import DeleteRunButton from "src/pages/DeleteRunButton";
 import { usePatchDagRun } from "src/queries/usePatchDagRun";
@@ -124,13 +124,11 @@ export const Header = ({ dagRun }: { readonly dagRun: 
DAGRunResponse }) => {
                 {
                   label: translate("dagRun.triggeringUser"),
                   value: (
-                    <Link asChild color="fg.info">
-                      <RouterLink
-                        
to={`/dag_runs?${SearchParamsKeys.TRIGGERING_USER_NAME_PATTERN}=${encodeURIComponent(dagRun.triggering_user_name)}`}
-                      >
-                        <Text>{dagRun.triggering_user_name}</Text>
-                      </RouterLink>
-                    </Link>
+                    <RouterLink
+                      
to={`/dag_runs?${SearchParamsKeys.TRIGGERING_USER_NAME_PATTERN}=${encodeURIComponent(dagRun.triggering_user_name)}`}
+                    >
+                      <Text>{dagRun.triggering_user_name}</Text>
+                    </RouterLink>
                   ),
                 },
               ]),
diff --git 
a/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx 
b/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx
index 2f75a9ab0ca..e2a56737768 100644
--- a/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx
@@ -16,11 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Flex, Link } from "@chakra-ui/react";
+import { Flex } from "@chakra-ui/react";
 import type { ColumnDef } from "@tanstack/react-table";
 import type { TFunction } from "i18next";
 import { useTranslation } from "react-i18next";
-import { Link as RouterLink, useParams, useSearchParams } from 
"react-router-dom";
+import { useParams, useSearchParams } from "react-router-dom";
 
 import { useTaskInstanceServiceGetTaskInstances } from "openapi/queries";
 import type { TaskInstanceResponse } from "openapi/requests/types.gen";
@@ -34,6 +34,7 @@ import { MarkTaskInstanceAsButton } from 
"src/components/MarkAs";
 import { StateBadge } from "src/components/StateBadge";
 import Time from "src/components/Time";
 import { TruncatedText } from "src/components/TruncatedText";
+import { RouterLink } from "src/components/ui";
 import { ActionBar } from "src/components/ui/ActionBar";
 import { Checkbox } from "src/components/ui/Checkbox";
 import { SearchParamsKeys, type SearchParamsKeysType } from 
"src/constants/searchParams";
@@ -117,11 +118,9 @@ const taskInstanceColumns = ({
         {
           accessorKey: "dag_display_name",
           cell: ({ row: { original } }: TaskInstanceRow) => (
-            <Link asChild color="fg.info">
-              <RouterLink to={`/dags/${original.dag_id}`}>
-                <TruncatedText text={original.dag_display_name} />
-              </RouterLink>
-            </Link>
+            <RouterLink to={`/dags/${original.dag_id}`}>
+              <TruncatedText text={original.dag_display_name} />
+            </RouterLink>
           ),
           enableSorting: false,
           header: translate("dagId"),
@@ -134,11 +133,9 @@ const taskInstanceColumns = ({
           accessorKey: "run_after",
           cell: ({ row: { original } }: TaskInstanceRow) =>
             Boolean(taskId) ? (
-              <Link asChild color="fg.info" fontWeight="bold">
-                <RouterLink to={getTaskInstanceLink(original)}>
-                  <Time datetime={original.run_after} />
-                </RouterLink>
-              </Link>
+              <RouterLink fontWeight="bold" to={getTaskInstanceLink(original)}>
+                <Time datetime={original.run_after} />
+              </RouterLink>
             ) : (
               <Time datetime={original.run_after} />
             ),
@@ -151,11 +148,9 @@ const taskInstanceColumns = ({
         {
           accessorKey: "task_display_name",
           cell: ({ row: { original } }: TaskInstanceRow) => (
-            <Link asChild color="fg.info" fontWeight="bold">
-              <RouterLink to={getTaskInstanceLink(original)}>
-                <TruncatedText text={original.task_display_name} />
-              </RouterLink>
-            </Link>
+            <RouterLink fontWeight="bold" to={getTaskInstanceLink(original)}>
+              <TruncatedText text={original.task_display_name} />
+            </RouterLink>
           ),
           enableSorting: false,
           header: translate("taskId"),
@@ -182,11 +177,9 @@ const taskInstanceColumns = ({
     accessorKey: "start_date",
     cell: ({ row: { original } }) =>
       Boolean(taskId) && Boolean(runId) ? (
-        <Link asChild color="fg.info" fontWeight="bold">
-          <RouterLink to={getTaskInstanceLink(original)}>
-            <Time datetime={original.start_date} />
-          </RouterLink>
-        </Link>
+        <RouterLink fontWeight="bold" to={getTaskInstanceLink(original)}>
+          <Time datetime={original.start_date} />
+        </RouterLink>
       ) : (
         <Time datetime={original.start_date} />
       ),
diff --git a/airflow-core/src/airflow/ui/src/pages/XCom/XCom.tsx 
b/airflow-core/src/airflow/ui/src/pages/XCom/XCom.tsx
index c9465ab3c3e..cecc75f7bbb 100644
--- a/airflow-core/src/airflow/ui/src/pages/XCom/XCom.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/XCom/XCom.tsx
@@ -16,10 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Box, Flex, Heading, Link, useDisclosure } from "@chakra-ui/react";
+import { Box, Flex, Heading, useDisclosure } from "@chakra-ui/react";
 import type { ColumnDef } from "@tanstack/react-table";
 import { useTranslation } from "react-i18next";
-import { Link as RouterLink, useParams, useSearchParams } from 
"react-router-dom";
+import { useParams, useSearchParams } from "react-router-dom";
 
 import { useXcomServiceGetXcomEntries } from "openapi/queries";
 import type { XComResponse } from "openapi/requests/types.gen";
@@ -29,6 +29,7 @@ import { ErrorAlert } from "src/components/ErrorAlert";
 import { ExpandCollapseButtons } from "src/components/ExpandCollapseButtons";
 import Time from "src/components/Time";
 import { TruncatedText } from "src/components/TruncatedText";
+import { RouterLink } from "src/components/ui";
 import { SearchParamsKeys, type SearchParamsKeysType } from 
"src/constants/searchParams";
 import { useAdvancedSearchArg } from "src/hooks/useAdvancedSearch";
 import { getTaskInstanceLink } from "src/utils/links";
@@ -60,49 +61,44 @@ const getColumns = ({ open, translate }: ColumnsProps): 
Array<ColumnDef<XComResp
   {
     accessorKey: "dag_id",
     cell: ({ row: { original } }) => (
-      <Link asChild color="fg.info" fontWeight="bold">
-        <RouterLink 
to={`/dags/${original.dag_id}`}>{original.dag_display_name}</RouterLink>
-      </Link>
+      <RouterLink fontWeight="bold" to={`/dags/${original.dag_id}`}>
+        {original.dag_display_name}
+      </RouterLink>
     ),
     header: translate("xcom.columns.dag"),
   },
   {
     accessorKey: "run_id",
     cell: ({ row: { original } }: { row: { original: XComResponse } }) => (
-      <Link asChild color="fg.info" fontWeight="bold">
-        <RouterLink to={`/dags/${original.dag_id}/runs/${original.run_id}`}>
-          <TruncatedText text={original.run_id} />
-        </RouterLink>
-      </Link>
+      <RouterLink fontWeight="bold" 
to={`/dags/${original.dag_id}/runs/${original.run_id}`}>
+        <TruncatedText text={original.run_id} />
+      </RouterLink>
     ),
     header: translate("common:dagRunId"),
   },
   {
     accessorKey: "run_after",
     cell: ({ row: { original } }: { row: { original: XComResponse } }) => (
-      <Link asChild color="fg.info" fontWeight="bold">
-        <RouterLink to={`/dags/${original.dag_id}/runs/${original.run_id}`}>
-          <Time datetime={original.run_after} />
-        </RouterLink>
-      </Link>
+      <RouterLink fontWeight="bold" 
to={`/dags/${original.dag_id}/runs/${original.run_id}`}>
+        <Time datetime={original.run_after} />
+      </RouterLink>
     ),
     header: translate("common:dagRun.runAfter"),
   },
   {
     accessorKey: "task_display_name",
     cell: ({ row: { original } }: { row: { original: XComResponse } }) => (
-      <Link asChild color="fg.info" fontWeight="bold">
-        <RouterLink
-          to={getTaskInstanceLink({
-            dagId: original.dag_id,
-            dagRunId: original.run_id,
-            mapIndex: original.map_index,
-            taskId: original.task_id,
-          })}
-        >
-          <TruncatedText text={original.task_display_name} />
-        </RouterLink>
-      </Link>
+      <RouterLink
+        fontWeight="bold"
+        to={getTaskInstanceLink({
+          dagId: original.dag_id,
+          dagRunId: original.run_id,
+          mapIndex: original.map_index,
+          taskId: original.task_id,
+        })}
+      >
+        <TruncatedText text={original.task_display_name} />
+      </RouterLink>
     ),
     header: translate("common:task_one"),
   },

Reply via email to