Skip to content

Fix Toaster in Plugin in Edge UI - #55641

Merged
bbovenzi merged 6 commits into
apache:mainfrom
jscheffl:bugfix/fix-toaster-in-plugin
Mar 2, 2026
Merged

Fix Toaster in Plugin in Edge UI#55641
bbovenzi merged 6 commits into
apache:mainfrom
jscheffl:bugfix/fix-toaster-in-plugin

Conversation

@jscheffl

@jscheffljscheffl commented Sep 13, 2025

Copy link
Copy Markdown
Contributor

With hints from @bbovenzi this PR now fixes the Toaster display in Edge Executor UI! Thanks! That was a longer endeavor.

This is how it looks now after the fix... toaster content/logic was in all the time already...

edge-toaster-fix-2026-03-01_21.59.59.mp4

Previous PR Intro:

There is a teething problem that the Chakra "Toast" component is not working in Edge React UI. I need some React Expertise to fix it seems.

@shubhamraj-git / @bbovenzi / @pierrejeambrun HELP :-D

To make this reprodicible I made two toasters:
1 in the Navbar and one in te Edge UI plugin.

How to see the error:

  1. Take this branch
  2. Run it locally via breeze start-airflow --python 3.12 --backend postgres --executor EdgeExecutor --load-example-dags
  3. Open the Web UI and after login on the start page, click on the "Toast" button in the Navbar - all OK
  4. Navifate to "Admin" -> "Edge Worker Hosts" (Which is the React Plugin)
  5. Click the same button --> Does not respond. See JavaScript console that logs are written and no errors
  6. Attempt to click on the Toaster Test button in the Plugin itself, also not working
  7. Same if you use the IFrame plugin in "Docs" -> "Edge API Docs", also there the Toaster in Navbar is not working

Is this a limitation of the plugin concept or a bug in my Plugin? How can the Toaster be made working?

@boring-cyborgboring-cyborgBot added area:providers area:UI Related to UI/UX. For Frontend Developers. provider:edge Edge Executor / Worker (AIP-69) / edge3 labels Sep 13, 2025
@jscheffljscheffl mentioned this pull request Sep 13, 2025
@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 0e30e30 to 104551aCompareSeptember 14, 2025 20:44
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 5 days if no further activity occurs. Thank you for your contributions.

@github-actionsgithub-actionsBot added the stale Stale PRs per the .github/workflows/stale.yml policy file label Oct 30, 2025
@pierrejeambrun

Copy link
Copy Markdown
Member

Up

@pierrejeambrunpierrejeambrun removed the stale Stale PRs per the .github/workflows/stale.yml policy file label Oct 30, 2025
@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 104551a to 770c74fCompareNovember 11, 2025 20:19
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up for ~1200 commits :-D

@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 770c74f to f976a86CompareDecember 23, 2025 18:07
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up for ~720 commits :-D (again)

@jscheffl

Copy link
Copy Markdown
ContributorAuthor

@pierrejeambrun Interesting, still do not understand the root cause why a toaster is not working on Plugins pages but what I noticed in the browser is that there is a <div> element rendered for all pages which seems to hold the toaster below the root div element with the id="toast-group":
image

This one is missing on the Plugins page - and don't know if this helps in trigaing - but noticed when navigating to Admin -> Configs (url: /config) which is raising a forbidden error via HTTP 403, there also the toaster is not working with the explicit ybutton in the Nav.

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have to investigate. But my guess is that Chakra UI handles the toaster via 'portals' into a specific unique dom element that is global. So basically any toaster will render in that shared toast-group element.

Then there might be some sort of conflict, the plugin toast can't find the proper host element to portal the toast to.

I'm sorry for the delay and not finding time to look at this yet.

@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from f976a86 to 525a1cbCompareJanuary 31, 2026 20:16
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up by 700 commits

@bbovenzibbovenzi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave you pseudo code. Here is exactly what you need:

toaster.tsx:

import { Toaster as ChakraToaster, Portal, Spinner, Stack, Toast, createToaster } from "@chakra-ui/react";
import type { RefObject } from "react";
export const toaster = createToaster({
pauseOnPageIdle: true,
placement: "bottom-end",
});
export const Toaster = ({ containerRef }: { containerRef: RefObject<HTMLDivElement | null> }) => (
<Portal container={containerRef}>
<ChakraToaster toaster={toaster} insetInline={{ mdDown: "4" }}>
{(toast) => (
<Toast.Root width={{ md: "sm" }}>
{toast.type === "loading" ? <Spinner size="sm" color="blue.solid" /> : <Toast.Indicator />}
<Stack gap="1" flex="1" maxWidth="100%">
{toast.title && <Toast.Title>{toast.title}</Toast.Title>}
{toast.description && <Toast.Description>{toast.description}</Toast.Description>}
</Stack>
{toast.action && <Toast.ActionTrigger>{toast.action.label}</Toast.ActionTrigger>}
{toast.closable && <Toast.CloseTrigger />}
</Toast.Root>
)}
</ChakraToaster>
</Portal>
);

EdgeLayout.tsx:

import { Box } from "@chakra-ui/react";
import { useRef } from "react";
import { Navigate, Route, Routes } from "react-router-dom";
import { Toaster } from "src/components/ui";
import { JobsPage } from "src/pages/JobsPage";
import { WorkerPage } from "src/pages/WorkerPage";
import { NavTabs } from "./NavTabs";
export const EdgeLayout = () => {
const containerRef = useRef<HTMLDivElement>(null);
const tabs = [
{ label: "Edge Worker", value: "worker" },
{ label: "Edge Jobs", value: "jobs" },
];
return (
<Box ref={containerRef} p={2} /* Compensate for parent padding from ExternalView */>
<NavTabs tabs={tabs} />
<Routes>
<Route index element={<Navigate to="worker" replace />} />
<Route path="worker" element={<WorkerPage />} />
<Route path="jobs" element={<JobsPage />} />
</Routes>
<Toaster containerRef={containerRef} />
</Box>
);
};

@jscheffljscheffl changed the title [DO NOT MERGE] Attempt to fix Toaster in PluginFix Toaster in Plugin in Edge UIMar 1, 2026
@jscheffl
jscheffl marked this pull request as ready for review March 1, 2026 21:02
@jscheffljscheffl added the type:bug-fix Changelog: Bug Fixes label Mar 1, 2026
@bbovenzi
bbovenzi merged commit 3161a80 into apache:mainMar 2, 2026
120 of 123 checks passed
dominikhei pushed a commit to dominikhei/airflow that referenced this pull request Mar 11, 2026
* Attempt to fix Toaster in Plugin
* Attempt to fix via proposal
* Revert testing of toaster open
* Fix toaster using hints from Brent
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersarea:UIRelated to UI/UX. For Frontend Developers.provider:edgeEdge Executor / Worker (AIP-69) / edge3type:bug-fixChangelog: Bug Fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jscheffl@pierrejeambrun@bbovenzi
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Fix Toaster in Plugin in Edge UI by jscheffl · Pull Request #55641 · apache/airflow · GitHub
Skip to content

