mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-31 08:13:11 +03:00
fix(webui): compact single-pane chat header
This commit is contained in:
@@ -2816,6 +2816,7 @@ function Shell({
|
|||||||
hostChromeTitleInset={hostSidebarCollapsed}
|
hostChromeTitleInset={hostSidebarCollapsed}
|
||||||
hideThemeButton={!context.active}
|
hideThemeButton={!context.active}
|
||||||
hideHeaderTitle
|
hideHeaderTitle
|
||||||
|
inlineHandle={workbenchPaneSessions.length > 1}
|
||||||
headerActions={context.headerActions}
|
headerActions={context.headerActions}
|
||||||
headerPortalTarget={context.headerPortalTarget}
|
headerPortalTarget={context.headerPortalTarget}
|
||||||
headerActive={context.active}
|
headerActive={context.active}
|
||||||
|
|||||||
@@ -346,6 +346,7 @@ interface ThreadShellProps {
|
|||||||
hostChromeTitleInset?: boolean;
|
hostChromeTitleInset?: boolean;
|
||||||
hideThemeButton?: boolean;
|
hideThemeButton?: boolean;
|
||||||
hideHeaderTitle?: boolean;
|
hideHeaderTitle?: boolean;
|
||||||
|
inlineHandle?: boolean;
|
||||||
hideHeader?: boolean;
|
hideHeader?: boolean;
|
||||||
headerActions?: ReactNode;
|
headerActions?: ReactNode;
|
||||||
headerPortalTarget?: HTMLElement | null;
|
headerPortalTarget?: HTMLElement | null;
|
||||||
@@ -645,6 +646,7 @@ export function ThreadShell({
|
|||||||
hostChromeTitleInset = false,
|
hostChromeTitleInset = false,
|
||||||
hideThemeButton = false,
|
hideThemeButton = false,
|
||||||
hideHeaderTitle = false,
|
hideHeaderTitle = false,
|
||||||
|
inlineHandle = false,
|
||||||
hideHeader = false,
|
hideHeader = false,
|
||||||
headerActions,
|
headerActions,
|
||||||
headerPortalTarget,
|
headerPortalTarget,
|
||||||
@@ -1614,7 +1616,7 @@ export function ThreadShell({
|
|||||||
const threadHeader = !hideHeader ? (
|
const threadHeader = !hideHeader ? (
|
||||||
<ThreadHeader
|
<ThreadHeader
|
||||||
title={title}
|
title={title}
|
||||||
handle={temporary || hideHeaderTitle ? null : session?.handle}
|
handle={temporary || (hideHeaderTitle && inlineHandle) ? null : session?.handle}
|
||||||
onToggleSidebar={onToggleSidebar}
|
onToggleSidebar={onToggleSidebar}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
onToggleTheme={onToggleTheme}
|
onToggleTheme={onToggleTheme}
|
||||||
@@ -1638,7 +1640,7 @@ export function ThreadShell({
|
|||||||
return (
|
return (
|
||||||
<section ref={shellRef} className="relative flex min-h-0 flex-1 overflow-hidden">
|
<section ref={shellRef} className="relative flex min-h-0 flex-1 overflow-hidden">
|
||||||
<div className="relative flex min-w-0 flex-1 flex-col overflow-hidden">
|
<div className="relative flex min-w-0 flex-1 flex-col overflow-hidden">
|
||||||
{hideHeaderTitle && !temporary && session?.handle ? (
|
{hideHeaderTitle && inlineHandle && !temporary && session?.handle ? (
|
||||||
<div
|
<div
|
||||||
aria-label={`Session @${session.handle.name}`}
|
aria-label={`Session @${session.handle.name}`}
|
||||||
className="flex h-8 shrink-0 items-center px-3 text-[12px]"
|
className="flex h-8 shrink-0 items-center px-3 text-[12px]"
|
||||||
|
|||||||
@@ -417,6 +417,52 @@ describe("ThreadShell", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("moves the session handle into the pane only when the workbench is split", () => {
|
||||||
|
const client = makeClient();
|
||||||
|
const portal = document.createElement("div");
|
||||||
|
document.body.append(portal);
|
||||||
|
const activeSession = {
|
||||||
|
...session("pane-handle"),
|
||||||
|
handle: {
|
||||||
|
id: "handle_11111111111111111111111111111111",
|
||||||
|
name: "soro",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const { unmount } = render(wrap(
|
||||||
|
client,
|
||||||
|
<ThreadShell
|
||||||
|
session={activeSession}
|
||||||
|
title="Single pane"
|
||||||
|
onToggleSidebar={() => {}}
|
||||||
|
hideHeaderTitle
|
||||||
|
headerPortalTarget={portal}
|
||||||
|
/>,
|
||||||
|
));
|
||||||
|
|
||||||
|
expect(within(portal).getByText("@soro")).toBeInTheDocument();
|
||||||
|
expect(screen.queryByLabelText("Session @soro")).not.toBeInTheDocument();
|
||||||
|
|
||||||
|
unmount();
|
||||||
|
const splitView = render(wrap(
|
||||||
|
client,
|
||||||
|
<ThreadShell
|
||||||
|
session={activeSession}
|
||||||
|
title="Split pane"
|
||||||
|
onToggleSidebar={() => {}}
|
||||||
|
hideHeaderTitle
|
||||||
|
inlineHandle
|
||||||
|
headerPortalTarget={portal}
|
||||||
|
/>,
|
||||||
|
));
|
||||||
|
|
||||||
|
expect(screen.getByLabelText("Session @soro")).toHaveTextContent("@soro");
|
||||||
|
expect(within(portal).queryByText("@soro")).not.toBeInTheDocument();
|
||||||
|
|
||||||
|
splitView.unmount();
|
||||||
|
portal.remove();
|
||||||
|
});
|
||||||
|
|
||||||
it("keeps inferred file paths non-interactive when the availability probe fails", async () => {
|
it("keeps inferred file paths non-interactive when the availability probe fails", async () => {
|
||||||
await preloadMarkdownText();
|
await preloadMarkdownText();
|
||||||
const client = makeClient();
|
const client = makeClient();
|
||||||
|
|||||||
Reference in New Issue
Block a user