Restructure chat interface to display history side-by-side with live chat
- Change chat layout from vertical stacking to horizontal side-by-side layout - History panel (300px width) displays on left with conversation list - Main chat area takes remaining space on right with messages and input - Improves UX by making chat history visible alongside active conversation - Fix JSX structure and nesting for proper component rendering 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -536,17 +536,24 @@ export default function FloatingChat() {
|
|||||||
|
|
||||||
{!isMinimized && (
|
{!isMinimized && (
|
||||||
<>
|
<>
|
||||||
{/* Chat History Panel */}
|
{/* Main Content Area - Side by Side Layout */}
|
||||||
|
<Box sx={{
|
||||||
|
display: 'flex',
|
||||||
|
flexGrow: 1,
|
||||||
|
overflow: 'hidden'
|
||||||
|
}}>
|
||||||
|
{/* Chat History Panel - Left Side */}
|
||||||
{showHistory && (
|
{showHistory && (
|
||||||
<Box sx={{
|
<Box sx={{
|
||||||
p: 2,
|
width: '300px',
|
||||||
borderBottom: 1,
|
borderRight: 1,
|
||||||
borderColor: 'divider',
|
borderColor: 'divider',
|
||||||
bgcolor: 'grey.50',
|
bgcolor: 'grey.50',
|
||||||
maxHeight: '300px',
|
display: 'flex',
|
||||||
overflowY: 'auto'
|
flexDirection: 'column',
|
||||||
}}>
|
}}>
|
||||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
|
<Box sx={{ p: 2, borderBottom: 1, borderColor: 'divider' }}>
|
||||||
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
<Typography variant="h6">
|
<Typography variant="h6">
|
||||||
Chat History
|
Chat History
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -568,6 +575,9 @@ export default function FloatingChat() {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box sx={{ flexGrow: 1, overflowY: 'auto', p: 2 }}>
|
||||||
|
|
||||||
{!isAuthenticated ? (
|
{!isAuthenticated ? (
|
||||||
<Box sx={{ textAlign: 'center', py: 3 }}>
|
<Box sx={{ textAlign: 'center', py: 3 }}>
|
||||||
@@ -639,77 +649,16 @@ export default function FloatingChat() {
|
|||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Conversation Menu */}
|
{/* Main Chat Area - Right Side */}
|
||||||
<Menu
|
<Box sx={{
|
||||||
anchorEl={menuAnchorEl}
|
flexGrow: 1,
|
||||||
open={Boolean(menuAnchorEl)}
|
display: 'flex',
|
||||||
onClose={handleMenuClose}
|
flexDirection: 'column',
|
||||||
transformOrigin={{ horizontal: 'right', vertical: 'top' }}
|
overflow: 'hidden'
|
||||||
anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}
|
}}>
|
||||||
>
|
|
||||||
<MenuItem onClick={handleRenameClick}>
|
|
||||||
<Edit fontSize="small" sx={{ mr: 1 }} />
|
|
||||||
Rename
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem onClick={handleDeleteClick} sx={{ color: 'error.main' }}>
|
|
||||||
<Delete fontSize="small" sx={{ mr: 1 }} />
|
|
||||||
Delete
|
|
||||||
</MenuItem>
|
|
||||||
</Menu>
|
|
||||||
|
|
||||||
{/* Rename Dialog */}
|
|
||||||
<Dialog open={showRenameDialog} onClose={() => setShowRenameDialog(false)} maxWidth="sm" fullWidth>
|
|
||||||
<DialogTitle>Rename Conversation</DialogTitle>
|
|
||||||
<DialogContent>
|
|
||||||
<TextField
|
|
||||||
autoFocus
|
|
||||||
margin="dense"
|
|
||||||
label="Conversation Title"
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
value={newTitle}
|
|
||||||
onChange={(e) => setNewTitle(e.target.value)}
|
|
||||||
onKeyPress={(e) => {
|
|
||||||
if (e.key === 'Enter') {
|
|
||||||
handleRenameSubmit()
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</DialogContent>
|
|
||||||
<DialogActions>
|
|
||||||
<Button onClick={() => setShowRenameDialog(false)}>Cancel</Button>
|
|
||||||
<Button
|
|
||||||
onClick={handleRenameSubmit}
|
|
||||||
variant="contained"
|
|
||||||
disabled={!newTitle.trim()}
|
|
||||||
>
|
|
||||||
Rename
|
|
||||||
</Button>
|
|
||||||
</DialogActions>
|
|
||||||
</Dialog>
|
|
||||||
|
|
||||||
{/* Delete Confirmation Dialog */}
|
|
||||||
<Dialog open={showDeleteDialog} onClose={() => setShowDeleteDialog(false)}>
|
|
||||||
<DialogTitle>Delete Conversation</DialogTitle>
|
|
||||||
<DialogContent>
|
|
||||||
<Typography>
|
|
||||||
Are you sure you want to delete this conversation? This action cannot be undone.
|
|
||||||
</Typography>
|
|
||||||
</DialogContent>
|
|
||||||
<DialogActions>
|
|
||||||
<Button onClick={() => setShowDeleteDialog(false)}>Cancel</Button>
|
|
||||||
<Button
|
|
||||||
onClick={handleDeleteConfirm}
|
|
||||||
variant="contained"
|
|
||||||
color="error"
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</Button>
|
|
||||||
</DialogActions>
|
|
||||||
</Dialog>
|
|
||||||
|
|
||||||
{/* Suggested Questions */}
|
{/* Suggested Questions */}
|
||||||
<Box sx={{ p: 2, borderBottom: 1, borderColor: 'divider' }}>
|
<Box sx={{ p: 2, borderBottom: 1, borderColor: 'divider' }}>
|
||||||
<Typography variant="body2" color="text.secondary" sx={{ mb: 1 }}>
|
<Typography variant="body2" color="text.secondary" sx={{ mb: 1 }}>
|
||||||
@@ -933,6 +882,77 @@ export default function FloatingChat() {
|
|||||||
{t('enterToSend')}
|
{t('enterToSend')}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Conversation Menu */}
|
||||||
|
<Menu
|
||||||
|
anchorEl={menuAnchorEl}
|
||||||
|
open={Boolean(menuAnchorEl)}
|
||||||
|
onClose={handleMenuClose}
|
||||||
|
transformOrigin={{ horizontal: 'right', vertical: 'top' }}
|
||||||
|
anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}
|
||||||
|
>
|
||||||
|
<MenuItem onClick={handleRenameClick}>
|
||||||
|
<Edit fontSize="small" sx={{ mr: 1 }} />
|
||||||
|
Rename
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem onClick={handleDeleteClick} sx={{ color: 'error.main' }}>
|
||||||
|
<Delete fontSize="small" sx={{ mr: 1 }} />
|
||||||
|
Delete
|
||||||
|
</MenuItem>
|
||||||
|
</Menu>
|
||||||
|
|
||||||
|
{/* Rename Dialog */}
|
||||||
|
<Dialog open={showRenameDialog} onClose={() => setShowRenameDialog(false)} maxWidth="sm" fullWidth>
|
||||||
|
<DialogTitle>Rename Conversation</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<TextField
|
||||||
|
autoFocus
|
||||||
|
margin="dense"
|
||||||
|
label="Conversation Title"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={newTitle}
|
||||||
|
onChange={(e) => setNewTitle(e.target.value)}
|
||||||
|
onKeyPress={(e) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
handleRenameSubmit()
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={() => setShowRenameDialog(false)}>Cancel</Button>
|
||||||
|
<Button
|
||||||
|
onClick={handleRenameSubmit}
|
||||||
|
variant="contained"
|
||||||
|
disabled={!newTitle.trim()}
|
||||||
|
>
|
||||||
|
Rename
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
{/* Delete Confirmation Dialog */}
|
||||||
|
<Dialog open={showDeleteDialog} onClose={() => setShowDeleteDialog(false)}>
|
||||||
|
<DialogTitle>Delete Conversation</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<Typography>
|
||||||
|
Are you sure you want to delete this conversation? This action cannot be undone.
|
||||||
|
</Typography>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={() => setShowDeleteDialog(false)}>Cancel</Button>
|
||||||
|
<Button
|
||||||
|
onClick={handleDeleteConfirm}
|
||||||
|
variant="contained"
|
||||||
|
color="error"
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|||||||
Reference in New Issue
Block a user