Skip to content

Commit 1767353

Browse files
committed
Refactor the ChatInput dropdown menu into a reusable DropdownMenu component
1 parent ab43a92 commit 1767353

8 files changed

Lines changed: 131 additions & 95 deletions

File tree

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
.menu {
2+
position: absolute;
3+
top: calc(100% + 4px);
4+
right: 0;
5+
background-color: var(--vscode-menu-background);
6+
border: 1px solid var(--vscode-menu-border);
7+
border-radius: var(--border-radius-8px);
8+
box-shadow: 0 2px 8px var(--vscode-widget-shadow);
9+
z-index: 1;
10+
padding: var(--padding-4px);
11+
width: max-content;
12+
text-align: left;
13+
}
14+
15+
.item {
16+
display: flex;
17+
justify-content: space-between;
18+
gap: var(--padding-12px);
19+
align-items: center;
20+
padding: var(--padding-4px) var(--padding-8px);
21+
cursor: pointer;
22+
color: var(--vscode-menu-foreground);
23+
white-space: nowrap;
24+
border-radius: var(--border-radius-4px);
25+
26+
&:hover {
27+
background-color: var(--vscode-menu-selectionBackground);
28+
& > span {
29+
color: var(--vscode-menu-selectionForeground);
30+
}
31+
}
32+
}
33+
34+
.shortcut {
35+
color: var(--vscode-descriptionForeground);
36+
font-size: var(--font-size-12px);
37+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { DropdownMenu } from './DropdownMenu'
2+
3+
export default {
4+
component: DropdownMenu,
5+
decorators: [
6+
(Story: any) => (
7+
<div style={{ position: 'relative', width: '200px', height: '150px' }}>
8+
<Story />
9+
</div>
10+
)
11+
]
12+
}
13+
14+
const sample_items: DropdownMenu.Item[] = [
15+
{
16+
label: 'Select...',
17+
shortcut: 'cmd+return',
18+
on_click: () => alert('Select clicked')
19+
},
20+
{
21+
label: 'Copy prompt',
22+
shortcut: 'cmd+option+c',
23+
on_click: () => alert('Copy clicked')
24+
},
25+
{
26+
label: 'Another Action',
27+
on_click: () => alert('Another action clicked')
28+
}
29+
]
30+
31+
export const Default = {
32+
args: {
33+
items: sample_items
34+
}
35+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import styles from './DropdownMenu.module.scss'
2+
import cn from 'classnames'
3+
4+
export namespace DropdownMenu {
5+
export type Item = {
6+
label: string
7+
shortcut?: string
8+
on_click: () => void
9+
}
10+
11+
export type Props = {
12+
items: Item[]
13+
className?: string
14+
}
15+
}
16+
17+
export const DropdownMenu: React.FC<DropdownMenu.Props> = ({
18+
items,
19+
className
20+
}) => {
21+
return (
22+
<div className={cn(styles.menu, className)}>
23+
{items.map((item, index) => (
24+
<div key={index} className={styles.item} onClick={item.on_click}>
25+
<span>{item.label}</span>
26+
{item.shortcut && (
27+
<span className={styles.shortcut}>{item.shortcut}</span>
28+
)}
29+
</div>
30+
))}
31+
</div>
32+
)
33+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './DropdownMenu'

‎packages/ui/src/components/editor/panel/ChatInput/ChatInput.module.scss‎

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -266,41 +266,6 @@
266266
width: 20px;
267267
}
268268
}
269-
270-
&__dropdown {
271-
position: absolute;
272-
top: calc(100% + 4px);
273-
right: 0;
274-
background-color: var(--vscode-menu-background);
275-
border: 1px solid var(--vscode-menu-border);
276-
border-radius: var(--border-radius-5px);
277-
box-shadow: 0 2px 8px var(--vscode-widget-shadow);
278-
z-index: 10;
279-
padding: var(--padding-4px) 0;
280-
width: max-content;
281-
text-align: left;
282-
283-
&__item {
284-
display: flex;
285-
justify-content: space-between;
286-
gap: var(--padding-12px);
287-
align-items: center;
288-
padding: var(--padding-4px) var(--padding-8px);
289-
cursor: pointer;
290-
color: var(--vscode-menu-foreground);
291-
white-space: nowrap;
292-
293-
&:hover {
294-
background-color: var(--vscode-menu-selectionBackground);
295-
color: var(--vscode-menu-selectionForeground) !important;
296-
}
297-
298-
&__shortcut {
299-
color: var(--vscode-descriptionForeground);
300-
font-size: var(--font-size-12px);
301-
}
302-
}
303-
}
304269
}
305270
}
306271
}

