Skip to content

Commit 2a4756a

Browse files
authored
Merge pull request #1329 from RooVetGit/chat_custom_dropdown
Custom dropdowns for mode/api profile
2 parents 3168b1e + 9c3e477 commit 2a4756a

File tree

5 files changed

+473
-125
lines changed

5 files changed

+473
-125
lines changed

webview-ui/src/components/chat/ChatTextArea.tsx

Lines changed: 69 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import Thumbnails from "../common/Thumbnails"
1515
import { vscode } from "../../utils/vscode"
1616
import { WebviewMessage } from "../../../../src/shared/WebviewMessage"
1717
import { Mode, getAllModes } from "../../../../src/shared/modes"
18-
import { CaretIcon } from "../common/CaretIcon"
1918
import { convertToMentionPath } from "../../utils/path-mentions"
19+
import { SelectDropdown, DropdownOptionType } from "../ui"
2020

2121
interface ChatTextAreaProps {
2222
inputValue: string
@@ -541,35 +541,6 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
541541
[updateCursorPosition],
542542
)
543543

544-
const selectStyle = {
545-
fontSize: "11px",
546-
cursor: textAreaDisabled ? "not-allowed" : "pointer",
547-
backgroundColor: "transparent",
548-
border: "none",
549-
color: "var(--vscode-foreground)",
550-
opacity: textAreaDisabled ? 0.5 : 0.8,
551-
outline: "none",
552-
paddingLeft: "20px",
553-
paddingRight: "6px",
554-
WebkitAppearance: "none" as const,
555-
MozAppearance: "none" as const,
556-
appearance: "none" as const,
557-
}
558-
559-
const optionStyle = {
560-
backgroundColor: "var(--vscode-dropdown-background)",
561-
color: "var(--vscode-dropdown-foreground)",
562-
}
563-
564-
const caretContainerStyle = {
565-
position: "absolute" as const,
566-
left: 6,
567-
top: "50%",
568-
transform: "translateY(-45%)",
569-
pointerEvents: "none" as const,
570-
opacity: textAreaDisabled ? 0.5 : 0.8,
571-
}
572-
573544
return (
574545
<div
575546
className="chat-text-area"
@@ -791,122 +762,110 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
791762
marginTop: "auto",
792763
paddingTop: "2px",
793764
}}>
765+
{/* Left side - dropdowns container */}
794766
<div
795767
style={{
796768
display: "flex",
797769
alignItems: "center",
770+
gap: "4px",
771+
overflow: "hidden",
772+
minWidth: 0,
798773
}}>
799-
<div style={{ position: "relative", display: "inline-block" }}>
800-
<select
774+
{/* Mode selector - fixed width */}
775+
<div style={{ flexShrink: 0 }}>
776+
<SelectDropdown
801777
value={mode}
802778
disabled={textAreaDisabled}
803779
title="Select mode for interaction"
804-
onChange={(e) => {
805-
const value = e.target.value
806-
if (value === "prompts-action") {
807-
window.postMessage({ type: "action", action: "promptsButtonClicked" })
808-
return
809-
}
780+
options={[
781+
// Add the shortcut text as a disabled option at the top
782+
{
783+
value: "shortcut",
784+
label: modeShortcutText,
785+
disabled: true,
786+
type: DropdownOptionType.SHORTCUT,
787+
},
788+
// Add all modes
789+
...getAllModes(customModes).map((mode) => ({
790+
value: mode.slug,
791+
label: mode.name,
792+
type: DropdownOptionType.ITEM,
793+
})),
794+
// Add separator
795+
{
796+
value: "sep-1",
797+
label: "Separator",
798+
type: DropdownOptionType.SEPARATOR,
799+
},
800+
// Add Edit option
801+
{
802+
value: "promptsButtonClicked",
803+
label: "Edit...",
804+
type: DropdownOptionType.ACTION,
805+
},
806+
]}
807+
onChange={(value) => {
810808
setMode(value as Mode)
811809
vscode.postMessage({
812810
type: "mode",
813811
text: value,
814812
})
815813
}}
816-
style={{
817-
...selectStyle,
818-
minWidth: "70px",
819-
flex: "0 0 auto",
820-
}}>
821-
<option
822-
disabled
823-
style={{ ...optionStyle, fontStyle: "italic", opacity: 0.6, padding: "2px 8px" }}>
824-
{modeShortcutText}
825-
</option>
826-
{getAllModes(customModes).map((mode) => (
827-
<option key={mode.slug} value={mode.slug} style={{ ...optionStyle }}>
828-
{mode.name}
829-
</option>
830-
))}
831-
<option
832-
disabled
833-
style={{
834-
borderTop: "1px solid var(--vscode-dropdown-border)",
835-
...optionStyle,
836-
}}>
837-
────
838-
</option>
839-
<option value="prompts-action" style={{ ...optionStyle }}>
840-
Edit...
841-
</option>
842-
</select>
843-
<div style={caretContainerStyle}>
844-
<CaretIcon />
845-
</div>
814+
shortcutText={modeShortcutText}
815+
triggerClassName="w-full"
816+
/>
846817
</div>
847818

819+
{/* API configuration selector - flexible width */}
848820
<div
849821
style={{
850-
position: "relative",
851-
display: "inline-block",
852822
flex: "1 1 auto",
853823
minWidth: 0,
854-
maxWidth: "150px",
855824
overflow: "hidden",
856825
}}>
857-
<select
826+
<SelectDropdown
858827
value={currentApiConfigName || ""}
859828
disabled={textAreaDisabled}
860829
title="Select API configuration"
861-
onChange={(e) => {
862-
const value = e.target.value
863-
if (value === "settings-action") {
864-
window.postMessage({ type: "action", action: "settingsButtonClicked" })
865-
return
866-
}
830+
options={[
831+
// Add all API configurations
832+
...(listApiConfigMeta || []).map((config) => ({
833+
value: config.name,
834+
label: config.name,
835+
type: DropdownOptionType.ITEM,
836+
})),
837+
// Add separator
838+
{
839+
value: "sep-2",
840+
label: "Separator",
841+
type: DropdownOptionType.SEPARATOR,
842+
},
843+
// Add Edit option
844+
{
845+
value: "settingsButtonClicked",
846+
label: "Edit...",
847+
type: DropdownOptionType.ACTION,
848+
},
849+
]}
850+
onChange={(value) => {
867851
vscode.postMessage({
868852
type: "loadApiConfiguration",
869853
text: value,
870854
})
871855
}}
872-
style={{
873-
...selectStyle,
874-
width: "100%",
875-
textOverflow: "ellipsis",
876-
}}>
877-
{(listApiConfigMeta || []).map((config) => (
878-
<option
879-
key={config.name}
880-
value={config.name}
881-
style={{
882-
...optionStyle,
883-
}}>
884-
{config.name}
885-
</option>
886-
))}
887-
<option
888-
disabled
889-
style={{
890-
borderTop: "1px solid var(--vscode-dropdown-border)",
891-
...optionStyle,
892-
}}>
893-
────
894-
</option>
895-
<option value="settings-action" style={{ ...optionStyle }}>
896-
Edit...
897-
</option>
898-
</select>
899-
<div style={caretContainerStyle}>
900-
<CaretIcon />
901-
</div>
856+
contentClassName="max-h-[300px] overflow-y-auto"
857+
triggerClassName="w-full text-ellipsis overflow-hidden"
858+
/>
902859
</div>
903860
</div>
904861

862+
{/* Right side - action buttons */}
905863
<div
906864
style={{
907865
display: "flex",
908866
alignItems: "center",
909-
gap: "12px",
867+
gap: "8px",
868+
flexShrink: 0,
910869
}}>
911870
<div style={{ display: "flex", alignItems: "center" }}>
912871
{isEnhancingPrompt ? (
@@ -916,7 +875,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
916875
color: "var(--vscode-input-foreground)",
917876
opacity: 0.5,
918877
fontSize: 16.5,
919-
marginRight: 10,
878+
marginRight: 6,
920879
}}
921880
/>
922881
) : (

webview-ui/src/components/common/CaretIcon.tsx

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)