Fix Toaster in Plugin in Edge UI - #55641

Merged
bbovenzi merged 6 commits into
apache:mainfrom
jscheffl:bugfix/fix-toaster-in-plugin
Mar 2, 2026
Merged

Fix Toaster in Plugin in Edge UI#55641
bbovenzi merged 6 commits into
apache:mainfrom
jscheffl:bugfix/fix-toaster-in-plugin

Conversation

@jscheffl

@jscheffljscheffl commented Sep 13, 2025

Copy link
Copy Markdown
Contributor

With hints from @bbovenzi this PR now fixes the Toaster display in Edge Executor UI! Thanks! That was a longer endeavor.

This is how it looks now after the fix... toaster content/logic was in all the time already...

edge-toaster-fix-2026-03-01_21.59.59.mp4

Previous PR Intro:

There is a teething problem that the Chakra "Toast" component is not working in Edge React UI. I need some React Expertise to fix it seems.

@shubhamraj-git / @bbovenzi / @pierrejeambrun HELP :-D

To make this reprodicible I made two toasters:
1 in the Navbar and one in te Edge UI plugin.

How to see the error:

  1. Take this branch
  2. Run it locally via breeze start-airflow --python 3.12 --backend postgres --executor EdgeExecutor --load-example-dags
  3. Open the Web UI and after login on the start page, click on the "Toast" button in the Navbar - all OK
  4. Navifate to "Admin" -> "Edge Worker Hosts" (Which is the React Plugin)
  5. Click the same button --> Does not respond. See JavaScript console that logs are written and no errors
  6. Attempt to click on the Toaster Test button in the Plugin itself, also not working
  7. Same if you use the IFrame plugin in "Docs" -> "Edge API Docs", also there the Toaster in Navbar is not working

Is this a limitation of the plugin concept or a bug in my Plugin? How can the Toaster be made working?

@boring-cyborgboring-cyborgBot added area:providers area:UI Related to UI/UX. For Frontend Developers. provider:edge Edge Executor / Worker (AIP-69) / edge3 labels Sep 13, 2025
@jscheffljscheffl mentioned this pull request Sep 13, 2025
@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 0e30e30 to 104551aCompareSeptember 14, 2025 20:44
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 5 days if no further activity occurs. Thank you for your contributions.

@github-actionsgithub-actionsBot added the stale Stale PRs per the .github/workflows/stale.yml policy file label Oct 30, 2025
@pierrejeambrun

Copy link
Copy Markdown
Member

Up

@pierrejeambrunpierrejeambrun removed the stale Stale PRs per the .github/workflows/stale.yml policy file label Oct 30, 2025
@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 104551a to 770c74fCompareNovember 11, 2025 20:19
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up for ~1200 commits :-D

@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 770c74f to f976a86CompareDecember 23, 2025 18:07
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up for ~720 commits :-D (again)

@jscheffl

Copy link
Copy Markdown
ContributorAuthor

@pierrejeambrun Interesting, still do not understand the root cause why a toaster is not working on Plugins pages but what I noticed in the browser is that there is a <div> element rendered for all pages which seems to hold the toaster below the root div element with the id="toast-group":
image

This one is missing on the Plugins page - and don't know if this helps in trigaing - but noticed when navigating to Admin -> Configs (url: /config) which is raising a forbidden error via HTTP 403, there also the toaster is not working with the explicit ybutton in the Nav.

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have to investigate. But my guess is that Chakra UI handles the toaster via 'portals' into a specific unique dom element that is global. So basically any toaster will render in that shared toast-group element.

Then there might be some sort of conflict, the plugin toast can't find the proper host element to portal the toast to.

I'm sorry for the delay and not finding time to look at this yet.

@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from f976a86 to 525a1cbCompareJanuary 31, 2026 20:16
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up by 700 commits

@bbovenzibbovenzi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave you pseudo code. Here is exactly what you need:

toaster.tsx:

import { Toaster as ChakraToaster, Portal, Spinner, Stack, Toast, createToaster } from "@chakra-ui/react";
import type { RefObject } from "react";
export const toaster = createToaster({
pauseOnPageIdle: true,
placement: "bottom-end",
});
export const Toaster = ({ containerRef }: { containerRef: RefObject<HTMLDivElement | null> }) => (
<Portal container={containerRef}>
<ChakraToaster toaster={toaster} insetInline={{ mdDown: "4" }}>
{(toast) => (
<Toast.Root width={{ md: "sm" }}>
{toast.type === "loading" ? <Spinner size="sm" color="blue.solid" /> : <Toast.Indicator />}
<Stack gap="1" flex="1" maxWidth="100%">
{toast.title && <Toast.Title>{toast.title}</Toast.Title>}
{toast.description && <Toast.Description>{toast.description}</Toast.Description>}
</Stack>
{toast.action && <Toast.ActionTrigger>{toast.action.label}</Toast.ActionTrigger>}
{toast.closable && <Toast.CloseTrigger />}
</Toast.Root>
)}
</ChakraToaster>
</Portal>
);

EdgeLayout.tsx:

import { Box } from "@chakra-ui/react";
import { useRef } from "react";
import { Navigate, Route, Routes } from "react-router-dom";
import { Toaster } from "src/components/ui";
import { JobsPage } from "src/pages/JobsPage";
import { WorkerPage } from "src/pages/WorkerPage";
import { NavTabs } from "./NavTabs";
export const EdgeLayout = () => {
const containerRef = useRef<HTMLDivElement>(null);
const tabs = [
{ label: "Edge Worker", value: "worker" },
{ label: "Edge Jobs", value: "jobs" },
];
return (
<Box ref={containerRef} p={2} /* Compensate for parent padding from ExternalView */>
<NavTabs tabs={tabs} />
<Routes>
<Route index element={<Navigate to="worker" replace />} />
<Route path="worker" element={<WorkerPage />} />
<Route path="jobs" element={<JobsPage />} />
</Routes>
<Toaster containerRef={containerRef} />
</Box>
);
};

@jscheffljscheffl changed the title [DO NOT MERGE] Attempt to fix Toaster in PluginFix Toaster in Plugin in Edge UIMar 1, 2026
@jscheffl
jscheffl marked this pull request as ready for review March 1, 2026 21:02
@jscheffljscheffl added the type:bug-fix Changelog: Bug Fixes label Mar 1, 2026
@bbovenzi
bbovenzi merged commit 3161a80 into apache:mainMar 2, 2026
120 of 123 checks passed
dominikhei pushed a commit to dominikhei/airflow that referenced this pull request Mar 11, 2026
* Attempt to fix Toaster in Plugin
* Attempt to fix via proposal
* Revert testing of toaster open
* Fix toaster using hints from Brent
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersarea:UIRelated to UI/UX. For Frontend Developers.provider:edgeEdge Executor / Worker (AIP-69) / edge3type:bug-fixChangelog: Bug Fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jscheffl@pierrejeambrun@bbovenzi
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Fix Toaster in Plugin in Edge UI by jscheffl · Pull Request #55641 · apache/airflow · GitHub
Skip to content

