This is an automated email from the ASF dual-hosted git repository. kaxilnaik pushed a commit to branch v3-1-test in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 03d75acd4a561cfc8cf4832dec263a5ef07d20f1 Author: Shahar Epstein <[email protected]> AuthorDate: Sat Sep 13 11:29:06 2025 +0300 Fix alignment of arrows in RTL mode (#55619) (cherry picked from commit 7d02b8528892533550d35e0e367f6101c81d9292) --- .../src/airflow/ui/src/components/NeedsReviewButton.tsx | 5 ++++- airflow-core/src/airflow/ui/src/components/StatsCard.tsx | 6 ++++-- .../airflow/ui/src/layouts/Nav/UserSettingsButton.tsx | 16 +++++++++++++--- .../ui/src/pages/Dashboard/Stats/DAGImportErrors.tsx | 5 ++++- .../src/airflow/ui/src/pages/Dashboard/Stats/Stats.tsx | 8 +++++++- 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/airflow-core/src/airflow/ui/src/components/NeedsReviewButton.tsx b/airflow-core/src/airflow/ui/src/components/NeedsReviewButton.tsx index 646bca0bca6..78b246f3e36 100644 --- a/airflow-core/src/airflow/ui/src/components/NeedsReviewButton.tsx +++ b/airflow-core/src/airflow/ui/src/components/NeedsReviewButton.tsx @@ -41,7 +41,9 @@ export const NeedsReviewButton = ({ }); const hitlTIsCount = hitlStatsData?.hitl_details.length ?? 0; - const { t: translate } = useTranslation("hitl"); + const { i18n, t: translate } = useTranslation("hitl"); + + const isRTL = i18n.dir() === "rtl"; return hitlTIsCount > 0 ? ( <Box maxW="250px"> @@ -50,6 +52,7 @@ export const NeedsReviewButton = ({ count={hitlTIsCount} icon={<LuUserRoundPen />} isLoading={isLoading} + isRTL={isRTL} label={translate("requiredAction_other")} link="required_actions?response_received=false" /> diff --git a/airflow-core/src/airflow/ui/src/components/StatsCard.tsx b/airflow-core/src/airflow/ui/src/components/StatsCard.tsx index 7d7bf9c14b4..cbade7d249d 100644 --- a/airflow-core/src/airflow/ui/src/components/StatsCard.tsx +++ b/airflow-core/src/airflow/ui/src/components/StatsCard.tsx @@ -17,7 +17,7 @@ * under the License. */ import { Box, HStack, Skeleton, Text } from "@chakra-ui/react"; -import { FiChevronRight } from "react-icons/fi"; +import { FiChevronRight, FiChevronLeft } from "react-icons/fi"; import { Link as RouterLink } from "react-router-dom"; import type { TaskInstanceState } from "openapi/requests/types.gen"; @@ -28,6 +28,7 @@ export const StatsCard = ({ count, icon, isLoading = false, + isRTL, label, link, onClick, @@ -37,6 +38,7 @@ export const StatsCard = ({ readonly count: number; readonly icon?: React.ReactNode; readonly isLoading?: boolean; + readonly isRTL: boolean; readonly label: string; readonly link?: string; readonly onClick?: () => void; @@ -63,7 +65,7 @@ export const StatsCard = ({ <Text color="fg" fontSize="sm" fontWeight="bold"> {label} </Text> - <FiChevronRight size={16} /> + {isRTL ? <FiChevronLeft size={16} /> : <FiChevronRight size={16} />} </HStack> ); diff --git a/airflow-core/src/airflow/ui/src/layouts/Nav/UserSettingsButton.tsx b/airflow-core/src/airflow/ui/src/layouts/Nav/UserSettingsButton.tsx index a2b99016d91..c8cc8108945 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Nav/UserSettingsButton.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Nav/UserSettingsButton.tsx @@ -27,6 +27,7 @@ import { FiGlobe, FiEye, FiChevronRight, + FiChevronLeft, FiMonitor, } from "react-icons/fi"; import { MdOutlineAccountTree } from "react-icons/md"; @@ -52,7 +53,7 @@ const COLOR_MODES = { type ColorMode = (typeof COLOR_MODES)[keyof typeof COLOR_MODES]; export const UserSettingsButton = ({ externalViews }: { readonly externalViews: Array<NavItemResponse> }) => { - const { t: translate } = useTranslation(); + const { i18n, t: translate } = useTranslation(); const { selectedTheme, setColorMode } = useColorMode(); const { onClose: onCloseTimezone, onOpen: onOpenTimezone, open: isOpenTimezone } = useDisclosure(); const { onClose: onCloseLogout, onOpen: onOpenLogout, open: isOpenLogout } = useDisclosure(); @@ -61,6 +62,8 @@ export const UserSettingsButton = ({ externalViews }: { readonly externalViews: const theme = selectedTheme ?? COLOR_MODES.SYSTEM; + const isRTL = i18n.dir() === "rtl"; + return ( <Menu.Root positioning={{ placement: "right" }}> <Menu.Trigger asChild> @@ -75,7 +78,11 @@ export const UserSettingsButton = ({ externalViews }: { readonly externalViews: <Menu.TriggerItem> <FiEye size="1.25rem" style={{ marginRight: "8px" }} /> {translate("appearance.appearance")} - <FiChevronRight size="1.25rem" style={{ marginLeft: "auto" }} /> + {isRTL ? ( + <FiChevronLeft size="1.25rem" style={{ marginRight: "auto" }} /> + ) : ( + <FiChevronRight size="1.25rem" style={{ marginLeft: "auto" }} /> + )} </Menu.TriggerItem> <Menu.Content> <Menu.RadioItemGroup @@ -121,7 +128,10 @@ export const UserSettingsButton = ({ externalViews }: { readonly externalViews: <PluginMenuItem {...view} key={view.name} /> ))} <Menu.Item onClick={onOpenLogout} value="logout"> - <FiLogOut size="1.25rem" style={{ marginRight: "8px" }} /> + <FiLogOut + size="1.25rem" + style={{ marginRight: "8px", transform: isRTL ? "rotate(180deg)" : undefined }} + /> {translate("logout")} </Menu.Item> </Menu.Content> diff --git a/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/DAGImportErrors.tsx b/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/DAGImportErrors.tsx index 079472cf353..2966fee23cd 100644 --- a/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/DAGImportErrors.tsx +++ b/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/DAGImportErrors.tsx @@ -29,7 +29,9 @@ import { DAGImportErrorsModal } from "./DAGImportErrorsModal"; export const DAGImportErrors = ({ iconOnly = false }: { readonly iconOnly?: boolean }) => { const { onClose, onOpen, open } = useDisclosure(); - const { t: translate } = useTranslation("dashboard"); + const { i18n, t: translate } = useTranslation("dashboard"); + + const isRTL = i18n.dir() === "rtl"; const { data, error, isLoading } = useImportErrorServiceGetImportErrors(); const importErrorsCount = data?.total_entries ?? 0; @@ -63,6 +65,7 @@ export const DAGImportErrors = ({ iconOnly = false }: { readonly iconOnly?: bool count={importErrorsCount} icon={<LuFileWarning />} isLoading={isLoading} + isRTL={isRTL} label={translate("importErrors.dagImportError", { count: importErrorsCount })} onClick={onOpen} /> diff --git a/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/Stats.tsx b/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/Stats.tsx index b766cd12b4f..5cfc7b2d7c2 100644 --- a/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/Stats.tsx +++ b/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/Stats.tsx @@ -38,7 +38,9 @@ export const Stats = () => { const queuedDagsCount = statsData?.queued_dag_count ?? 0; const runningDagsCount = statsData?.running_dag_count ?? 0; const activeDagsCount = statsData?.active_dag_count ?? 0; - const { t: translate } = useTranslation("dashboard"); + const { i18n, t: translate } = useTranslation("dashboard"); + + const isRTL = i18n.dir() === "rtl"; return ( <Box> @@ -56,6 +58,7 @@ export const Stats = () => { colorScheme="failed" count={failedDagsCount} isLoading={isStatsLoading} + isRTL={isRTL} label={translate("stats.failedDags")} link="dags?last_dag_run_state=failed" state="failed" @@ -70,6 +73,7 @@ export const Stats = () => { colorScheme="queued" count={queuedDagsCount} isLoading={isStatsLoading} + isRTL={isRTL} label={translate("stats.queuedDags")} link="dags?last_dag_run_state=queued" state="queued" @@ -80,6 +84,7 @@ export const Stats = () => { colorScheme="running" count={runningDagsCount} isLoading={isStatsLoading} + isRTL={isRTL} label={translate("stats.runningDags")} link="dags?last_dag_run_state=running" state="running" @@ -90,6 +95,7 @@ export const Stats = () => { count={activeDagsCount} icon={<FiZap />} isLoading={isStatsLoading} + isRTL={isRTL} label={translate("stats.activeDags")} link="dags?paused=false" />
