-
+
Workspace
diff --git a/apps/web/src/components/BranchToolbarEnvironmentSelector.tsx b/apps/web/src/components/BranchToolbarEnvironmentSelector.tsx
index 6304e37cf88d29be60f031b0579d8149d264d16b..fabda55688bcf6f8be44bd2ef04087affcff0338 100644
--- a/apps/web/src/components/BranchToolbarEnvironmentSelector.tsx
+++ b/apps/web/src/components/BranchToolbarEnvironmentSelector.tsx
@@ -3,6 +3,7 @@ import { memo, useMemo } from "react";
import type { EnvironmentOption } from "./BranchToolbar.logic";
import { EnvironmentMachineIcon } from "./EnvironmentMachineIcon";
+import { composerFloatingLayerProps } from "./chat/composerEventScope";
import {
Select,
SelectGroup,
@@ -101,7 +102,7 @@ export const BranchToolbarEnvironmentSelector = memo(function BranchToolbarEnvir
-
+
Run on
{availableEnvironments.map((env) => (
diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx
index 5f8376b431f74f40491d7d343d32f69bbc805983..90da57b948c404c5b05700ff1a74685ce0932766 100644
--- a/apps/web/src/components/chat/ChatComposer.tsx
+++ b/apps/web/src/components/chat/ChatComposer.tsx
@@ -4283,7 +4283,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps)
const composerSurface = composerSurfaceRef.current;
const composerForm = composerFormRef.current;
const activeElement = document.activeElement;
- if (activeElement instanceof Element && isInsideComposerFloatingLayer(activeElement)) {
+ if (isInsideRestingComposerControlScope(activeElement)) {
return;
}
if (
@@ -4303,8 +4303,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps)
const isInsideDesktopComposerFocusScope = (target: EventTarget | null) =>
Boolean(
target instanceof Node &&
- (composerFormRef.current?.contains(target) ||
- (target instanceof Element && isInsideComposerFloatingLayer(target))),
+ (composerFormRef.current?.contains(target) || isInsideRestingComposerControlScope(target)),
);
const handleFocusIn = (event: FocusEvent) => {
if (!isInsideDesktopComposerFocusScope(event.target)) {
diff --git a/apps/web/src/components/chat/composerEventScope.test.ts b/apps/web/src/components/chat/composerEventScope.test.ts
index b559009ed43f23618be8345ed01aa7ed38d447a9..365c5304aa2dd33741aca3daa451a50e4b26a24e 100644
--- a/apps/web/src/components/chat/composerEventScope.test.ts
+++ b/apps/web/src/components/chat/composerEventScope.test.ts
@@ -29,6 +29,13 @@ describe("composer event scopes", () => {
expect(isInsideRestingComposerControlScope(target as unknown as EventTarget)).toBe(true);
});
+ it("recognizes events from the composer context strip controls", () => {
+ vi.stubGlobal("Element", FakeElement);
+
+ const target = new FakeElement("[data-composer-context-control]");
+ expect(isInsideRestingComposerControlScope(target as unknown as EventTarget)).toBe(true);
+ });
+
it("keeps resting image previews focused without expanding their subtree", () => {
vi.stubGlobal("Element", FakeElement);
diff --git a/apps/web/src/components/chat/composerEventScope.ts b/apps/web/src/components/chat/composerEventScope.ts
index 60aedb09615675568e2971a5cc2675c63f23666c..88e24fd89422977d4ced41785f2b007405189e5a 100644
--- a/apps/web/src/components/chat/composerEventScope.ts
+++ b/apps/web/src/components/chat/composerEventScope.ts
@@ -26,6 +26,7 @@ export function isInsideRestingComposerControlScope(target: EventTarget | null):
target instanceof Element &&
(target.closest('[data-chat-composer-resting-controls="true"]') !== null ||
target.closest('[data-chat-composer-resting-images="true"]') !== null ||
+ target.closest("[data-composer-context-control]") !== null ||
isInsideComposerFloatingLayer(target))
);
}