Fix Toaster in Plugin in Edge UI - #55641

Merged
bbovenzi merged 6 commits into
apache:mainfrom
jscheffl:bugfix/fix-toaster-in-plugin
Mar 2, 2026
Merged

Fix Toaster in Plugin in Edge UI#55641
bbovenzi merged 6 commits into
apache:mainfrom
jscheffl:bugfix/fix-toaster-in-plugin

Conversation

@jscheffl

@jscheffljscheffl commented Sep 13, 2025

Copy link
Copy Markdown
Contributor

With hints from @bbovenzi this PR now fixes the Toaster display in Edge Executor UI! Thanks! That was a longer endeavor.

This is how it looks now after the fix... toaster content/logic was in all the time already...

edge-toaster-fix-2026-03-01_21.59.59.mp4

Previous PR Intro:

There is a teething problem that the Chakra "Toast" component is not working in Edge React UI. I need some React Expertise to fix it seems.

@shubhamraj-git / @bbovenzi / @pierrejeambrun HELP :-D

To make this reprodicible I made two toasters:
1 in the Navbar and one in te Edge UI plugin.

How to see the error:

  1. Take this branch
  2. Run it locally via breeze start-airflow --python 3.12 --backend postgres --executor EdgeExecutor --load-example-dags
  3. Open the Web UI and after login on the start page, click on the "Toast" button in the Navbar - all OK
  4. Navifate to "Admin" -> "Edge Worker Hosts" (Which is the React Plugin)
  5. Click the same button --> Does not respond. See JavaScript console that logs are written and no errors
  6. Attempt to click on the Toaster Test button in the Plugin itself, also not working
  7. Same if you use the IFrame plugin in "Docs" -> "Edge API Docs", also there the Toaster in Navbar is not working

Is this a limitation of the plugin concept or a bug in my Plugin? How can the Toaster be made working?

@boring-cyborgboring-cyborgBot added area:providers area:UI Related to UI/UX. For Frontend Developers. provider:edge Edge Executor / Worker (AIP-69) / edge3 labels Sep 13, 2025
@jscheffljscheffl mentioned this pull request Sep 13, 2025
@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 0e30e30 to 104551aCompareSeptember 14, 2025 20:44
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 5 days if no further activity occurs. Thank you for your contributions.

@github-actionsgithub-actionsBot added the stale Stale PRs per the .github/workflows/stale.yml policy file label Oct 30, 2025
@pierrejeambrun

Copy link
Copy Markdown
Member

Up

@pierrejeambrunpierrejeambrun removed the stale Stale PRs per the .github/workflows/stale.yml policy file label Oct 30, 2025
@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 104551a to 770c74fCompareNovember 11, 2025 20:19
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up for ~1200 commits :-D

@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 770c74f to f976a86CompareDecember 23, 2025 18:07
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up for ~720 commits :-D (again)

@jscheffl

Copy link
Copy Markdown
ContributorAuthor

@pierrejeambrun Interesting, still do not understand the root cause why a toaster is not working on Plugins pages but what I noticed in the browser is that there is a <div> element rendered for all pages which seems to hold the toaster below the root div element with the id="toast-group":
image

This one is missing on the Plugins page - and don't know if this helps in trigaing - but noticed when navigating to Admin -> Configs (url: /config) which is raising a forbidden error via HTTP 403, there also the toaster is not working with the explicit ybutton in the Nav.

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have to investigate. But my guess is that Chakra UI handles the toaster via 'portals' into a specific unique dom element that is global. So basically any toaster will render in that shared toast-group element.

Then there might be some sort of conflict, the plugin toast can't find the proper host element to portal the toast to.

I'm sorry for the delay and not finding time to look at this yet.

@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from f976a86 to 525a1cbCompareJanuary 31, 2026 20:16
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up by 700 commits

@bbovenzibbovenzi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave you pseudo code. Here is exactly what you need:

toaster.tsx:

import { Toaster as ChakraToaster, Portal, Spinner, Stack, Toast, createToaster } from "@chakra-ui/react";
import type { RefObject } from "react";
export const toaster = createToaster({
pauseOnPageIdle: true,
placement: "bottom-end",
});
export const Toaster = ({ containerRef }: { containerRef: RefObject<HTMLDivElement | null> }) => (
<Portal container={containerRef}>
<ChakraToaster toaster={toaster} insetInline={{ mdDown: "4" }}>
{(toast) => (
<Toast.Root width={{ md: "sm" }}>
{toast.type === "loading" ? <Spinner size="sm" color="blue.solid" /> : <Toast.Indicator />}
<Stack gap="1" flex="1" maxWidth="100%">
{toast.title && <Toast.Title>{toast.title}</Toast.Title>}
{toast.description && <Toast.Description>{toast.description}</Toast.Description>}
</Stack>
{toast.action && <Toast.ActionTrigger>{toast.action.label}</Toast.ActionTrigger>}
{toast.closable && <Toast.CloseTrigger />}
</Toast.Root>
)}
</ChakraToaster>
</Portal>
);

EdgeLayout.tsx:

import { Box } from "@chakra-ui/react";
import { useRef } from "react";
import { Navigate, Route, Routes } from "react-router-dom";
import { Toaster } from "src/components/ui";
import { JobsPage } from "src/pages/JobsPage";
import { WorkerPage } from "src/pages/WorkerPage";
import { NavTabs } from "./NavTabs";
export const EdgeLayout = () => {
const containerRef = useRef<HTMLDivElement>(null);
const tabs = [
{ label: "Edge Worker", value: "worker" },
{ label: "Edge Jobs", value: "jobs" },
];
return (
<Box ref={containerRef} p={2} /* Compensate for parent padding from ExternalView */>
<NavTabs tabs={tabs} />
<Routes>
<Route index element={<Navigate to="worker" replace />} />
<Route path="worker" element={<WorkerPage />} />
<Route path="jobs" element={<JobsPage />} />
</Routes>
<Toaster containerRef={containerRef} />
</Box>
);
};

@jscheffljscheffl changed the title [DO NOT MERGE] Attempt to fix Toaster in PluginFix Toaster in Plugin in Edge UIMar 1, 2026
@jscheffl
jscheffl marked this pull request as ready for review March 1, 2026 21:02
@jscheffljscheffl added the type:bug-fix Changelog: Bug Fixes label Mar 1, 2026
@bbovenzi
bbovenzi merged commit 3161a80 into apache:mainMar 2, 2026
120 of 123 checks passed
dominikhei pushed a commit to dominikhei/airflow that referenced this pull request Mar 11, 2026
* Attempt to fix Toaster in Plugin
* Attempt to fix via proposal
* Revert testing of toaster open
* Fix toaster using hints from Brent
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersarea:UIRelated to UI/UX. For Frontend Developers.provider:edgeEdge Executor / Worker (AIP-69) / edge3type:bug-fixChangelog: Bug Fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jscheffl@pierrejeambrun@bbovenzi
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Fix Toaster in Plugin in Edge UI by jscheffl · Pull Request #55641 · apache/airflow · GitHub
Skip to content

