Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions webview-ui/src/components/settings/PromptsSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const PromptsSettings = ({
setCustomCondensingPrompt,
includeTaskHistoryInEnhance: contextIncludeTaskHistoryInEnhance,
setIncludeTaskHistoryInEnhance: contextSetIncludeTaskHistoryInEnhance,
mode,
} = useExtensionState()

// Use props if provided, otherwise fall back to context
Expand All @@ -52,6 +53,9 @@ const PromptsSettings = ({
const [testPrompt, setTestPrompt] = useState("")
const [isEnhancing, setIsEnhancing] = useState(false)
const [activeSupportOption, setActiveSupportOption] = useState<SupportPromptType>("ENHANCE")
const [isDialogOpen, setIsDialogOpen] = useState(false)
const [selectedPromptContent, setSelectedPromptContent] = useState("")
const [selectedPromptTitle, setSelectedPromptTitle] = useState("")

useEffect(() => {
const handler = (event: MessageEvent) => {
Expand All @@ -61,6 +65,12 @@ const PromptsSettings = ({
setTestPrompt(message.text)
}
setIsEnhancing(false)
} else if (message.type === "systemPrompt") {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing error handling here. What happens if message.text or message.mode is undefined? Consider adding defensive checks to prevent runtime errors.

if (message.text) {
setSelectedPromptContent(message.text)
setSelectedPromptTitle(`System Prompt (${message.mode} mode)`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using the translation function (t) to set the system prompt title instead of a hard-coded template literal. For example, use t('prompts:systemPrompt.title', { modeName: message.mode }) to ensure consistency with translations.

Suggested change
setSelectedPromptTitle(`System Prompt (${message.mode} mode)`)
setSelectedPromptTitle(t('prompts:systemPrompt.title', { modeName: message.mode }))

This comment was generated because it violated a code review rule: irule_C0ez7Rji6ANcGkkX.

setIsDialogOpen(true)
}
}
}

Expand Down Expand Up @@ -122,6 +132,43 @@ const PromptsSettings = ({
</SectionHeader>

<Section>
{/* System Prompt Preview Section */}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This entire system prompt preview section (lines 135-167) duplicates functionality that already exists in ModesView.tsx. Could we extract this into a shared component like <SystemPromptPreview /> to follow DRY principles?

<div className="mb-4">
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This component is adding significant new functionality without any test coverage. Consider adding tests for:

  • The message event handlers (lines 60-79)
  • The dialog state management
  • The button click handlers
  • The integration with vscode.postMessage

<div className="flex gap-2">
<Button
variant="default"
onClick={() => {
vscode.postMessage({
type: "getSystemPrompt",
mode: mode,
})
}}
data-testid="preview-prompt-button">
{t("prompts:systemPrompt.preview")}
</Button>
<StandardTooltip content={t("prompts:systemPrompt.copy")}>
<Button
variant="ghost"
size="icon"
onClick={() => {
vscode.postMessage({
type: "copySystemPrompt",
mode: mode,
})
}}
data-testid="copy-prompt-button">
<span className="codicon codicon-copy"></span>
</Button>
</StandardTooltip>
</div>
<div className="text-sm text-vscode-descriptionForeground mt-1">
{t("prompts:systemPrompt.previewDescription")}
</div>
</div>

<div className="border-t border-vscode-input-border my-4"></div>

{/* Support Prompts Section */}
<div>
<Select
value={activeSupportOption}
Expand Down Expand Up @@ -281,6 +328,34 @@ const PromptsSettings = ({
)}
</div>
</Section>

{/* System Prompt Preview Dialog */}
{isDialogOpen && (
<div className="fixed inset-0 flex justify-end bg-black/50 z-[1000]">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For improved accessibility, consider adding appropriate ARIA attributes (e.g., role='dialog', aria-modal='true') to the system prompt preview modal container.

Suggested change
<div className="fixed inset-0 flex justify-end bg-black/50 z-[1000]">
<div className="fixed inset-0 flex justify-end bg-black/50 z-[1000]" role="dialog" aria-modal="true">

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dialog styling mixes inline Tailwind classes with what appears to be VSCode-specific CSS variables. For consistency and maintainability, consider consolidating to one approach. Also, the fixed positioning with 'inset-0' might cause issues on smaller screens.

<div className="w-[calc(100vw-100px)] h-full bg-vscode-editor-background shadow-md flex flex-col relative">
<div className="flex-1 p-5 overflow-y-auto min-h-0">
<Button
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accessibility issue: This close button only has an icon without an aria-label. Screen reader users won't know what this button does. Consider adding aria-label="Close dialog".

variant="ghost"
size="icon"
onClick={() => setIsDialogOpen(false)}
className="absolute top-5 right-5">
<span className="codicon codicon-close"></span>
</Button>
<h2 className="mb-4">
{selectedPromptTitle || t("prompts:systemPrompt.title", { modeName: mode })}
</h2>
<pre className="p-2 whitespace-pre-wrap break-words font-mono text-vscode-editor-font-size text-vscode-editor-foreground bg-vscode-editor-background border border-vscode-editor-lineHighlightBorder rounded overflow-y-auto">
{selectedPromptContent}
</pre>
</div>
<div className="flex justify-end p-3 px-5 border-t border-vscode-editor-lineHighlightBorder bg-vscode-editor-background">
<Button variant="secondary" onClick={() => setIsDialogOpen(false)}>
{t("prompts:createModeDialog.close")}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This translation key 'prompts:createModeDialog.close' seems to be borrowed from a different context (createModeDialog). Consider adding a dedicated translation key for this dialog, like 'prompts:systemPromptDialog.close' for better maintainability.

</Button>
</div>
</div>
</div>
)}
</div>
)
}
Expand Down
3 changes: 2 additions & 1 deletion webview-ui/src/i18n/locales/en/prompts.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@
"systemPrompt": {
"preview": "Preview System Prompt",
"copy": "Copy system prompt to clipboard",
"title": "System Prompt ({{modeName}} mode)"
"title": "System Prompt ({{modeName}} mode)",
"previewDescription": "View the complete system prompt that will be sent to the AI model for the current mode"
},
"supportPrompts": {
"title": "Support Prompts",
Expand Down
Loading