This is an automated email from the ASF dual-hosted git repository.
bbovenzi 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 4ddb6b46210 Fix clipping of Last run state badge (#72459)
4ddb6b46210 is described below
commit 4ddb6b4621052c26b5d7b79b6556f2815f8be619
Author: jasperjonkhans <[email protected]>
AuthorDate: Wed Sep 9 19:52:31 2026 +0200
Fix clipping of Last run state badge (#72459)
Chakra's default select value clamping hides the lower edge of rich labels
such as state badges.
---
.../ui/src/components/FilterBar/FilterBar.test.tsx | 27 +++++++++++++++++++++-
.../components/FilterBar/filters/SelectFilter.tsx | 12 +++++++---
2 files changed, 35 insertions(+), 4 deletions(-)
diff --git
a/airflow-core/src/airflow/ui/src/components/FilterBar/FilterBar.test.tsx
b/airflow-core/src/airflow/ui/src/components/FilterBar/FilterBar.test.tsx
index 7b4e7326cfb..3710f2ed6e4 100644
--- a/airflow-core/src/airflow/ui/src/components/FilterBar/FilterBar.test.tsx
+++ b/airflow-core/src/airflow/ui/src/components/FilterBar/FilterBar.test.tsx
@@ -19,10 +19,12 @@
import type { PropsWithChildren } from "react";
import "@testing-library/jest-dom";
-import { cleanup, fireEvent, render, screen, waitFor } from
"@testing-library/react";
+import { cleanup, fireEvent, render, screen, waitFor, within } from
"@testing-library/react";
import { MemoryRouter } from "react-router-dom";
import { afterEach, describe, expect, it, vi } from "vitest";
+import { StateBadge } from "src/components/StateBadge";
+
import { BaseWrapper } from "src/utils/Wrapper";
import { FilterBar } from "./FilterBar";
@@ -107,6 +109,29 @@ describe("FilterBar boolean filters", () => {
});
});
+describe("FilterBar select filters", () => {
+ it("keeps a selected rich option label fully visible", () => {
+ const selectConfig: FilterConfig = {
+ key: "state",
+ label: "State",
+ options: [{ label: <StateBadge state="failed">Failed</StateBadge>,
value: "failed" }],
+ type: "select",
+ };
+
+ render(
+ <FilterBar configs={[selectConfig]} initialValues={{ state: "failed" }}
onFiltersChange={vi.fn()} />,
+ { wrapper },
+ );
+
+ fireEvent.click(screen.getByTestId("state-pill"));
+
+ const valueText =
within(screen.getByTestId("state-filter")).getByTestId("state-badge").parentElement;
+
+ expect(valueText).not.toBeNull();
+ expect(globalThis.getComputedStyle(valueText as
HTMLElement).overflow).toBe("visible");
+ });
+});
+
describe("FilterBar multiselect filters", () => {
it("renders a pill for each value from array initialValues", () => {
render(
diff --git
a/airflow-core/src/airflow/ui/src/components/FilterBar/filters/SelectFilter.tsx
b/airflow-core/src/airflow/ui/src/components/FilterBar/filters/SelectFilter.tsx
index 8f8e6d9b36f..e1b50eaa0c4 100644
---
a/airflow-core/src/airflow/ui/src/components/FilterBar/filters/SelectFilter.tsx
+++
b/airflow-core/src/airflow/ui/src/components/FilterBar/filters/SelectFilter.tsx
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { useRef } from "react";
+import { useRef, type ReactNode } from "react";
import { Box, createListCollection } from "@chakra-ui/react";
@@ -26,7 +26,7 @@ import { FilterPill } from "../FilterPill";
import type { FilterConfig, FilterPluginProps } from "../types";
type SelectOption = {
- label: string;
+ label: ReactNode;
value: string;
};
@@ -59,6 +59,8 @@ export const SelectFilter = ({ filter, onChange, onRemove }:
FilterPluginProps)
const displayValue = config.options.find(
(option) => option.value === (typeof filter.value === "string" ?
filter.value : ""),
)?.label;
+ // Chakra line-clamps value text by default, which clips padded elements
such as state badges.
+ const hasRichDisplayValue = displayValue !== undefined && typeof
displayValue !== "string";
return (
<FilterPill
@@ -118,7 +120,11 @@ export const SelectFilter = ({ filter, onChange, onRemove
}: FilterPluginProps)
value={hasValue && typeof filter.value === "string" ?
[filter.value] : []}
>
<Select.Trigger dataTestId={`${filter.config.key}-filter`}
triggerProps={{ border: "none" }}>
- <Select.ValueText placeholder={filter.config.placeholder} />
+ <Select.ValueText
+ lineClamp={hasRichDisplayValue ? "none" : undefined}
+ overflow={hasRichDisplayValue ? "visible" : undefined}
+ placeholder={filter.config.placeholder}
+ />
</Select.Trigger>
<Select.Content>
{config.options.map((option) => (