Multi-pane Titles

This commit is contained in:
Enrico Ros
2025-02-28 04:18:03 -08:00
parent 2b55921830
commit 5bf9270d5d
3 changed files with 73 additions and 0 deletions
+11
View File
@@ -40,6 +40,7 @@ import { useLLM } from '~/common/stores/llms/llms.hooks';
import { useModelDomain } from '~/common/stores/llms/hooks/useModelDomain';
import { useOverlayComponents } from '~/common/layout/overlays/useOverlayComponents';
import { useRouterQuery } from '~/common/app.routes';
import { useUIComplexityIsMinimal } from '~/common/state/store-ui';
import { useUXLabsStore } from '~/common/state/store-ux-labs';
import { ChatPane } from './components/layout-pane/ChatPane';
@@ -50,6 +51,7 @@ import { ChatBeamWrapper } from './components/ChatBeamWrapper';
import { ChatDrawerMemo } from './components/layout-drawer/ChatDrawer';
import { ChatMessageList } from './components/ChatMessageList';
import { Composer } from './components/composer/Composer';
import { PaneTitleOverlay } from './components/layout-pane/PaneTitleOverlay';
import { usePanesManager } from './components/panes/store-panes-manager';
import type { ChatExecuteMode } from './execute-mode/execute-mode.types';
@@ -126,6 +128,8 @@ export function AppChat() {
const isMobile = useIsMobile();
const isTallScreen = useIsTallScreen();
const isZenMode = useUIComplexityIsMinimal();
const intent = useRouterQuery<Partial<AppChatIntent>>();
const showAltTitleBar = useUXLabsStore(state => DEV_MODE_SETTINGS && state.labsChatBarAlt === 'title');
@@ -659,6 +663,13 @@ export function AppChat() {
}}
>
{isMultiPane && !isZenMode && (
<PaneTitleOverlay
conversationId={_paneConversationId}
isFocused={_paneIsFocused}
/>
)}
<ScrollToBottom
bootToBottom
stickToBottomInitial
@@ -0,0 +1,50 @@
import * as React from 'react';
import { Sheet } from '@mui/joy';
import type { DConversationId } from '~/common/stores/chat/chat.conversation';
import { useConversationTitle } from '~/common/stores/chat/hooks/useConversationTitle';
const _style = {
position: 'absolute',
top: 0,
left: '50%',
transform: 'translateX(-50%)',
zIndex: 10,
p: '1px 1rem 4px',
fontSize: 'sm',
fontWeight: 'md',
borderBottomLeftRadius: '8px',
borderBottomRightRadius: '8px',
// boxShadow: 'xs',
// border: '1px solid',
// borderColor: 'background.popup',
borderTop: 'none',
maxWidth: '78%',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
} as const;
export function PaneTitleOverlay(props: { conversationId: DConversationId | null, isFocused: boolean }) {
// external state
const title = useConversationTitle(props.conversationId);
if (!title || title?.length < 3)
return null;
// don't render if not focused
// if (!props.isFocused)
// return null;
return (
<Sheet
color={props.isFocused ? 'primary' : 'neutral'}
variant={props.isFocused ? 'solid' : 'outlined'}
sx={_style}
>
{title}
</Sheet>
);
}
@@ -0,0 +1,12 @@
import { useShallow } from 'zustand/react/shallow';
import { conversationTitle, DConversationId } from '../chat.conversation';
import { useChatStore } from '../store-chats';
export function useConversationTitle(conversationId: DConversationId | null) {
return useChatStore(useShallow(({ conversations }) => {
const conversation = conversationId ? conversations.find(_c => _c.id === conversationId) : null;
return conversation ? conversationTitle(conversation) : null;
}));
}