Fix Toaster in Plugin in Edge UI - #55641

Merged
bbovenzi merged 6 commits into
apache:mainfrom
jscheffl:bugfix/fix-toaster-in-plugin
Mar 2, 2026
Merged

Fix Toaster in Plugin in Edge UI#55641
bbovenzi merged 6 commits into
apache:mainfrom
jscheffl:bugfix/fix-toaster-in-plugin

Conversation

@jscheffl

@jscheffljscheffl commented Sep 13, 2025

Copy link
Copy Markdown
Contributor

With hints from @bbovenzi this PR now fixes the Toaster display in Edge Executor UI! Thanks! That was a longer endeavor.

This is how it looks now after the fix... toaster content/logic was in all the time already...

edge-toaster-fix-2026-03-01_21.59.59.mp4

Previous PR Intro:

There is a teething problem that the Chakra "Toast" component is not working in Edge React UI. I need some React Expertise to fix it seems.

@shubhamraj-git / @bbovenzi / @pierrejeambrun HELP :-D

To make this reprodicible I made two toasters:
1 in the Navbar and one in te Edge UI plugin.

How to see the error:

  1. Take this branch
  2. Run it locally via breeze start-airflow --python 3.12 --backend postgres --executor EdgeExecutor --load-example-dags
  3. Open the Web UI and after login on the start page, click on the "Toast" button in the Navbar - all OK
  4. Navifate to "Admin" -> "Edge Worker Hosts" (Which is the React Plugin)
  5. Click the same button --> Does not respond. See JavaScript console that logs are written and no errors
  6. Attempt to click on the Toaster Test button in the Plugin itself, also not working
  7. Same if you use the IFrame plugin in "Docs" -> "Edge API Docs", also there the Toaster in Navbar is not working

Is this a limitation of the plugin concept or a bug in my Plugin? How can the Toaster be made working?

@boring-cyborgboring-cyborgBot added area:providers area:UI Related to UI/UX. For Frontend Developers. provider:edge Edge Executor / Worker (AIP-69) / edge3 labels Sep 13, 2025
@jscheffljscheffl mentioned this pull request Sep 13, 2025
@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 0e30e30 to 104551aCompareSeptember 14, 2025 20:44
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 5 days if no further activity occurs. Thank you for your contributions.

@github-actionsgithub-actionsBot added the stale Stale PRs per the .github/workflows/stale.yml policy file label Oct 30, 2025
@pierrejeambrun

Copy link
Copy Markdown
Member

Up

@pierrejeambrunpierrejeambrun removed the stale Stale PRs per the .github/workflows/stale.yml policy file label Oct 30, 2025
@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 104551a to 770c74fCompareNovember 11, 2025 20:19
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up for ~1200 commits :-D

@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 770c74f to f976a86CompareDecember 23, 2025 18:07
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up for ~720 commits :-D (again)

@jscheffl

Copy link
Copy Markdown
ContributorAuthor

@pierrejeambrun Interesting, still do not understand the root cause why a toaster is not working on Plugins pages but what I noticed in the browser is that there is a <div> element rendered for all pages which seems to hold the toaster below the root div element with the id="toast-group":
image

This one is missing on the Plugins page - and don't know if this helps in trigaing - but noticed when navigating to Admin -> Configs (url: /config) which is raising a forbidden error via HTTP 403, there also the toaster is not working with the explicit ybutton in the Nav.

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have to investigate. But my guess is that Chakra UI handles the toaster via 'portals' into a specific unique dom element that is global. So basically any toaster will render in that shared toast-group element.

Then there might be some sort of conflict, the plugin toast can't find the proper host element to portal the toast to.

I'm sorry for the delay and not finding time to look at this yet.

@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from f976a86 to 525a1cbCompareJanuary 31, 2026 20:16
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up by 700 commits

@bbovenzibbovenzi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave you pseudo code. Here is exactly what you need:

toaster.tsx:

import { Toaster as ChakraToaster, Portal, Spinner, Stack, Toast, createToaster } from "@chakra-ui/react";
import type { RefObject } from "react";
export const toaster = createToaster({
pauseOnPageIdle: true,
placement: "bottom-end",
});
export const Toaster = ({ containerRef }: { containerRef: RefObject<HTMLDivElement | null> }) => (
<Portal container={containerRef}>
<ChakraToaster toaster={toaster} insetInline={{ mdDown: "4" }}>
{(toast) => (
<Toast.Root width={{ md: "sm" }}>
{toast.type === "loading" ? <Spinner size="sm" color="blue.solid" /> : <Toast.Indicator />}
<Stack gap="1" flex="1" maxWidth="100%">
{toast.title && <Toast.Title>{toast.title}</Toast.Title>}
{toast.description && <Toast.Description>{toast.description}</Toast.Description>}
</Stack>
{toast.action && <Toast.ActionTrigger>{toast.action.label}</Toast.ActionTrigger>}
{toast.closable && <Toast.CloseTrigger />}
</Toast.Root>
)}
</ChakraToaster>
</Portal>
);

EdgeLayout.tsx:

import { Box } from "@chakra-ui/react";
import { useRef } from "react";
import { Navigate, Route, Routes } from "react-router-dom";
import { Toaster } from "src/components/ui";
import { JobsPage } from "src/pages/JobsPage";
import { WorkerPage } from "src/pages/WorkerPage";
import { NavTabs } from "./NavTabs";
export const EdgeLayout = () => {
const containerRef = useRef<HTMLDivElement>(null);
const tabs = [
{ label: "Edge Worker", value: "worker" },
{ label: "Edge Jobs", value: "jobs" },
];
return (
<Box ref={containerRef} p={2} /* Compensate for parent padding from ExternalView */>
<NavTabs tabs={tabs} />
<Routes>
<Route index element={<Navigate to="worker" replace />} />
<Route path="worker" element={<WorkerPage />} />
<Route path="jobs" element={<JobsPage />} />
</Routes>
<Toaster containerRef={containerRef} />
</Box>
);
};

@jscheffljscheffl changed the title [DO NOT MERGE] Attempt to fix Toaster in PluginFix Toaster in Plugin in Edge UIMar 1, 2026
@jscheffl
jscheffl marked this pull request as ready for review March 1, 2026 21:02
@jscheffljscheffl added the type:bug-fix Changelog: Bug Fixes label Mar 1, 2026
@bbovenzi
bbovenzi merged commit 3161a80 into apache:mainMar 2, 2026
120 of 123 checks passed
dominikhei pushed a commit to dominikhei/airflow that referenced this pull request Mar 11, 2026
* Attempt to fix Toaster in Plugin
* Attempt to fix via proposal
* Revert testing of toaster open
* Fix toaster using hints from Brent
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersarea:UIRelated to UI/UX. For Frontend Developers.provider:edgeEdge Executor / Worker (AIP-69) / edge3type:bug-fixChangelog: Bug Fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jscheffl@pierrejeambrun@bbovenzi
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Fix Toaster in Plugin in Edge UI by jscheffl · Pull Request #55641 · apache/airflow · GitHub
Skip to content

