Fold the conversation header's icons into one menu

The header's sessions, new session, computers, models and settings icons
become rows in a single dropdown off an ellipsis on the right, so the
header keeps one control whatever width it has. A row that opens a modal
closes the menu first, so the modal never sits behind an open menu, and
each row shows what it acts on (the computer's name, the text model).
This commit is contained in:
2026-10-21 16:06:21 +01:00
parent 361b8add9b
commit 40cf101b38
7 changed files with 461 additions and 134 deletions
+17 -1
View File
@@ -1,4 +1,9 @@
import { useState, type ComponentProps, type ReactNode } from "react";
import {
useEffect,
useState,
type ComponentProps,
type ReactNode,
} from "react";
import Input from "@moduletrace/twui/form/Input";
import Modal from "@moduletrace/twui/elements/Modal";
import Button from "@moduletrace/twui/layout/Button";
@@ -25,6 +30,10 @@ type Props = {
*/
target?: ReactNode;
target_wrapper_props?: ComponentProps<typeof Modal>["targetWrapperProps"];
/**
* Runs as it opens, e.g. closing the menu it was opened from.
*/
on_open?: () => void;
};
/**
@@ -39,6 +48,7 @@ export default function BotSessionsModal({
has_other_unread,
target,
target_wrapper_props,
on_open,
}: Props) {
const [open, setOpen] = useState(false);
const sessions = useBotSessions({
@@ -48,6 +58,12 @@ export default function BotSessionsModal({
});
const name = bot.name || "the bot";
useEffect(() => {
if (open) {
on_open?.();
}
}, [open]);
return (
<Modal
target={