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 e4352cd20b8 Mark task-group aggregate bars on Gantt with a diagonal
stripe (#72894)
e4352cd20b8 is described below
commit e4352cd20b8f2d0d6b2f52d48c1d47e35cabd15b
Author: Pierre Jeambrun <[email protected]>
AuthorDate: Tue Sep 15 15:27:56 2026 +0200
Mark task-group aggregate bars on Gantt with a diagonal stripe (#72894)
A collapsed TaskGroup renders on the Gantt as a single bar spanning the
envelope of its children's runtime. That bar looked identical to a real task
and read as one very long-running task at a glance, exactly the confusion
the
linked issue describes.
Overlay a diagonal stripe on group aggregate bars so they are visually
distinct from real task bars while keeping their duration and position (so
groups still line up with the sidebar for organisation). Composes on top of
the badge's solid state colour so state is still legible.
closes: #72434
---
.../layouts/Details/Gantt/GanttTimeline.test.tsx | 46 ++++++++++++++++++++++
.../ui/src/layouts/Details/Gantt/GanttTimeline.tsx | 12 ++++++
2 files changed, 58 insertions(+)
diff --git
a/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/GanttTimeline.test.tsx
b/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/GanttTimeline.test.tsx
index f7554c685bf..5448f3b5c68 100644
---
a/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/GanttTimeline.test.tsx
+++
b/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/GanttTimeline.test.tsx
@@ -329,4 +329,50 @@ describe("GanttTimeline segment bars", () => {
// Only the execution bar should be rendered; scheduled and queued are too
narrow.
expect(screen.getAllByRole("link")).toHaveLength(1);
});
+
+ it("hatches a task-group aggregate bar so it does not read as a single long
task", () => {
+ const groupNode: GridTask = {
+ depth: 0,
+ id: "group_1",
+ is_mapped: false,
+ isGroup: true,
+ label: "group_1",
+ };
+ const groupSegment: GanttDataItem = {
+ queued_when: null,
+ scheduled_when: null,
+ state: "success",
+ taskId: "group_1",
+ tryNumber: undefined,
+ x: [new Date("2024-03-14T10:00:00Z").getTime(), new
Date("2024-03-14T10:05:00Z").getTime()],
+ y: "group_1",
+ };
+ const leafSegment: GanttDataItem = {
+ queued_when: null,
+ scheduled_when: null,
+ state: "success",
+ taskId: "task_1",
+ tryNumber: 1,
+ x: [new Date("2024-03-14T10:00:00Z").getTime(), new
Date("2024-03-14T10:05:00Z").getTime()],
+ y: "task_1",
+ };
+
+ render(
+ <GanttTimeline
+ {...defaultProps}
+ flatNodes={[groupNode, BASE_NODE]}
+ ganttDataItems={[groupSegment, leafSegment]}
+ rowSegments={[[groupSegment], [leafSegment]]}
+ scrollContainerRef={makeScrollRef()}
+ />,
+ { wrapper: TestWrapper },
+ );
+
+ const bars = screen.getAllByRole("link");
+
+ // Group aggregate bar carries the diagonal-stripe overlay.
+
expect(bars[0]?.querySelector('[style*="repeating-linear-gradient"]')).not.toBeNull();
+ // Regular task bar does not.
+
expect(bars[1]?.querySelector('[style*="repeating-linear-gradient"]')).toBeNull();
+ });
});
diff --git
a/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/GanttTimeline.tsx
b/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/GanttTimeline.tsx
index 977322eeb38..06e5924a740 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/GanttTimeline.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/GanttTimeline.tsx
@@ -385,6 +385,18 @@ export const GanttTimeline = ({
justifyContent="center"
minH={0}
p={0}
+ // Aggregate task-group bars are the envelope of
their children's
+ // runtime, not a real running task. Overlay a
diagonal stripe so
+ // they read as an aggregate at a glance and
don't get mistaken for
+ // a single long-running task.
+ style={
+ node.isGroup === true
+ ? {
+ backgroundImage:
+ "repeating-linear-gradient(45deg,
rgba(255,255,255,0.4) 0px, rgba(255,255,255,0.4) 3px, transparent 3px,
transparent 6px)",
+ }
+ : undefined
+ }
variant="solid"
w="100%"
>