Fix Toaster in Plugin in Edge UI - #55641

Merged
bbovenzi merged 6 commits into
apache:mainfrom
jscheffl:bugfix/fix-toaster-in-plugin
Mar 2, 2026
Merged

Fix Toaster in Plugin in Edge UI#55641
bbovenzi merged 6 commits into
apache:mainfrom
jscheffl:bugfix/fix-toaster-in-plugin

Conversation

@jscheffl

@jscheffljscheffl commented Sep 13, 2025

Copy link
Copy Markdown
Contributor

With hints from @bbovenzi this PR now fixes the Toaster display in Edge Executor UI! Thanks! That was a longer endeavor.

This is how it looks now after the fix... toaster content/logic was in all the time already...

edge-toaster-fix-2026-03-01_21.59.59.mp4

Previous PR Intro:

There is a teething problem that the Chakra "Toast" component is not working in Edge React UI. I need some React Expertise to fix it seems.

@shubhamraj-git / @bbovenzi / @pierrejeambrun HELP :-D

To make this reprodicible I made two toasters:
1 in the Navbar and one in te Edge UI plugin.

How to see the error:

  1. Take this branch
  2. Run it locally via breeze start-airflow --python 3.12 --backend postgres --executor EdgeExecutor --load-example-dags
  3. Open the Web UI and after login on the start page, click on the "Toast" button in the Navbar - all OK
  4. Navifate to "Admin" -> "Edge Worker Hosts" (Which is the React Plugin)
  5. Click the same button --> Does not respond. See JavaScript console that logs are written and no errors
  6. Attempt to click on the Toaster Test button in the Plugin itself, also not working
  7. Same if you use the IFrame plugin in "Docs" -> "Edge API Docs", also there the Toaster in Navbar is not working

Is this a limitation of the plugin concept or a bug in my Plugin? How can the Toaster be made working?

@boring-cyborgboring-cyborgBot added area:providers area:UI Related to UI/UX. For Frontend Developers. provider:edge Edge Executor / Worker (AIP-69) / edge3 labels Sep 13, 2025
@jscheffljscheffl mentioned this pull request Sep 13, 2025
@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 0e30e30 to 104551aCompareSeptember 14, 2025 20:44
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 5 days if no further activity occurs. Thank you for your contributions.

@github-actionsgithub-actionsBot added the stale Stale PRs per the .github/workflows/stale.yml policy file label Oct 30, 2025
@pierrejeambrun

Copy link
Copy Markdown
Member

Up

@pierrejeambrunpierrejeambrun removed the stale Stale PRs per the .github/workflows/stale.yml policy file label Oct 30, 2025
@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 104551a to 770c74fCompareNovember 11, 2025 20:19
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up for ~1200 commits :-D

@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 770c74f to f976a86CompareDecember 23, 2025 18:07
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up for ~720 commits :-D (again)

@jscheffl

Copy link
Copy Markdown
ContributorAuthor

@pierrejeambrun Interesting, still do not understand the root cause why a toaster is not working on Plugins pages but what I noticed in the browser is that there is a <div> element rendered for all pages which seems to hold the toaster below the root div element with the id="toast-group":
image

This one is missing on the Plugins page - and don't know if this helps in trigaing - but noticed when navigating to Admin -> Configs (url: /config) which is raising a forbidden error via HTTP 403, there also the toaster is not working with the explicit ybutton in the Nav.

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have to investigate. But my guess is that Chakra UI handles the toaster via 'portals' into a specific unique dom element that is global. So basically any toaster will render in that shared toast-group element.

Then there might be some sort of conflict, the plugin toast can't find the proper host element to portal the toast to.

I'm sorry for the delay and not finding time to look at this yet.

@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from f976a86 to 525a1cbCompareJanuary 31, 2026 20:16
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up by 700 commits

@bbovenzibbovenzi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave you pseudo code. Here is exactly what you need:

toaster.tsx:

import { Toaster as ChakraToaster, Portal, Spinner, Stack, Toast, createToaster } from "@chakra-ui/react";
import type { RefObject } from "react";
export const toaster = createToaster({
pauseOnPageIdle: true,
placement: "bottom-end",
});
export const Toaster = ({ containerRef }: { containerRef: RefObject<HTMLDivElement | null> }) => (
<Portal container={containerRef}>
<ChakraToaster toaster={toaster} insetInline={{ mdDown: "4" }}>
{(toast) => (
<Toast.Root width={{ md: "sm" }}>
{toast.type === "loading" ? <Spinner size="sm" color="blue.solid" /> : <Toast.Indicator />}
<Stack gap="1" flex="1" maxWidth="100%">
{toast.title && <Toast.Title>{toast.title}</Toast.Title>}
{toast.description && <Toast.Description>{toast.description}</Toast.Description>}
</Stack>
{toast.action && <Toast.ActionTrigger>{toast.action.label}</Toast.ActionTrigger>}
{toast.closable && <Toast.CloseTrigger />}
</Toast.Root>
)}
</ChakraToaster>
</Portal>
);

EdgeLayout.tsx:

import { Box } from "@chakra-ui/react";
import { useRef } from "react";
import { Navigate, Route, Routes } from "react-router-dom";
import { Toaster } from "src/components/ui";
import { JobsPage } from "src/pages/JobsPage";
import { WorkerPage } from "src/pages/WorkerPage";
import { NavTabs } from "./NavTabs";
export const EdgeLayout = () => {
const containerRef = useRef<HTMLDivElement>(null);
const tabs = [
{ label: "Edge Worker", value: "worker" },
{ label: "Edge Jobs", value: "jobs" },
];
return (
<Box ref={containerRef} p={2} /* Compensate for parent padding from ExternalView */>
<NavTabs tabs={tabs} />
<Routes>
<Route index element={<Navigate to="worker" replace />} />
<Route path="worker" element={<WorkerPage />} />
<Route path="jobs" element={<JobsPage />} />
</Routes>
<Toaster containerRef={containerRef} />
</Box>
);
};

@jscheffljscheffl changed the title [DO NOT MERGE] Attempt to fix Toaster in PluginFix Toaster in Plugin in Edge UIMar 1, 2026
@jscheffl
jscheffl marked this pull request as ready for review March 1, 2026 21:02
@jscheffljscheffl added the type:bug-fix Changelog: Bug Fixes label Mar 1, 2026
@bbovenzi
bbovenzi merged commit 3161a80 into apache:mainMar 2, 2026
120 of 123 checks passed
dominikhei pushed a commit to dominikhei/airflow that referenced this pull request Mar 11, 2026
* Attempt to fix Toaster in Plugin
* Attempt to fix via proposal
* Revert testing of toaster open
* Fix toaster using hints from Brent
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersarea:UIRelated to UI/UX. For Frontend Developers.provider:edgeEdge Executor / Worker (AIP-69) / edge3type:bug-fixChangelog: Bug Fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jscheffl@pierrejeambrun@bbovenzi
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Fix Toaster in Plugin in Edge UI by jscheffl · Pull Request #55641 · apache/airflow · GitHub
Skip to content