‎packages/ui/src/components/editor/panel/ChatInput/ChatInput.tsx‎

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
import { useRef, useEffect, useMemo, useState } from 'react'
1+
import { useRef, useEffect, useMemo } from 'react'
22
import styles from './ChatInput.module.scss'
33
import TextareaAutosize from 'react-textarea-autosize'
44
import cn from 'classnames'
55
import { Icon } from '../../common/Icon'
66
import { get_highlighted_text } from './utils/get-highlighted-text'
77
import { use_handlers } from './hooks/use-handlers'
88
import { use_dropdown } from './hooks/use-dropdown'
9+
import { DropdownMenu } from '../../common/DropdownMenu'
910

1011
export type EditFormat = 'whole' | 'truncated' | 'diff'
1112

@@ -109,8 +110,7 @@ export const ChatInput: React.FC<ChatInputProps> = (props) => {
109110
}, [
110111
props.is_in_code_completions_mode,
111112
props.chat_history,
112-
is_history_enabled,
113-
props.is_web_mode
113+
is_history_enabled
114114
])
115115

116116
const custom_handle_key_down = (
@@ -306,42 +306,20 @@ export const ChatInput: React.FC<ChatInputProps> = (props) => {
306306
/>
307307
</button>
308308
{is_dropdown_open && (
309-
<div className={styles['footer__right__submit__dropdown']}>
310-
<div
311-
className={
312-
styles['footer__right__submit__dropdown__item']
313-
}
314-
onClick={handle_select_click}
315-
>
316-
Select...
317-
<span
318-
className={
319-
styles[
320-
'footer__right__submit__dropdown__item__shortcut'
321-
]
322-
}
323-
>
324-
{mod_key}+{is_mac ? 'return' : 'enter'}
325-
</span>
326-
</div>
327-
<div
328-
className={
329-
styles['footer__right__submit__dropdown__item']
309+
<DropdownMenu
310+
items={[
311+
{
312+
label: 'Select...',
313+
shortcut: `${mod_key}+${is_mac ? 'return' : 'enter'}`,
314+
on_click: handle_select_click
315+
},
316+
{
317+
label: 'Copy prompt',
318+
shortcut: `${mod_key}+${is_mac ? 'option' : 'alt'}+c`,
319+
on_click: handle_copy_click
330320
}
331-
onClick={handle_copy_click}
332-
>
333-
Copy prompt
334-
<span
335-
className={
336-
styles[
337-
'footer__right__submit__dropdown__item__shortcut'
338-
]
339-
}
340-
>
341-
{mod_key}+{is_mac ? 'option' : 'alt'}+c
342-
</span>
343-
</div>
344-
</div>
321+
]}
322+
/>
345323
)}
346324
</>
347325
)}

‎packages/ui/src/components/editor/panel/ChatInput/hooks/use-dropdown.ts‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,12 @@ export const use_dropdown = ({
3737
}
3838
}, [])
3939

40-
const handle_copy_click = (e: React.MouseEvent) => {
41-
e.stopPropagation()
40+
const handle_copy_click = () => {
4241
on_copy()
4342
close_dropdown()
4443
}
4544

46-
const handle_select_click = (e: React.MouseEvent) => {
47-
e.stopPropagation()
45+
const handle_select_click = () => {
4846
on_submit_with_control()
4947
close_dropdown()
5048
}

‎packages/ui/src/components/editor/panel/Dropdown/Dropdown.module.scss‎

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -50,37 +50,26 @@
5050
position: absolute;
5151
right: 0;
5252
margin-top: var(--padding-2px);
53-
z-index: 3;
54-
background-color: var(--vscode-dropdown-background);
55-
border: 1px solid var(--vscode-focusBorder);
56-
border-radius: var(--border-radius-4px);
53+
z-index: 1;
54+
background-color: var(--vscode-menu-background);
55+
border: 1px solid var(--vscode-menu-border);
56+
border-radius: var(--border-radius-8px);
57+
box-shadow: 0 2px 8px var(--vscode-widget-shadow);
5758
min-width: 100%;
5859
max-height: 200px;
5960
overflow-y: auto;
61+
padding: var(--padding-4px);
6062

6163
&__item {
62-
--margin: 1px;
6364
display: flex;
6465
align-items: center;
6566
height: 24px;
6667
padding: 0 var(--padding-8px);
6768
color: var(--vscode-menu-foreground);
6869
font-size: var(--font-size-13px);
6970
cursor: pointer;
70-
margin: var(--margin);
7171
white-space: nowrap;
72-
73-
&:first-child {
74-
border-top-left-radius: calc(var(--border-radius-4px) - var(--margin));
75-
border-top-right-radius: calc(var(--border-radius-4px) - var(--margin));
76-
}
77-
78-
&:last-child {
79-
border-bottom-left-radius: calc(var(--border-radius-4px) - var(--margin));
80-
border-bottom-right-radius: calc(
81-
var(--border-radius-4px) - var(--margin)
82-
);
83-
}
72+
border-radius: var(--border-radius-4px);
8473

8574
&:hover {
8675
background-color: var(--vscode-menu-selectionBackground);

0 commit comments

Comments
 (0)