Label the composer's computer button and move it after the tools

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-19 16:09:21 +01:00
co-authored by Claude Opus 5.5
parent 9b55ef793b
commit e157863cfb
2 changed files with 35 additions and 6 deletions
@@ -2,6 +2,7 @@ import { useContext } from "react";
import Button from "@moduletrace/twui/layout/Button"; import Button from "@moduletrace/twui/layout/Button";
import { Monitor } from "lucide-react"; import { Monitor } from "lucide-react";
import { BotComputersContext } from "../(data)/bot-computers-context"; import { BotComputersContext } from "../(data)/bot-computers-context";
import Span from "@moduletrace/twui/layout/Span";
/** /**
* Beside the composer's tools: opens the computer the bot is on in the * Beside the composer's tools: opens the computer the bot is on in the
@@ -24,9 +25,14 @@ export default function ComposerComputerButton() {
variant="ghost" variant="ghost"
color="gray" color="gray"
size="small" size="small"
onClick={() => openComputer({ computer_id: computer.id || 0, mode: "browser" })} onClick={() =>
openComputer({ computer_id: computer.id || 0, mode: "browser" })
}
className="shrink-0 px-1.5! py-0.5! text-ink-secondary dark:text-ink-secondary hover:text-ink hover:dark:text-ink" className="shrink-0 px-1.5! py-0.5! text-ink-secondary dark:text-ink-secondary hover:text-ink hover:dark:text-ink"
> >
<Span className="text-[12px] leading-4 text-ink-secondary">
Computer
</Span>
<Monitor size={14} aria-hidden /> <Monitor size={14} aria-hidden />
</Button> </Button>
); );
@@ -7,6 +7,7 @@ import { BotComputersContext } from "../(data)/bot-computers-context";
import ComposerAddToolModal from "./composer-add-tool-modal"; import ComposerAddToolModal from "./composer-add-tool-modal";
import ComposerComputerButton from "./composer-computer-button"; import ComposerComputerButton from "./composer-computer-button";
import ComposerToolChip from "./composer-tool-chip"; import ComposerToolChip from "./composer-tool-chip";
import { Dot } from "lucide-react";
type Props = { type Props = {
bot: BotWithLastMessage; bot: BotWithLastMessage;
@@ -29,14 +30,20 @@ export default function ComposerTools({ bot, workspace_id, initial }: Props) {
const { computers } = useContext(BotComputersContext); const { computers } = useContext(BotComputersContext);
const has_tools = Boolean(extensions.attached.length || (extensions.can_manage && extensions.addable.length)); const has_tools = Boolean(
extensions.attached.length ||
(extensions.can_manage && extensions.addable.length),
);
if (!has_tools && !computers.length) return null; if (!has_tools && !computers.length) return null;
return ( return (
<Row className="w-full max-w-container mx-auto gap-1.5! items-center px-6 pb-3 -mt-3"> <Row className="w-full max-w-container mx-auto gap-1.5! items-center px-6 pb-3 -mt-3">
<ComposerComputerButton /> {has_tools ? (
{has_tools ? <Span className="text-[12px] leading-4 text-ink-secondary">Tools</Span> : null} <Span className="text-[12px] leading-4 text-ink-secondary">
Tools
</Span>
) : null}
{extensions.attached.map((item) => ( {extensions.attached.map((item) => (
<ComposerToolChip <ComposerToolChip
key={`${item.kind}:${item.id}`} key={`${item.kind}:${item.id}`}
@@ -44,11 +51,24 @@ export default function ComposerTools({ bot, workspace_id, initial }: Props) {
busy={extensions.busy == `${item.kind}:${item.id}`} busy={extensions.busy == `${item.kind}:${item.id}`}
onRemove={ onRemove={
extensions.can_manage && item.source == "bot" extensions.can_manage && item.source == "bot"
? () => extensions.remove({ kind: item.kind, id: item.id, name: item.name }) ? () =>
extensions.remove({
kind: item.kind,
id: item.id,
name: item.name,
})
: undefined : undefined
} }
/> />
))} ))}
{has_tools ? (
<Span className="-mr-2 opacity-40">
<Dot size={20} />
</Span>
) : null}
<ComposerComputerButton />
{extensions.can_manage ? ( {extensions.can_manage ? (
<ComposerAddToolModal <ComposerAddToolModal
bot_name={bot.name || "This bot"} bot_name={bot.name || "This bot"}
@@ -58,7 +78,10 @@ export default function ComposerTools({ bot, workspace_id, initial }: Props) {
/> />
) : null} ) : null}
{extensions.status?.error ? ( {extensions.status?.error ? (
<Span role="alert" className="text-[12px] leading-4 text-ink-secondary"> <Span
role="alert"
className="text-[12px] leading-4 text-ink-secondary"
>
{extensions.status.msg} {extensions.status.msg}
</Span> </Span>
) : null} ) : null}