Fix Toaster in Plugin in Edge UI - #55641

Merged
bbovenzi merged 6 commits into
apache:mainfrom
jscheffl:bugfix/fix-toaster-in-plugin
Mar 2, 2026
Merged

Fix Toaster in Plugin in Edge UI#55641
bbovenzi merged 6 commits into
apache:mainfrom
jscheffl:bugfix/fix-toaster-in-plugin

Conversation

@jscheffl

@jscheffljscheffl commented Sep 13, 2025

Copy link
Copy Markdown
Contributor

With hints from @bbovenzi this PR now fixes the Toaster display in Edge Executor UI! Thanks! That was a longer endeavor.

This is how it looks now after the fix... toaster content/logic was in all the time already...

edge-toaster-fix-2026-03-01_21.59.59.mp4

Previous PR Intro:

There is a teething problem that the Chakra "Toast" component is not working in Edge React UI. I need some React Expertise to fix it seems.

@shubhamraj-git / @bbovenzi / @pierrejeambrun HELP :-D

To make this reprodicible I made two toasters:
1 in the Navbar and one in te Edge UI plugin.

How to see the error:

  1. Take this branch
  2. Run it locally via breeze start-airflow --python 3.12 --backend postgres --executor EdgeExecutor --load-example-dags
  3. Open the Web UI and after login on the start page, click on the "Toast" button in the Navbar - all OK
  4. Navifate to "Admin" -> "Edge Worker Hosts" (Which is the React Plugin)
  5. Click the same button --> Does not respond. See JavaScript console that logs are written and no errors
  6. Attempt to click on the Toaster Test button in the Plugin itself, also not working
  7. Same if you use the IFrame plugin in "Docs" -> "Edge API Docs", also there the Toaster in Navbar is not working

Is this a limitation of the plugin concept or a bug in my Plugin? How can the Toaster be made working?

@boring-cyborgboring-cyborgBot added area:providers area:UI Related to UI/UX. For Frontend Developers. provider:edge Edge Executor / Worker (AIP-69) / edge3 labels Sep 13, 2025
@jscheffljscheffl mentioned this pull request Sep 13, 2025
@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 0e30e30 to 104551aCompareSeptember 14, 2025 20:44
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 5 days if no further activity occurs. Thank you for your contributions.

@github-actionsgithub-actionsBot added the stale Stale PRs per the .github/workflows/stale.yml policy file label Oct 30, 2025
@pierrejeambrun

Copy link
Copy Markdown
Member

Up

@pierrejeambrunpierrejeambrun removed the stale Stale PRs per the .github/workflows/stale.yml policy file label Oct 30, 2025
@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 104551a to 770c74fCompareNovember 11, 2025 20:19
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up for ~1200 commits :-D

@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 770c74f to f976a86CompareDecember 23, 2025 18:07
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up for ~720 commits :-D (again)

@jscheffl

Copy link
Copy Markdown
ContributorAuthor

@pierrejeambrun Interesting, still do not understand the root cause why a toaster is not working on Plugins pages but what I noticed in the browser is that there is a <div> element rendered for all pages which seems to hold the toaster below the root div element with the id="toast-group":
image

This one is missing on the Plugins page - and don't know if this helps in trigaing - but noticed when navigating to Admin -> Configs (url: /config) which is raising a forbidden error via HTTP 403, there also the toaster is not working with the explicit ybutton in the Nav.

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have to investigate. But my guess is that Chakra UI handles the toaster via 'portals' into a specific unique dom element that is global. So basically any toaster will render in that shared toast-group element.

Then there might be some sort of conflict, the plugin toast can't find the proper host element to portal the toast to.

I'm sorry for the delay and not finding time to look at this yet.

@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from f976a86 to 525a1cbCompareJanuary 31, 2026 20:16
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up by 700 commits

@bbovenzibbovenzi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave you pseudo code. Here is exactly what you need:

toaster.tsx:

import { Toaster as ChakraToaster, Portal, Spinner, Stack, Toast, createToaster } from "@chakra-ui/react";
import type { RefObject } from "react";
export const toaster = createToaster({
pauseOnPageIdle: true,
placement: "bottom-end",
});
export const Toaster = ({ containerRef }: { containerRef: RefObject<HTMLDivElement | null> }) => (
<Portal container={containerRef}>
<ChakraToaster toaster={toaster} insetInline={{ mdDown: "4" }}>
{(toast) => (
<Toast.Root width={{ md: "sm" }}>
{toast.type === "loading" ? <Spinner size="sm" color="blue.solid" /> : <Toast.Indicator />}
<Stack gap="1" flex="1" maxWidth="100%">
{toast.title && <Toast.Title>{toast.title}</Toast.Title>}
{toast.description && <Toast.Description>{toast.description}</Toast.Description>}
</Stack>
{toast.action && <Toast.ActionTrigger>{toast.action.label}</Toast.ActionTrigger>}
{toast.closable && <Toast.CloseTrigger />}
</Toast.Root>
)}
</ChakraToaster>
</Portal>
);

EdgeLayout.tsx:

import { Box } from "@chakra-ui/react";
import { useRef } from "react";
import { Navigate, Route, Routes } from "react-router-dom";
import { Toaster } from "src/components/ui";
import { JobsPage } from "src/pages/JobsPage";
import { WorkerPage } from "src/pages/WorkerPage";
import { NavTabs } from "./NavTabs";
export const EdgeLayout = () => {
const containerRef = useRef<HTMLDivElement>(null);
const tabs = [
{ label: "Edge Worker", value: "worker" },
{ label: "Edge Jobs", value: "jobs" },
];
return (
<Box ref={containerRef} p={2} /* Compensate for parent padding from ExternalView */>
<NavTabs tabs={tabs} />
<Routes>
<Route index element={<Navigate to="worker" replace />} />
<Route path="worker" element={<WorkerPage />} />
<Route path="jobs" element={<JobsPage />} />
</Routes>
<Toaster containerRef={containerRef} />
</Box>
);
};

@jscheffljscheffl changed the title [DO NOT MERGE] Attempt to fix Toaster in PluginFix Toaster in Plugin in Edge UIMar 1, 2026
@jscheffl
jscheffl marked this pull request as ready for review March 1, 2026 21:02
@jscheffljscheffl added the type:bug-fix Changelog: Bug Fixes label Mar 1, 2026
@bbovenzi
bbovenzi merged commit 3161a80 into apache:mainMar 2, 2026
120 of 123 checks passed
dominikhei pushed a commit to dominikhei/airflow that referenced this pull request Mar 11, 2026
* Attempt to fix Toaster in Plugin
* Attempt to fix via proposal
* Revert testing of toaster open
* Fix toaster using hints from Brent
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersarea:UIRelated to UI/UX. For Frontend Developers.provider:edgeEdge Executor / Worker (AIP-69) / edge3type:bug-fixChangelog: Bug Fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jscheffl@pierrejeambrun@bbovenzi
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Fix Toaster in Plugin in Edge UI by jscheffl · Pull Request #55641 · apache/airflow · GitHub
Skip to content

