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

ephraimanierobi pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git

commit 507db91c6f8924af95f9b5114f24b0ca88bdad69
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri Jan 9 11:11:42 2026 -0500

    [v3-1-test] Move dags list filters to buttongroups (#60298) (#60337)
    
    (cherry picked from commit cd3b6b4578792b4fb172ad22b101da85a51eb3aa)
    
    Co-authored-by: Brent Bovenzi <[email protected]>
---
 .../components/DataTable/ToggleTableDisplay.tsx    | 58 +++++++------------
 .../src/pages/DagsList/DagsFilters/DagsFilters.tsx | 60 ++++++++++----------
 .../pages/DagsList/DagsFilters/FavoriteFilter.tsx  | 66 +++++++++++++---------
 .../pages/DagsList/DagsFilters/PausedFilter.tsx    | 59 ++++++++++---------
 .../pages/DagsList/DagsFilters/StateFilters.tsx    | 57 ++++++++++++-------
 .../src/pages/DagsList/DagsFilters/TagFilter.tsx   |  1 +
 6 files changed, 158 insertions(+), 143 deletions(-)

diff --git 
a/airflow-core/src/airflow/ui/src/components/DataTable/ToggleTableDisplay.tsx 
b/airflow-core/src/airflow/ui/src/components/DataTable/ToggleTableDisplay.tsx
index feb072f8677..75e336d615f 100644
--- 
a/airflow-core/src/airflow/ui/src/components/DataTable/ToggleTableDisplay.tsx
+++ 
b/airflow-core/src/airflow/ui/src/components/DataTable/ToggleTableDisplay.tsx
@@ -16,12 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { HStack, IconButton } from "@chakra-ui/react";
+import { ButtonGroup, IconButton } from "@chakra-ui/react";
 import { useTranslation } from "react-i18next";
 import { FiAlignJustify, FiGrid } from "react-icons/fi";
 
-import { Tooltip } from "src/components/ui";
-
 type Display = "card" | "table";
 
 type Props = {
@@ -33,39 +31,25 @@ export const ToggleTableDisplay = ({ display, setDisplay }: 
Props) => {
   const { t: translate } = useTranslation("components");
 
   return (
-    <HStack colorPalette="brand" gap={1} pb={2}>
-      <Tooltip content={translate("toggleCardView")}>
-        <IconButton
-          _hover={{ bg: "colorPalette.emphasized" }}
-          aria-label={translate("toggleCardView")}
-          bg={display === "card" ? "colorPalette.muted" : "bg"}
-          borderColor="border.emphasized"
-          borderWidth={1}
-          color="colorPalette.fg"
-          height={8}
-          minWidth={8}
-          onClick={() => setDisplay("card")}
-          width={8}
-        >
-          <FiGrid />
-        </IconButton>
-      </Tooltip>
-      <Tooltip content={translate("toggleTableView")}>
-        <IconButton
-          _hover={{ bg: "colorPalette.emphasized" }}
-          aria-label={translate("toggleTableView")}
-          bg={display === "table" ? "colorPalette.muted" : "bg"}
-          borderColor="border.emphasized"
-          borderWidth={1}
-          color="colorPalette.fg"
-          height={8}
-          minWidth={8}
-          onClick={() => setDisplay("table")}
-          width={8}
-        >
-          <FiAlignJustify />
-        </IconButton>
-      </Tooltip>
-    </HStack>
+    <ButtonGroup attached colorPalette="brand" pb={2} size="sm" 
variant="outline">
+      <IconButton
+        aria-label={translate("toggleCardView")}
+        bg={display === "card" ? "colorPalette.muted" : undefined}
+        onClick={() => setDisplay("card")}
+        title={translate("toggleCardView")}
+        variant={display === "card" ? "solid" : "outline"}
+      >
+        <FiGrid />
+      </IconButton>
+      <IconButton
+        aria-label={translate("toggleTableView")}
+        bg={display === "table" ? "colorPalette.muted" : undefined}
+        onClick={() => setDisplay("table")}
+        title={translate("toggleTableView")}
+        variant={display === "table" ? "solid" : "outline"}
+      >
+        <FiAlignJustify />
+      </IconButton>
+    </ButtonGroup>
   );
 };
diff --git 
a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/DagsFilters.tsx 
b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/DagsFilters.tsx
index 5b413ab012c..11269d577e9 100644
--- a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/DagsFilters.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/DagsFilters.tsx
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Box, HStack } from "@chakra-ui/react";
+import { Box, Flex } from "@chakra-ui/react";
 import type { MultiValue } from "chakra-react-select";
 import { useCallback, useState } from "react";
 import { useSearchParams } from "react-router-dom";
@@ -72,14 +72,12 @@ export const DagsFilters = () => {
   const { setTableURLState, tableURLState } = useTableURLState();
   const { pagination, sorting } = tableURLState;
 
-  const handlePausedChange = useCallback(
-    ({ value }: { value: Array<string> }) => {
-      const [val] = value;
-
-      if (val === undefined) {
+  const handlePausedChange: React.MouseEventHandler<HTMLButtonElement> = 
useCallback(
+    ({ currentTarget: { value } }) => {
+      if (value === "all") {
         searchParams.delete(PAUSED_PARAM);
       } else {
-        searchParams.set(PAUSED_PARAM, val);
+        searchParams.set(PAUSED_PARAM, value);
       }
       setTableURLState({
         pagination: { ...pagination, pageIndex: 0 },
@@ -91,14 +89,12 @@ export const DagsFilters = () => {
     [pagination, searchParams, setSearchParams, setTableURLState, sorting],
   );
 
-  const handleFavoriteChange = useCallback(
-    ({ value }: { value: Array<string> }) => {
-      const [val] = value;
-
-      if (val === undefined || val === "all") {
+  const handleFavoriteChange: React.MouseEventHandler<HTMLButtonElement> = 
useCallback(
+    ({ currentTarget: { value } }) => {
+      if (value === "all") {
         searchParams.delete(FAVORITE_PARAM);
       } else {
-        searchParams.set(FAVORITE_PARAM, val);
+        searchParams.set(FAVORITE_PARAM, value);
       }
       setTableURLState({
         pagination: { ...pagination, pageIndex: 0 },
@@ -189,8 +185,8 @@ export const DagsFilters = () => {
   });
 
   return (
-    <HStack justifyContent="space-between">
-      <HStack gap={4}>
+    <Flex flexWrap="wrap" gap={4} justifyContent="space-between">
+      <Flex alignItems="center" flexWrap="wrap" gap={4}>
         <StateFilters
           isAll={isAll}
           isFailed={isFailed}
@@ -205,25 +201,27 @@ export const DagsFilters = () => {
           onPausedChange={handlePausedChange}
           showPaused={showPaused}
         />
-        <TagFilter
-          onMenuScrollToBottom={() => {
-            void fetchNextPage();
-          }}
-          onMenuScrollToTop={() => {
-            void fetchPreviousPage();
-          }}
-          onSelectTagsChange={handleSelectTagsChange}
-          onTagModeChange={handleTagModeChange}
-          onUpdate={setPattern}
-          selectedTags={selectedTags}
-          tagFilterMode={tagFilterMode}
-          tags={data?.pages.flatMap((dagResponse) => dagResponse.tags) ?? []}
-        />
+        <Box maxWidth="300px">
+          <TagFilter
+            onMenuScrollToBottom={() => {
+              void fetchNextPage();
+            }}
+            onMenuScrollToTop={() => {
+              void fetchPreviousPage();
+            }}
+            onSelectTagsChange={handleSelectTagsChange}
+            onTagModeChange={handleTagModeChange}
+            onUpdate={setPattern}
+            selectedTags={selectedTags}
+            tagFilterMode={tagFilterMode}
+            tags={data?.pages.flatMap((dagResponse) => dagResponse.tags) ?? []}
+          />
+        </Box>
         <FavoriteFilter onFavoriteChange={handleFavoriteChange} 
showFavorites={showFavorites} />
-      </HStack>
+      </Flex>
       <Box>
         <ResetButton filterCount={filterCount} onClearFilters={onClearFilters} 
/>
       </Box>
-    </HStack>
+    </Flex>
   );
 };
diff --git 
a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/FavoriteFilter.tsx 
b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/FavoriteFilter.tsx
index 5e8bcd93cd9..3554658f98d 100644
--- 
a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/FavoriteFilter.tsx
+++ 
b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/FavoriteFilter.tsx
@@ -16,43 +16,55 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { createListCollection, type SelectValueChangeDetails } from 
"@chakra-ui/react";
+import { Button, ButtonGroup, Icon } from "@chakra-ui/react";
 import { useTranslation } from "react-i18next";
-
-import { Select } from "src/components/ui";
+import { FiStar } from "react-icons/fi";
 
 type Props = {
-  readonly onFavoriteChange: (details: SelectValueChangeDetails<string>) => 
void;
+  readonly onFavoriteChange: React.MouseEventHandler<HTMLButtonElement>;
   readonly showFavorites: string | null;
 };
 
 export const FavoriteFilter = ({ onFavoriteChange, showFavorites }: Props) => {
   const { t: translate } = useTranslation("dags");
 
-  const enabledOptions = createListCollection({
-    items: [
-      { label: translate("filters.favorite.all"), value: "all" },
-      { label: translate("filters.favorite.favorite"), value: "true" },
-      { label: translate("filters.favorite.unfavorite"), value: "false" },
-    ],
-  });
+  const currentValue = showFavorites ?? "all";
 
   return (
-    <Select.Root
-      collection={enabledOptions}
-      onValueChange={onFavoriteChange}
-      value={[showFavorites ?? "all"]}
-    >
-      <Select.Trigger colorPalette="brand" isActive={Boolean(showFavorites)}>
-        <Select.ValueText width={20} />
-      </Select.Trigger>
-      <Select.Content>
-        {enabledOptions.items.map((option) => (
-          <Select.Item item={option} key={option.label}>
-            {option.label}
-          </Select.Item>
-        ))}
-      </Select.Content>
-    </Select.Root>
+    <ButtonGroup attached size="sm" variant="outline">
+      <Button
+        bg={currentValue === "all" ? "colorPalette.muted" : undefined}
+        colorPalette="brand"
+        onClick={onFavoriteChange}
+        value="all"
+        variant={currentValue === "all" ? "solid" : "outline"}
+      >
+        {translate("filters.favorite.all")}
+      </Button>
+      <Button
+        bg={currentValue === "true" ? "colorPalette.muted" : undefined}
+        colorPalette="brand"
+        onClick={onFavoriteChange}
+        value="true"
+        variant={currentValue === "true" ? "solid" : "outline"}
+      >
+        <Icon asChild color="brand.solid">
+          <FiStar style={{ fill: "currentColor" }} />
+        </Icon>
+        {translate("filters.favorite.favorite")}
+      </Button>
+      <Button
+        bg={currentValue === "false" ? "colorPalette.muted" : undefined}
+        colorPalette="brand"
+        onClick={onFavoriteChange}
+        value="false"
+        variant={currentValue === "false" ? "solid" : "outline"}
+      >
+        <Icon asChild color="fg.muted">
+          <FiStar />
+        </Icon>
+        {translate("filters.favorite.unfavorite")}
+      </Button>
+    </ButtonGroup>
   );
 };
diff --git 
a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/PausedFilter.tsx 
b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/PausedFilter.tsx
index 042795b18d0..ec21d605109 100644
--- 
a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/PausedFilter.tsx
+++ 
b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/PausedFilter.tsx
@@ -16,44 +16,49 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { createListCollection, type SelectValueChangeDetails } from 
"@chakra-ui/react";
+import { Button, ButtonGroup } from "@chakra-ui/react";
 import { useTranslation } from "react-i18next";
 
-import { Select } from "src/components/ui";
-
 type Props = {
   readonly defaultShowPaused: string;
-  readonly onPausedChange: (details: SelectValueChangeDetails<string>) => void;
+  readonly onPausedChange: React.MouseEventHandler<HTMLButtonElement>;
   readonly showPaused: string | null;
 };
 
 export const PausedFilter = ({ defaultShowPaused, onPausedChange, showPaused 
}: Props) => {
   const { t: translate } = useTranslation("dags");
 
-  const enabledOptions = createListCollection({
-    items: [
-      { label: translate("filters.paused.all"), value: "all" },
-      { label: translate("filters.paused.active"), value: "false" },
-      { label: translate("filters.paused.paused"), value: "true" },
-    ],
-  });
+  const currentValue = showPaused ?? defaultShowPaused;
 
   return (
-    <Select.Root
-      collection={enabledOptions}
-      onValueChange={onPausedChange}
-      value={[showPaused ?? defaultShowPaused]}
-    >
-      <Select.Trigger colorPalette="brand" isActive={Boolean(showPaused)}>
-        <Select.ValueText width={20} />
-      </Select.Trigger>
-      <Select.Content>
-        {enabledOptions.items.map((option) => (
-          <Select.Item item={option} key={option.label}>
-            {option.label}
-          </Select.Item>
-        ))}
-      </Select.Content>
-    </Select.Root>
+    <ButtonGroup attached size="sm" variant="outline">
+      <Button
+        bg={currentValue === "all" ? "colorPalette.muted" : undefined}
+        colorPalette="brand"
+        onClick={onPausedChange}
+        value="all"
+        variant={currentValue === "all" ? "solid" : "outline"}
+      >
+        {translate("filters.paused.all")}
+      </Button>
+      <Button
+        bg={currentValue === "false" ? "colorPalette.muted" : undefined}
+        colorPalette="brand"
+        onClick={onPausedChange}
+        value="false"
+        variant={currentValue === "false" ? "solid" : "outline"}
+      >
+        {translate("filters.paused.active")}
+      </Button>
+      <Button
+        bg={currentValue === "true" ? "colorPalette.muted" : undefined}
+        colorPalette="brand"
+        onClick={onPausedChange}
+        value="true"
+        variant={currentValue === "true" ? "solid" : "outline"}
+      >
+        {translate("filters.paused.paused")}
+      </Button>
+    </ButtonGroup>
   );
 };
diff --git 
a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/StateFilters.tsx 
b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/StateFilters.tsx
index 3bda2ba98fe..0533de4dc3a 100644
--- 
a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/StateFilters.tsx
+++ 
b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/StateFilters.tsx
@@ -16,11 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { HStack } from "@chakra-ui/react";
+import { Button, ButtonGroup } from "@chakra-ui/react";
 import { useTranslation } from "react-i18next";
 import { LuUserRoundPen } from "react-icons/lu";
 
-import { QuickFilterButton } from "src/components/QuickFilterButton";
 import { StateBadge } from "src/components/StateBadge";
 
 type Props = {
@@ -45,57 +44,73 @@ export const StateFilters = ({
   const { t: translate } = useTranslation(["dags", "common", "hitl"]);
 
   return (
-    <HStack>
-      <QuickFilterButton isActive={isAll} onClick={onStateChange} value="all">
+    <ButtonGroup attached size="sm" variant="outline">
+      <Button
+        bg={isAll ? "colorPalette.muted" : undefined}
+        colorPalette="brand"
+        onClick={onStateChange}
+        value="all"
+        variant={isAll ? "solid" : "outline"}
+      >
         {translate("dags:filters.paused.all")}
-      </QuickFilterButton>
-      <QuickFilterButton
+      </Button>
+      <Button
+        bg={isFailed ? "colorPalette.muted" : undefined}
+        colorPalette="brand"
         data-testid="dags-failed-filter"
-        isActive={isFailed}
         onClick={onStateChange}
         value="failed"
+        variant={isFailed ? "solid" : "outline"}
       >
         <StateBadge state="failed" />
         {translate("common:states.failed")}
-      </QuickFilterButton>
-      <QuickFilterButton
+      </Button>
+      <Button
+        bg={isQueued ? "colorPalette.muted" : undefined}
+        colorPalette="brand"
         data-testid="dags-queued-filter"
-        isActive={isQueued}
         onClick={onStateChange}
         value="queued"
+        variant={isQueued ? "solid" : "outline"}
       >
         <StateBadge state="queued" />
         {translate("common:states.queued")}
-      </QuickFilterButton>
-      <QuickFilterButton
+      </Button>
+      <Button
+        bg={isRunning ? "colorPalette.muted" : undefined}
+        colorPalette="brand"
         data-testid="dags-running-filter"
-        isActive={isRunning}
         onClick={onStateChange}
         value="running"
+        variant={isRunning ? "solid" : "outline"}
       >
         <StateBadge state="running" />
         {translate("common:states.running")}
-      </QuickFilterButton>
-      <QuickFilterButton
+      </Button>
+      <Button
+        bg={isSuccess ? "colorPalette.muted" : undefined}
+        colorPalette="brand"
         data-testid="dags-success-filter"
-        isActive={isSuccess}
         onClick={onStateChange}
         value="success"
+        variant={isSuccess ? "solid" : "outline"}
       >
         <StateBadge state="success" />
         {translate("common:states.success")}
-      </QuickFilterButton>
-      <QuickFilterButton
+      </Button>
+      <Button
+        bg={needsReview ? "colorPalette.muted" : undefined}
+        colorPalette="brand"
         data-testid="dags-needs-review-filter"
-        isActive={needsReview}
         onClick={onStateChange}
         value="needs_review"
+        variant={needsReview ? "solid" : "outline"}
       >
         <StateBadge colorPalette="deferred">
           <LuUserRoundPen />
         </StateBadge>
         {translate("hitl:requiredAction_other")}
-      </QuickFilterButton>
-    </HStack>
+      </Button>
+    </ButtonGroup>
   );
 };
diff --git 
a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/TagFilter.tsx 
b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/TagFilter.tsx
index 113d7e8de6a..001cd0b94f8 100644
--- a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/TagFilter.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/TagFilter.tsx
@@ -57,6 +57,7 @@ export const TagFilter = ({
             }),
             container: (provided) => ({
               ...provided,
+              maxWidth: 300,
               minWidth: 64,
             }),
             control: (provided) => ({

Reply via email to