From f340da98aeaaf2d7c343d34fe5d5d8f16c9cfe3f Mon Sep 17 00:00:00 2001 From: lstockmann Date: Tue, 1 Sep 2026 11:43:49 +0200 Subject: [PATCH 1/9] feat(Badge): support a button after the text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A Button, CopyButton, Action, ContextualHelpTrigger or ModalTrigger in the badge content is moved to the end of the badge and rendered like the onClose icon. With both, the close icon stays rightmost. Triggers move along with their button — a button tunneled out on its own mounts outside the trigger and loses its press behavior. Co-Authored-By: Claude Opus 5 --- .../status/badge/examples/contextualHelp.tsx | 22 +++ .../content/components/status/badge/index.mdx | 8 +- .../components/Badge/Badge.browser.test.tsx | 161 ++++++++++++++++++ .../components/Badge/Badge.module.d.scss.ts | 1 + .../src/components/Badge/Badge.module.scss | 47 ++++- .../components/src/components/Badge/Badge.tsx | 50 +++++- .../Badge/stories/Default.stories.tsx | 44 +++++ .../src/tests/visual/Badge.browser.test.tsx | 82 +++++++++ .../Badge-actions-firefox-darwin.png | Bin 0 -> 25954 bytes .../Badge-actions-webkit-darwin.png | Bin 0 -> 25580 bytes 10 files changed, 406 insertions(+), 9 deletions(-) create mode 100644 apps/docs/src/content/components/status/badge/examples/contextualHelp.tsx create mode 100644 packages/components/src/components/Badge/Badge.browser.test.tsx create mode 100644 packages/remote-react-components/src/tests/visual/__screenshots__/Badge.browser.test.tsx/Badge-actions-firefox-darwin.png create mode 100644 packages/remote-react-components/src/tests/visual/__screenshots__/Badge.browser.test.tsx/Badge-actions-webkit-darwin.png diff --git a/apps/docs/src/content/components/status/badge/examples/contextualHelp.tsx b/apps/docs/src/content/components/status/badge/examples/contextualHelp.tsx new file mode 100644 index 0000000000..7a18788e26 --- /dev/null +++ b/apps/docs/src/content/components/status/badge/examples/contextualHelp.tsx @@ -0,0 +1,22 @@ +import { + Badge, + Button, + ContextualHelp, + ContextualHelpTrigger, + Label, + Text, +} from "@mittwald/flow-react-components"; + + + + Hoch + + + , + ); + + const button = screen + .getByRole("button", { name: "More information" }) + .element() + .getBoundingClientRect(); + const closeButton = screen + .getByRole("button", { name: "Remove" }) + .element() + .getBoundingClientRect(); + + expect(button.width).toBe(closeButton.width); + expect(button.height).toBe(closeButton.height); + expect(button.top).toBe(closeButton.top); + expect(button.right).toBe(closeButton.left); +}); + +test("A copy button in the content is placed before the close button", async () => { + const screen = await render( + undefined}> + Value + + , + ); + + const badge = badgeOf(screen.container); + const copyButton = screen.getByRole("button", { name: "Copy" }).element(); + const closeButton = screen.getByRole("button", { name: "Remove" }).element(); + + expect(copyButton.parentElement).toBe(badge); + expect(closeButton.previousElementSibling).toBe(copyButton); +}); + +test("An action in the content keeps its button working", async () => { + const onAction = vi.fn(); + + const screen = await render( + + Value + + )} + + {onClose && ( - , - ); - - const button = screen - .getByRole("button", { name: "More information" }) - .element() - .getBoundingClientRect(); - const closeButton = screen - .getByRole("button", { name: "Remove" }) - .element() - .getBoundingClientRect(); - - expect(button.width).toBe(closeButton.width); - expect(button.height).toBe(closeButton.height); - expect(button.top).toBe(closeButton.top); - expect(button.right).toBe(closeButton.left); -}); - -test("A copy button in the content is placed before the close button", async () => { - const screen = await render( - undefined}> - Value - - , - ); - - const badge = badgeOf(screen.container); - const copyButton = screen.getByRole("button", { name: "Copy" }).element(); - const closeButton = screen.getByRole("button", { name: "Remove" }).element(); - - expect(copyButton.parentElement).toBe(badge); - expect(closeButton.previousElementSibling).toBe(copyButton); -}); - test("An action in the content keeps its button working", async () => { const onAction = vi.fn(); const screen = await render( - + Value )} - + {onClose && (