Fix Toaster in Plugin in Edge UI - #55641

Merged
bbovenzi merged 6 commits into
apache:mainfrom
jscheffl:bugfix/fix-toaster-in-plugin
Mar 2, 2026
Merged

Fix Toaster in Plugin in Edge UI#55641
bbovenzi merged 6 commits into
apache:mainfrom
jscheffl:bugfix/fix-toaster-in-plugin

Conversation

@jscheffl

@jscheffljscheffl commented Sep 13, 2025

Copy link
Copy Markdown
Contributor

With hints from @bbovenzi this PR now fixes the Toaster display in Edge Executor UI! Thanks! That was a longer endeavor.

This is how it looks now after the fix... toaster content/logic was in all the time already...

edge-toaster-fix-2026-03-01_21.59.59.mp4

Previous PR Intro:

There is a teething problem that the Chakra "Toast" component is not working in Edge React UI. I need some React Expertise to fix it seems.

@shubhamraj-git / @bbovenzi / @pierrejeambrun HELP :-D

To make this reprodicible I made two toasters:
1 in the Navbar and one in te Edge UI plugin.

How to see the error:

  1. Take this branch
  2. Run it locally via breeze start-airflow --python 3.12 --backend postgres --executor EdgeExecutor --load-example-dags
  3. Open the Web UI and after login on the start page, click on the "Toast" button in the Navbar - all OK
  4. Navifate to "Admin" -> "Edge Worker Hosts" (Which is the React Plugin)
  5. Click the same button --> Does not respond. See JavaScript console that logs are written and no errors
  6. Attempt to click on the Toaster Test button in the Plugin itself, also not working
  7. Same if you use the IFrame plugin in "Docs" -> "Edge API Docs", also there the Toaster in Navbar is not working

Is this a limitation of the plugin concept or a bug in my Plugin? How can the Toaster be made working?

@boring-cyborgboring-cyborgBot added area:providers area:UI Related to UI/UX. For Frontend Developers. provider:edge Edge Executor / Worker (AIP-69) / edge3 labels Sep 13, 2025
@jscheffljscheffl mentioned this pull request Sep 13, 2025
@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 0e30e30 to 104551aCompareSeptember 14, 2025 20:44
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 5 days if no further activity occurs. Thank you for your contributions.

@github-actionsgithub-actionsBot added the stale Stale PRs per the .github/workflows/stale.yml policy file label Oct 30, 2025
@pierrejeambrun

Copy link
Copy Markdown
Member

Up

@pierrejeambrunpierrejeambrun removed the stale Stale PRs per the .github/workflows/stale.yml policy file label Oct 30, 2025
@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 104551a to 770c74fCompareNovember 11, 2025 20:19
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up for ~1200 commits :-D

@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 770c74f to f976a86CompareDecember 23, 2025 18:07
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up for ~720 commits :-D (again)

@jscheffl

Copy link
Copy Markdown
ContributorAuthor

@pierrejeambrun Interesting, still do not understand the root cause why a toaster is not working on Plugins pages but what I noticed in the browser is that there is a <div> element rendered for all pages which seems to hold the toaster below the root div element with the id="toast-group":
image

This one is missing on the Plugins page - and don't know if this helps in trigaing - but noticed when navigating to Admin -> Configs (url: /config) which is raising a forbidden error via HTTP 403, there also the toaster is not working with the explicit ybutton in the Nav.

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have to investigate. But my guess is that Chakra UI handles the toaster via 'portals' into a specific unique dom element that is global. So basically any toaster will render in that shared toast-group element.

Then there might be some sort of conflict, the plugin toast can't find the proper host element to portal the toast to.

I'm sorry for the delay and not finding time to look at this yet.

@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from f976a86 to 525a1cbCompareJanuary 31, 2026 20:16
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up by 700 commits

@bbovenzibbovenzi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave you pseudo code. Here is exactly what you need:

toaster.tsx:

import { Toaster as ChakraToaster, Portal, Spinner, Stack, Toast, createToaster } from "@chakra-ui/react";
import type { RefObject } from "react";
export const toaster = createToaster({
pauseOnPageIdle: true,
placement: "bottom-end",
});
export const Toaster = ({ containerRef }: { containerRef: RefObject<HTMLDivElement | null> }) => (
<Portal container={containerRef}>
<ChakraToaster toaster={toaster} insetInline={{ mdDown: "4" }}>
{(toast) => (
<Toast.Root width={{ md: "sm" }}>
{toast.type === "loading" ? <Spinner size="sm" color="blue.solid" /> : <Toast.Indicator />}
<Stack gap="1" flex="1" maxWidth="100%">
{toast.title && <Toast.Title>{toast.title}</Toast.Title>}
{toast.description && <Toast.Description>{toast.description}</Toast.Description>}
</Stack>
{toast.action && <Toast.ActionTrigger>{toast.action.label}</Toast.ActionTrigger>}
{toast.closable && <Toast.CloseTrigger />}
</Toast.Root>
)}
</ChakraToaster>
</Portal>
);

EdgeLayout.tsx:

import { Box } from "@chakra-ui/react";
import { useRef } from "react";
import { Navigate, Route, Routes } from "react-router-dom";
import { Toaster } from "src/components/ui";
import { JobsPage } from "src/pages/JobsPage";
import { WorkerPage } from "src/pages/WorkerPage";
import { NavTabs } from "./NavTabs";
export const EdgeLayout = () => {
const containerRef = useRef<HTMLDivElement>(null);
const tabs = [
{ label: "Edge Worker", value: "worker" },
{ label: "Edge Jobs", value: "jobs" },
];
return (
<Box ref={containerRef} p={2} /* Compensate for parent padding from ExternalView */>
<NavTabs tabs={tabs} />
<Routes>
<Route index element={<Navigate to="worker" replace />} />
<Route path="worker" element={<WorkerPage />} />
<Route path="jobs" element={<JobsPage />} />
</Routes>
<Toaster containerRef={containerRef} />
</Box>
);
};

@jscheffljscheffl changed the title [DO NOT MERGE] Attempt to fix Toaster in PluginFix Toaster in Plugin in Edge UIMar 1, 2026
@jscheffl
jscheffl marked this pull request as ready for review March 1, 2026 21:02
@jscheffljscheffl added the type:bug-fix Changelog: Bug Fixes label Mar 1, 2026
@bbovenzi
bbovenzi merged commit 3161a80 into apache:mainMar 2, 2026
120 of 123 checks passed
dominikhei pushed a commit to dominikhei/airflow that referenced this pull request Mar 11, 2026
* Attempt to fix Toaster in Plugin
* Attempt to fix via proposal
* Revert testing of toaster open
* Fix toaster using hints from Brent
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersarea:UIRelated to UI/UX. For Frontend Developers.provider:edgeEdge Executor / Worker (AIP-69) / edge3type:bug-fixChangelog: Bug Fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jscheffl@pierrejeambrun@bbovenzi
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Fix Toaster in Plugin in Edge UI by jscheffl · Pull Request #55641 · apache/airflow · GitHub
Skip to content

