Skip to content

Commit 80eb909

Browse files
committed
Add AI input prompt to Roopik welcome page
Introduces a modern AI input section on the Roopik welcome page, allowing users to submit prompts directly to the AI agent. Updates include new UI/UX for the input, auto-opening the agent sidebar, and improved focus/unfocus controls for canvas cards. Also refines tool descriptions and adds a custom tab icon for the canvas panel.
1 parent 7512a67 commit 80eb909

7 files changed

Lines changed: 294 additions & 13 deletions

File tree

extensions/roopik-roo/src/core/prompts/tools/native-tools/roopik.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ export const project_start: OpenAI.Chat.ChatCompletionTool = {
314314
properties: {
315315
projectPath: {
316316
type: "string",
317-
description: "Path to the project directory (absolute or relative to workspace)",
317+
description: "Path to the project directory (Use absolute path to workspace)",
318318
},
319319
port: {
320320
type: "number",
@@ -439,7 +439,7 @@ export const component_add: OpenAI.Chat.ChatCompletionTool = {
439439
},
440440
name: {
441441
type: "string",
442-
description: "Display name for the component. Inferred from folder if not specified.",
442+
description: "Display name for the component. Always try to pass logical short name (one word or max 2-3 words) for the component.",
443443
},
444444
entryFile: {
445445
type: "string",

extensions/roopik-roo/src/core/prompts/tools/roopik/roopik-tools.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ export function getProjectStartDescription(args: ToolArgs): string {
230230
return `## project_start
231231
Description: [Roopik IDE - Projects Only] Start a FULL APPLICATION's dev server and preview in the integrated Browser (NOT used for Canvas components). Use for complete runnable vite based projects with routing/navigation (e.g., todo app with multiple pages). The browser shows the running app at localhost. For ISOLATED UI components/screens, use component_add instead.
232232
Parameters:
233-
- projectPath: (required) Path to the project directory (absolute or relative to ${args.cwd})
233+
- projectPath: (required) Path to the project directory (Use absolute path to workspace)
234234
- port: (optional) Port to run the dev server on. Default is auto-detected or 5173.
235235
Usage:
236236
<project_start>
@@ -297,7 +297,7 @@ Description: [Roopik IDE - Canvas Only] Add an ISOLATED UI component to the Canv
297297
Parameters:
298298
- folderPath: (required) The absolute system path to the component folder. Do not use relative paths.(contains the component files)
299299
- canvasId: (optional) Canvas to add the component to. Uses active canvas if not specified.
300-
- name: (optional) Display name for the component. Inferred from folder if not specified.
300+
- name: (optional) Display name for the component. Always try to pass logical short name (one word or max 2-3 words) for the component.
301301
- entryFile: (optional) Entry file name (e.g., index.tsx). Auto-detected in IDE if not specified.
302302
- framework: (optional) Force framework: react, vue, svelte, vanilla. Auto-detected in IDE if not specified.
303303
Usage:
@@ -439,7 +439,7 @@ These tools integrate with Roopik IDE's browser preview, canvas, and component f
439439
440440
**Component Canvas Workflow:**
441441
1. \`canvas_create\` or \`canvas_get_active\` - Get/create canvas (first try to get active canvas, if not found create a new one, use your judgment to determine better canvas short generic name)
442-
2. \`component_add\` - Add component folder to canvas (Once you write a component code, you have to pass the absolute path of the component file to the canvas add tool which shows the live preview of the component in the canvas UI)
442+
2. \`component_add\` - Add component folder to canvas (Once you write a component code, you have to pass the absolute path of the component file to the canvas add tool which shows the live preview of the component in the canvas UI).
443443
3. \`component_list\` - See all components on canvas (this will show the list of all components added to the canvas to you if you need to see the list of components added to the canvas or get info about a specific component use \`component_get_info\`)
444444
4. \`component_rebuild\` - Force rebuild after changes (use this tool if you make changes to the component code and want to rebuild the component)
445445
5. \`component_remove\` - Remove component (set deleteSourceCode=true to delete files automatically - never use terminal commands to delete files)

extensions/roopik/src/canvasPanel.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ export class CanvasPanel implements vscode.Disposable {
189189
}
190190
);
191191

192+
// Set custom icon for the tab using VS Code Codicon
193+
// Options: palette, paintbrush, layout, window, pencil, beaker
194+
panel.iconPath = new vscode.ThemeIcon('pencil');
195+
192196
return new CanvasPanel(panel, extensionUri, canvasId, canvasName, workspaceRoot, manager);
193197
}
194198

@@ -492,7 +496,7 @@ export class CanvasPanel implements vscode.Disposable {
492496
});
493497
break;
494498

495-
case 'debugLog':
499+
case 'debugLog': {
496500
// Handle debug logs from webview for tracing
497501
const debugPayload = message.payload as { level?: string; message: string };
498502
const logLevel = debugPayload?.level || 'info';
@@ -505,8 +509,7 @@ export class CanvasPanel implements vscode.Disposable {
505509
this.logger.info(`[WebviewTrace] ${logMsg}`);
506510
}
507511
break;
508-
509-
default:
512+
}
510513
this.logger.warn(`Unknown webview message type: ${message.type}`);
511514
}
512515
} catch (error) {

extensions/roopik/webview/src/canvasView/components/SandboxCard/SandboxCard.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,22 @@ export function SandboxCard({
898898
</div>
899899
</div>
900900

901+
{/* Focus button - only show when NOT focused and on hover */}
902+
{!isFocused && isHovered && (
903+
<button
904+
className="focus-button"
905+
onClick={(e) => {
906+
e.stopPropagation();
907+
onDoubleClick();
908+
}}
909+
title="Enter focus mode"
910+
>
911+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
912+
<path d="M8 3h8M3 8v8M21 8v8M8 21h8M3 8l3 3M21 8l-3 3M3 16l3-3M21 16l-3-3" />
913+
</svg>
914+
</button>
915+
)}
916+
901917
{/* Unfocus button - only show when focused */}
902918
{isFocused && (
903919
<button

extensions/roopik/webview/src/canvasView/styles/sandboxCard.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@
304304
/* ============================================================
305305
Unfocus Button (only visible when focused)
306306
============================================================ */
307+
.sandbox-card .focus-button,
307308
.sandbox-card .unfocus-button {
308309
position: absolute;
309310
bottom: 20px;
@@ -324,13 +325,21 @@
324325
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
325326
}
326327

328+
.sandbox-card .focus-button:hover {
329+
background: rgba(40, 40, 45, 0.95);
330+
color: rgba(102, 204, 204, 0.9);
331+
transform: scale(1.1);
332+
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
333+
}
334+
327335
.sandbox-card .unfocus-button:hover {
328336
background: rgba(40, 40, 45, 0.95);
329337
color: rgba(255, 165, 0, 0.9);
330338
transform: scale(1.1);
331339
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
332340
}
333341

342+
.sandbox-card .focus-button svg,
334343
.sandbox-card .unfocus-button svg {
335344
flex-shrink: 0;
336345
}

src/vs/workbench/contrib/roopik/browser/media/welcomeEditor.css

Lines changed: 172 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,174 @@
187187
border-color: var(--vscode-button-hoverBackground);
188188
}
189189

190+
.hero-button.primary:hover {
191+
background-color: var(--vscode-button-hoverBackground);
192+
border-color: var(--vscode-button-hoverBackground);
193+
}
194+
195+
/* ============================================================================
196+
AI Input Section - Clean Modern Design
197+
============================================================================ */
198+
199+
.ai-input-section {
200+
display: flex;
201+
justify-content: center;
202+
width: 100%;
203+
margin: 20px 0 36px 0;
204+
padding: 0 32px;
205+
box-sizing: border-box;
206+
}
207+
208+
/* Wrapper creates the gradient border effect - always glowing */
209+
.ai-input-wrapper {
210+
position: relative;
211+
width: 100%;
212+
max-width: 600px;
213+
border-radius: 999px;
214+
padding: 2px;
215+
background: linear-gradient(135deg,
216+
#667eea 0%,
217+
#764ba2 25%,
218+
#f093fb 50%,
219+
#4facfe 75%,
220+
#667eea 100%);
221+
background-size: 300% 300%;
222+
animation: gradient-shift 4s ease infinite;
223+
box-shadow: 0 0 20px rgba(102, 126, 234, 0.3),
224+
0 0 40px rgba(118, 75, 162, 0.15);
225+
transition: all 0.3s ease;
226+
}
227+
228+
.ai-input-wrapper:focus-within {
229+
box-shadow: 0 0 25px rgba(102, 126, 234, 0.5),
230+
0 0 50px rgba(118, 75, 162, 0.25);
231+
}
232+
233+
@keyframes gradient-shift {
234+
235+
0%,
236+
100% {
237+
background-position: 0% 50%;
238+
}
239+
240+
50% {
241+
background-position: 100% 50%;
242+
}
243+
}
244+
245+
/* Main input container - pill shape */
246+
.ai-input-box {
247+
display: flex;
248+
align-items: center;
249+
gap: 12px;
250+
width: 100%;
251+
padding: 14px 20px;
252+
border-radius: 999px;
253+
background: var(--vscode-input-background);
254+
box-sizing: border-box;
255+
}
256+
257+
/* Input field - fills all available space */
258+
.ai-input-field {
259+
flex: 1;
260+
background: transparent;
261+
border: none;
262+
outline: none !important;
263+
box-shadow: none !important;
264+
color: var(--vscode-input-foreground);
265+
font-size: 15px;
266+
font-weight: 400;
267+
padding: 0;
268+
line-height: 1.5;
269+
min-width: 0;
270+
}
271+
272+
.ai-input-field::placeholder {
273+
color: var(--vscode-input-placeholderForeground);
274+
opacity: 0.7;
275+
}
276+
277+
.ai-input-field:focus {
278+
outline: none !important;
279+
box-shadow: none !important;
280+
border: none !important;
281+
}
282+
283+
/* Submit button - circular */
284+
.ai-submit-button {
285+
display: flex;
286+
align-items: center;
287+
justify-content: center;
288+
width: 36px;
289+
height: 36px;
290+
border-radius: 50%;
291+
background: var(--vscode-button-background);
292+
color: var(--vscode-button-foreground);
293+
border: none;
294+
cursor: pointer;
295+
transition: all 0.2s ease;
296+
flex-shrink: 0;
297+
}
298+
299+
.ai-submit-button:hover {
300+
background: var(--vscode-button-hoverBackground);
301+
transform: scale(1.05);
302+
}
303+
304+
.ai-submit-button:active {
305+
transform: scale(0.95);
306+
}
307+
308+
.ai-submit-button .codicon {
309+
font-size: 16px;
310+
}
311+
312+
/* Responsive */
313+
@media (max-width: 768px) {
314+
.ai-input-section {
315+
padding: 0 16px;
316+
}
317+
318+
.ai-input-wrapper {
319+
max-width: 100%;
320+
}
321+
322+
.ai-input-box {
323+
padding: 12px 16px;
324+
}
325+
326+
.ai-input-field {
327+
font-size: 14px;
328+
}
329+
}
330+
331+
.hero-showcase {
332+
position: relative;
333+
padding: 28px;
334+
border-radius: 10px;
335+
background: radial-gradient(circle at top, rgba(110, 142, 251, 0.35), transparent 70%), var(--vscode-editor-background);
336+
border: 1px dashed var(--vscode-widget-border);
337+
display: flex;
338+
flex-direction: column;
339+
gap: 12px;
340+
min-height: 220px;
341+
min-width: 240px;
342+
overflow: hidden;
343+
box-sizing: border-box;
344+
}
345+
346+
.hero-showcase::after {
347+
content: '';
348+
position: absolute;
349+
inset: 0;
350+
background-image: linear-gradient(120deg, rgba(255, 255, 255, 0.03) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.03) 50%, rgba(255, 255, 255, 0.03) 75%, transparent 75%, transparent);
351+
background-size: 28px 28px;
352+
pointer-events: none;
353+
}
354+
355+
.showcase-label {}
356+
357+
190358
.hero-showcase {
191359
position: relative;
192360
padding: 28px;
@@ -667,8 +835,8 @@ Inline Settings View (replaces modal)
667835
}
668836

669837
/* ============================================
670-
Settings Sections
671-
============================================ */
838+
Settings Sections
839+
============================================ */
672840

673841
.settings-section {
674842
margin-bottom: 28px;
@@ -766,8 +934,8 @@ Toggle Switch
766934
}
767935

768936
/* ============================================
769-
Text Input
770-
============================================ */
937+
Text Input
938+
============================================ */
771939

772940
.settings-text-input {
773941
width: 200px;

0 commit comments

Comments
 (0)