feat: Add popover to ChatPanel

This commit adds a popover to ChatPanel that contains a dropdown menu for commands and contexts. The dropdown menu can be opened by clicking on the ChatPanel's textarea. The dropdown menu contains a list of commands and contexts that can be clicked to insert them into the textarea. The popover also contains a tooltip that provides instructions on how to select code or file and right-click to access the context menu.
This commit is contained in:
Rankin Zheng 2023-05-18 10:31:22 +08:00
parent 8e84acab08
commit 1aaf8a6ec9

View File

@ -1,6 +1,6 @@
import * as React from 'react';
import { useState, useEffect, useRef } from 'react';
import { Accordion, AccordionControlProps, Avatar, Box, Center, Code, Container, CopyButton, Divider, Flex, Grid, Stack, Textarea, TypographyStylesProvider, px, rem, useMantineTheme } from '@mantine/core';
import { Accordion, AccordionControlProps, Avatar, Box, Center, Code, Container, CopyButton, Divider, Flex, Grid, Popover, Stack, Textarea, TypographyStylesProvider, px, rem, useMantineTheme } from '@mantine/core';
import { Input, Tooltip } from '@mantine/core';
import { List } from '@mantine/core';
import { ScrollArea } from '@mantine/core';
@ -235,62 +235,96 @@ const chatPanel = () => {
const commandMenusNode = commandMenus.map(({ pattern, description, name }, index) => {
return (
<Menu.Item
<Flex
mih={40}
gap="md"
justify="flex-start"
align="flex-start"
direction="row"
wrap="wrap"
sx={{
'&:hover, &[data-hovered]': {
color: 'var(--vscode-menu-selectionForeground)',
border: 'var(--vscode-menu-selectionBorder)',
backgroundColor: 'var(--vscode-menu-selectionBackground)'
padding: '5px 0',
'&:hover': {
cursor: 'pointer',
color: 'var(--vscode-commandCenter-activeForeground)',
backgroundColor: 'var(--vscode-commandCenter-activeBackground)'
}
}}
onClick={() => { setInput(`/${pattern} `); }}
icon={<IconTerminal2 size={16} color='var(--vscode-menu-foreground)' />}
onClick={() => {
setInput(`/${pattern} `);
setMenuOpend(false);
}}
>
<Text sx={{
fontSize: 'sm',
fontWeight: 'bolder',
color: 'var(--vscode-menu-foreground)'
}}>
/{pattern}
</Text>
<Text sx={{
fontSize: 'sm',
color: theme.colors.gray[6],
}}>
{description}
</Text>
</Menu.Item>);
<IconTerminal2
size={16}
color='var(--vscode-menu-foreground)'
style={{
marginTop: 8,
marginLeft: 8,
}} />
<Stack spacing={0}>
<Text sx={{
fontSize: 'sm',
fontWeight: 'bolder',
color: 'var(--vscode-menu-foreground)'
}}>
/{pattern}
</Text>
<Text sx={{
fontSize: 'sm',
color: theme.colors.gray[6],
}}>
{description}
</Text>
</Stack>
</Flex>);
});
const contextMenusNode = contextMenus.map(({ pattern, description, name }, index) => {
return (
<Menu.Item
<Flex
mih={40}
gap="md"
justify="flex-start"
align="flex-start"
direction="row"
wrap="wrap"
sx={{
'&:hover, &[data-hovered]': {
color: 'var(--vscode-menu-selectionForeground)',
border: 'var(--vscode-menu-selectionBorder)',
backgroundColor: 'var(--vscode-menu-selectionBackground)'
padding: '5px 0',
'&:hover': {
cursor: 'pointer',
color: 'var(--vscode-commandCenter-activeForeground)',
backgroundColor: 'var(--vscode-commandCenter-activeBackground)'
}
}}
onClick={() => {
handleContextClick(name);
setMenuOpend(false);
}}
icon={<IconMessagePlus size={16} color='var(--vscode-menu-foreground)' />}
>
<Text sx={{
fontSize: 'sm',
fontWeight: 'bolder',
color: 'var(--vscode-menu-foreground)'
}}>
{name}
</Text>
<Text sx={{
fontSize: 'sm',
color: theme.colors.gray[6],
}}>
{description}
</Text>
</Menu.Item>);
<IconMessagePlus
size={16}
color='var(--vscode-menu-foreground)'
style={{
marginTop: 8,
marginLeft: 8,
}} />
<Stack spacing={0}>
<Text sx={{
fontSize: 'sm',
fontWeight: 'bolder',
color: 'var(--vscode-menu-foreground)'
}}>
{name}
</Text>
<Text sx={{
fontSize: 'sm',
color: theme.colors.gray[6],
}}>
{description}
</Text>
</Stack>
</Flex>);
});
const messageList = messages.map(({ message: messageText, type: messageType, contexts }, index) => {
@ -330,7 +364,7 @@ const chatPanel = () => {
}}
styles={{
item: {
border: 'var(--vscode-menu-border)',
borderColor: 'var(--vscode-menu-border)',
backgroundColor: 'var(--vscode-menu-background)',
},
control: {
@ -556,7 +590,7 @@ const chatPanel = () => {
}}
styles={{
item: {
border: 'var(--vscode-menu-border)',
borderColor: 'var(--vscode-menu-border)',
backgroundColor: 'var(--vscode-menu-background)',
},
control: {
@ -626,7 +660,7 @@ const chatPanel = () => {
}
</Accordion>
}
<Menu
<Popover
id='commandMenu'
position='top-start'
closeOnClickOutside={true}
@ -641,7 +675,7 @@ const chatPanel = () => {
onOpen={() => menuType !== '' ? setMenuOpend(true) : setMenuOpend(false)}
returnFocus={true}
>
<Menu.Target>
<Popover.Target>
<Textarea
id='chat-textarea'
disabled={generating}
@ -661,7 +695,7 @@ const chatPanel = () => {
rightSection: { alignItems: 'flex-start', paddingTop: '9px' },
input: {
backgroundColor: 'var(--vscode-input-background)',
border: 'var(--vscode-input-border)',
borderColor: 'var(--vscode-input-border)',
color: 'var(--vscode-input-foreground)',
'&[data-disabled]': {
color: 'var(--vscode-disabledForeground)'
@ -678,7 +712,7 @@ const chatPanel = () => {
backgroundColor: 'var(--vscode-toolbar-activeBackground)'
},
'&[data-disabled]': {
border: 'var(--vscode-input-border)',
borderColor: 'var(--vscode-input-border)',
backgroundColor: 'var(--vscode-toolbar-activeBackground)'
}
}}
@ -696,7 +730,7 @@ const chatPanel = () => {
backgroundColor: 'var(--vscode-toolbar-activeBackground)'
},
'&[data-disabled]': {
border: 'var(--vscode-input-border)',
borderColor: 'var(--vscode-input-border)',
backgroundColor: 'var(--vscode-toolbar-activeBackground)'
}
}}
@ -705,13 +739,14 @@ const chatPanel = () => {
</ActionIcon>
}
/>
</Menu.Target>
</Popover.Target>
{
menuType === 'contexts'
? (<Menu.Dropdown
? (<Popover.Dropdown
sx={{
padding: 0,
color: 'var(--vscode-menu-foreground)',
border: 'var(--vscode-menu-border)',
borderColor: 'var(--vscode-menu-border)',
backgroundColor: 'var(--vscode-menu-background)'
}}>
<Text
@ -723,22 +758,23 @@ const chatPanel = () => {
Tips: Select code or file & right click
</Text>
<Divider />
<Menu.Label>DevChat Contexts</Menu.Label>
<Text sx={{ padding: '5px 5px 5px 10px' }}>DevChat Contexts</Text>
{contextMenusNode}
</Menu.Dropdown>)
</Popover.Dropdown>)
: menuType === 'commands'
? <Menu.Dropdown
? <Popover.Dropdown
sx={{
padding: 0,
color: 'var(--vscode-menu-foreground)',
border: 'var(--vscode-menu-border)',
borderColor: 'var(--vscode-menu-border)',
backgroundColor: 'var(--vscode-menu-background)'
}}>
<Menu.Label>DevChat Commands</Menu.Label>
<Text sx={{ padding: '5px 5px 5px 10px' }}>DevChat Commands</Text>
{commandMenusNode}
</Menu.Dropdown>
</Popover.Dropdown>
: <></>
}
</Menu>
</Popover>
</Stack>
</Container >
);