Fix Toaster in Plugin in Edge UI - #55641

Merged
bbovenzi merged 6 commits into
apache:mainfrom
jscheffl:bugfix/fix-toaster-in-plugin
Mar 2, 2026
Merged

Fix Toaster in Plugin in Edge UI#55641
bbovenzi merged 6 commits into
apache:mainfrom
jscheffl:bugfix/fix-toaster-in-plugin

Conversation

@jscheffl

@jscheffljscheffl commented Sep 13, 2025

Copy link
Copy Markdown
Contributor

With hints from @bbovenzi this PR now fixes the Toaster display in Edge Executor UI! Thanks! That was a longer endeavor.

This is how it looks now after the fix... toaster content/logic was in all the time already...

edge-toaster-fix-2026-03-01_21.59.59.mp4

Previous PR Intro:

There is a teething problem that the Chakra "Toast" component is not working in Edge React UI. I need some React Expertise to fix it seems.

@shubhamraj-git / @bbovenzi / @pierrejeambrun HELP :-D

To make this reprodicible I made two toasters:
1 in the Navbar and one in te Edge UI plugin.

How to see the error:

  1. Take this branch
  2. Run it locally via breeze start-airflow --python 3.12 --backend postgres --executor EdgeExecutor --load-example-dags
  3. Open the Web UI and after login on the start page, click on the "Toast" button in the Navbar - all OK
  4. Navifate to "Admin" -> "Edge Worker Hosts" (Which is the React Plugin)
  5. Click the same button --> Does not respond. See JavaScript console that logs are written and no errors
  6. Attempt to click on the Toaster Test button in the Plugin itself, also not working
  7. Same if you use the IFrame plugin in "Docs" -> "Edge API Docs", also there the Toaster in Navbar is not working

Is this a limitation of the plugin concept or a bug in my Plugin? How can the Toaster be made working?

@boring-cyborgboring-cyborgBot added area:providers area:UI Related to UI/UX. For Frontend Developers. provider:edge Edge Executor / Worker (AIP-69) / edge3 labels Sep 13, 2025
@jscheffljscheffl mentioned this pull request Sep 13, 2025
@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 0e30e30 to 104551aCompareSeptember 14, 2025 20:44
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 5 days if no further activity occurs. Thank you for your contributions.

@github-actionsgithub-actionsBot added the stale Stale PRs per the .github/workflows/stale.yml policy file label Oct 30, 2025
@pierrejeambrun

Copy link
Copy Markdown
Member

Up

@pierrejeambrunpierrejeambrun removed the stale Stale PRs per the .github/workflows/stale.yml policy file label Oct 30, 2025
@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 104551a to 770c74fCompareNovember 11, 2025 20:19
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up for ~1200 commits :-D

@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from 770c74f to f976a86CompareDecember 23, 2025 18:07
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up for ~720 commits :-D (again)

@jscheffl

Copy link
Copy Markdown
ContributorAuthor

@pierrejeambrun Interesting, still do not understand the root cause why a toaster is not working on Plugins pages but what I noticed in the browser is that there is a <div> element rendered for all pages which seems to hold the toaster below the root div element with the id="toast-group":
image

This one is missing on the Plugins page - and don't know if this helps in trigaing - but noticed when navigating to Admin -> Configs (url: /config) which is raising a forbidden error via HTTP 403, there also the toaster is not working with the explicit ybutton in the Nav.

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have to investigate. But my guess is that Chakra UI handles the toaster via 'portals' into a specific unique dom element that is global. So basically any toaster will render in that shared toast-group element.

Then there might be some sort of conflict, the plugin toast can't find the proper host element to portal the toast to.

I'm sorry for the delay and not finding time to look at this yet.

@jscheffl
jschefflforce-pushed the bugfix/fix-toaster-in-plugin branch from f976a86 to 525a1cbCompareJanuary 31, 2026 20:16
@jscheffl

Copy link
Copy Markdown
ContributorAuthor

up by 700 commits

@bbovenzibbovenzi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave you pseudo code. Here is exactly what you need:

toaster.tsx:

import { Toaster as ChakraToaster, Portal, Spinner, Stack, Toast, createToaster } from "@chakra-ui/react";
import type { RefObject } from "react";
export const toaster = createToaster({
pauseOnPageIdle: true,
placement: "bottom-end",
});
export const Toaster = ({ containerRef }: { containerRef: RefObject<HTMLDivElement | null> }) => (
<Portal container={containerRef}>
<ChakraToaster toaster={toaster} insetInline={{ mdDown: "4" }}>
{(toast) => (
<Toast.Root width={{ md: "sm" }}>
{toast.type === "loading" ? <Spinner size="sm" color="blue.solid" /> : <Toast.Indicator />}
<Stack gap="1" flex="1" maxWidth="100%">
{toast.title && <Toast.Title>{toast.title}</Toast.Title>}
{toast.description && <Toast.Description>{toast.description}</Toast.Description>}
</Stack>
{toast.action && <Toast.ActionTrigger>{toast.action.label}</Toast.ActionTrigger>}
{toast.closable && <Toast.CloseTrigger />}
</Toast.Root>
)}
</ChakraToaster>
</Portal>
);

EdgeLayout.tsx:

import { Box } from "@chakra-ui/react";
import { useRef } from "react";
import { Navigate, Route, Routes } from "react-router-dom";
import { Toaster } from "src/components/ui";
import { JobsPage } from "src/pages/JobsPage";
import { WorkerPage } from "src/pages/WorkerPage";
import { NavTabs } from "./NavTabs";
export const EdgeLayout = () => {
const containerRef = useRef<HTMLDivElement>(null);
const tabs = [
{ label: "Edge Worker", value: "worker" },
{ label: "Edge Jobs", value: "jobs" },
];
return (
<Box ref={containerRef} p={2} /* Compensate for parent padding from ExternalView */>
<NavTabs tabs={tabs} />
<Routes>
<Route index element={<Navigate to="worker" replace />} />
<Route path="worker" element={<WorkerPage />} />
<Route path="jobs" element={<JobsPage />} />
</Routes>
<Toaster containerRef={containerRef} />
</Box>
);
};

@jscheffljscheffl changed the title [DO NOT MERGE] Attempt to fix Toaster in PluginFix Toaster in Plugin in Edge UIMar 1, 2026
@jscheffl
jscheffl marked this pull request as ready for review March 1, 2026 21:02
@jscheffljscheffl added the type:bug-fix Changelog: Bug Fixes label Mar 1, 2026
@bbovenzi
bbovenzi merged commit 3161a80 into apache:mainMar 2, 2026
120 of 123 checks passed
dominikhei pushed a commit to dominikhei/airflow that referenced this pull request Mar 11, 2026
* Attempt to fix Toaster in Plugin
* Attempt to fix via proposal
* Revert testing of toaster open
* Fix toaster using hints from Brent
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersarea:UIRelated to UI/UX. For Frontend Developers.provider:edgeEdge Executor / Worker (AIP-69) / edge3type:bug-fixChangelog: Bug Fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@jscheffl@pierrejeambrun@bbovenzi