Skip to content

Commit cc301c8

Browse files
committed
feat: add accordion HTML and CSS to homescreen sidebar
1 parent a8f78f8 commit cc301c8

1 file changed

Lines changed: 312 additions & 1 deletion

File tree

src/webview/homescreenView.ts

Lines changed: 312 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,266 @@ export class HomescreenViewProvider implements vscode.WebviewViewProvider {
369369
to { opacity: 1; transform: translateY(0); }
370370
}
371371
.hs-header { animation: hs-in 0.18s ease both; }
372+
373+
/* ── AI Tools accordion ── */
374+
#hs-btn-ai-tools { user-select: none; }
375+
#hs-btn-ai-tools.expanded {
376+
background: var(--vscode-list-hoverBackground);
377+
border-radius: 7px 7px 0 0;
378+
}
379+
380+
.hs-ai-panel {
381+
overflow: hidden;
382+
max-height: 0;
383+
transition: max-height 0.28s cubic-bezier(0.4, 0, 0.2, 1);
384+
border-radius: 0 0 7px 7px;
385+
background: rgba(255,255,255,0.02);
386+
border-top: 1px solid transparent;
387+
}
388+
.hs-ai-panel.open {
389+
max-height: 520px;
390+
border-top-color: var(--vscode-panel-border, rgba(128,128,128,0.14));
391+
}
392+
.hs-ai-panel-inner {
393+
padding: 10px 10px 12px;
394+
display: flex;
395+
flex-direction: column;
396+
gap: 10px;
397+
}
398+
399+
/* Loading skeletons */
400+
.hs-ai-loading { display: flex; flex-direction: column; gap: 6px; }
401+
.hs-skeleton {
402+
height: 22px;
403+
border-radius: 4px;
404+
background: linear-gradient(
405+
90deg,
406+
rgba(255,255,255,0.04) 0%,
407+
rgba(255,255,255,0.09) 50%,
408+
rgba(255,255,255,0.04) 100%
409+
);
410+
background-size: 200% 100%;
411+
animation: shimmer 1.4s ease infinite;
412+
}
413+
.hs-skeleton--short { width: 55%; }
414+
.hs-skeleton--label { height: 10px; width: 38%; margin-bottom: 4px; }
415+
@keyframes shimmer {
416+
0% { background-position: 200% 0; }
417+
100% { background-position: -200% 0; }
418+
}
419+
420+
/* Section headers */
421+
.hs-ai-section-head {
422+
display: flex;
423+
align-items: center;
424+
gap: 7px;
425+
font-size: 9.5px;
426+
font-weight: 700;
427+
letter-spacing: 0.9px;
428+
text-transform: uppercase;
429+
color: var(--vscode-descriptionForeground);
430+
opacity: 0.8;
431+
margin-bottom: 5px;
432+
}
433+
.hs-ai-section-head::after {
434+
content: '';
435+
flex: 1;
436+
height: 1px;
437+
background: var(--vscode-panel-border, rgba(128,128,128,0.14));
438+
}
439+
440+
/* IDE segmented control */
441+
.hs-ai-ide {
442+
position: relative;
443+
display: flex;
444+
background: rgba(255,255,255,0.04);
445+
border: 1px solid var(--vscode-panel-border, rgba(128,128,128,0.14));
446+
border-radius: 5px;
447+
padding: 2px;
448+
margin-bottom: 7px;
449+
}
450+
.hs-ai-ide-pill {
451+
position: absolute;
452+
top: 2px;
453+
height: calc(100% - 4px);
454+
background: rgba(52,72,197,0.35);
455+
border: 1px solid rgba(52,72,197,0.5);
456+
border-radius: 3px;
457+
transition:
458+
left 0.15s cubic-bezier(0.4,0,0.2,1),
459+
width 0.15s cubic-bezier(0.4,0,0.2,1);
460+
pointer-events: none;
461+
}
462+
.hs-ai-ide-btn {
463+
flex: 1;
464+
padding: 3px 4px;
465+
font-size: 9px;
466+
font-weight: 600;
467+
letter-spacing: 0.2px;
468+
text-align: center;
469+
text-transform: uppercase;
470+
background: none;
471+
border: none;
472+
border-radius: 3px;
473+
color: var(--vscode-descriptionForeground);
474+
cursor: pointer;
475+
font-family: var(--vscode-font-family);
476+
position: relative;
477+
z-index: 1;
478+
transition: color 0.15s;
479+
white-space: nowrap;
480+
}
481+
.hs-ai-ide-btn.active { color: var(--vscode-foreground); }
482+
.hs-ai-ide-btn:hover:not(.active) { color: var(--vscode-foreground); opacity: 0.7; }
483+
484+
/* Checklist items */
485+
.hs-ai-item {
486+
display: flex;
487+
align-items: center;
488+
gap: 7px;
489+
padding: 3px 4px 3px 2px;
490+
border-radius: 4px;
491+
transition: background 0.1s;
492+
cursor: pointer;
493+
animation: hs-row-in 0.18s ease both;
494+
}
495+
.hs-ai-item:hover { background: var(--vscode-list-hoverBackground); }
496+
.hs-ai-item:nth-child(1) { animation-delay: .05s; }
497+
.hs-ai-item:nth-child(2) { animation-delay: .09s; }
498+
.hs-ai-item:nth-child(3) { animation-delay: .13s; }
499+
.hs-ai-item:nth-child(4) { animation-delay: .17s; }
500+
.hs-ai-item:nth-child(5) { animation-delay: .21s; }
501+
@keyframes hs-row-in {
502+
from { opacity: 0; transform: translateX(-4px); }
503+
to { opacity: 1; transform: translateX(0); }
504+
}
505+
506+
/* Custom checkbox */
507+
.hs-ai-cb {
508+
appearance: none;
509+
-webkit-appearance: none;
510+
width: 12px;
511+
height: 12px;
512+
flex-shrink: 0;
513+
border: 1.5px solid var(--vscode-checkbox-border);
514+
border-radius: 2px;
515+
background: var(--vscode-checkbox-background);
516+
cursor: pointer;
517+
position: relative;
518+
transition: border-color 0.1s, background 0.1s;
519+
}
520+
.hs-ai-cb:checked {
521+
background: var(--vscode-button-background);
522+
border-color: var(--vscode-button-background);
523+
}
524+
.hs-ai-cb:checked::after {
525+
content: '';
526+
position: absolute;
527+
left: 2px; top: -1px;
528+
width: 5px; height: 8px;
529+
border: 1.5px solid var(--vscode-button-foreground);
530+
border-top: none;
531+
border-left: none;
532+
transform: rotate(45deg);
533+
}
534+
.hs-ai-cb:focus-visible {
535+
outline: 1px solid var(--vscode-focusBorder);
536+
outline-offset: 1px;
537+
}
538+
539+
.hs-ai-item-name {
540+
flex: 1;
541+
font-size: 11px;
542+
color: var(--vscode-foreground);
543+
overflow: hidden;
544+
text-overflow: ellipsis;
545+
white-space: nowrap;
546+
cursor: pointer;
547+
}
548+
549+
/* Status indicator */
550+
.hs-ai-item-status {
551+
flex-shrink: 0;
552+
display: flex;
553+
align-items: center;
554+
gap: 4px;
555+
font-size: 9.5px;
556+
color: var(--vscode-descriptionForeground);
557+
white-space: nowrap;
558+
}
559+
.hs-ai-item-status::before {
560+
content: '';
561+
display: inline-block;
562+
width: 5px;
563+
height: 5px;
564+
border-radius: 1px;
565+
flex-shrink: 0;
566+
}
567+
.hs-ai-item-status--ok::before { background: #4ade80; }
568+
.hs-ai-item-status--none::before { background: rgba(255,255,255,0.15); }
569+
570+
/* Progress tick */
571+
.hs-ai-item-tick {
572+
flex-shrink: 0;
573+
width: 13px;
574+
height: 13px;
575+
display: flex;
576+
align-items: center;
577+
justify-content: center;
578+
font-size: 9px;
579+
animation: tick-in 0.2s cubic-bezier(0.34,1.56,0.64,1) both;
580+
}
581+
@keyframes tick-in {
582+
from { opacity: 0; transform: scale(0); }
583+
to { opacity: 1; transform: scale(1); }
584+
}
585+
.hs-ai-item-tick--ok { color: #4ade80; }
586+
.hs-ai-item-tick--err { color: var(--vscode-errorForeground); }
587+
588+
/* Apply button */
589+
.hs-ai-apply {
590+
width: 100%;
591+
padding: 6px 0;
592+
font-size: 11px;
593+
font-weight: 600;
594+
letter-spacing: 0.3px;
595+
color: var(--vscode-button-foreground);
596+
background: var(--vscode-button-background);
597+
border: none;
598+
border-radius: 5px;
599+
cursor: pointer;
600+
font-family: var(--vscode-font-family);
601+
transition: opacity 0.12s;
602+
position: relative;
603+
overflow: hidden;
604+
margin-top: 2px;
605+
}
606+
.hs-ai-apply::after {
607+
content: '';
608+
position: absolute;
609+
inset: 0;
610+
background: rgba(255,255,255,0);
611+
transition: background 0.12s;
612+
}
613+
.hs-ai-apply:hover::after { background: rgba(255,255,255,0.08); }
614+
.hs-ai-apply:disabled { opacity: 0.35; cursor: default; }
615+
.hs-ai-apply:disabled::after { background: none; }
616+
.hs-ai-apply:focus-visible {
617+
outline: 1px solid var(--vscode-focusBorder);
618+
outline-offset: 2px;
619+
}
620+
621+
/* Error banner */
622+
.hs-ai-error {
623+
font-size: 10.5px;
624+
color: var(--vscode-errorForeground);
625+
padding: 5px 7px;
626+
border-radius: 4px;
627+
background: rgba(241,76,76,0.08);
628+
border: 1px solid rgba(241,76,76,0.2);
629+
}
630+
631+
.hidden { display: none !important; }
372632
</style>
373633
374634
<div class="hs-root">
@@ -421,15 +681,66 @@ export class HomescreenViewProvider implements vscode.WebviewViewProvider {
421681
422682
<div class="hs-section-divider" role="separator"></div>
423683
424-
<button id="hs-btn-ai-tools" class="hs-action">
684+
<button id="hs-btn-ai-tools" class="hs-action" aria-expanded="false" aria-controls="hs-ai-panel">
425685
<span class="hs-action-icon hs-action-icon--violet" aria-hidden="true">
426686
<svg width="15" height="15" viewBox="0 0 16 16" fill="currentColor"><path d="M7.657 6.247c.11-.33.576-.33.686 0l.645 1.937a2.89 2.89 0 0 0 1.829 1.828l1.936.645c.33.11.33.576 0 .686l-1.937.645a2.89 2.89 0 0 0-1.828 1.829l-.645 1.936a.361.361 0 0 1-.686 0l-.645-1.937a2.89 2.89 0 0 0-1.828-1.828l-1.937-.645a.361.361 0 0 1 0-.686l1.937-.645a2.89 2.89 0 0 0 1.828-1.828l.645-1.937zM3.794 1.148a.217.217 0 0 1 .412 0l.387 1.162c.173.518.579.924 1.097 1.097l1.162.387a.217.217 0 0 1 0 .412l-1.162.387A1.734 1.734 0 0 0 4.593 5.69l-.387 1.162a.217.217 0 0 1-.412 0L3.407 5.69A1.734 1.734 0 0 0 2.31 4.593l-1.162-.387a.217.217 0 0 1 0-.412l1.162-.387A1.734 1.734 0 0 0 3.407 2.31l.387-1.162zM10.863.099a.145.145 0 0 1 .274 0l.258.774c.115.346.386.617.732.732l.774.258a.145.145 0 0 1 0 .274l-.774.258a1.156 1.156 0 0 0-.732.732l-.258.774a.145.145 0 0 1-.274 0l-.258-.774a1.156 1.156 0 0 0-.732-.732L9.1 2.137a.145.145 0 0 1 0-.274l.774-.258c.346-.115.617-.386.732-.732L10.863.1z"/></svg>
427687
</span>
428688
<span class="hs-action-text">
429689
<span class="hs-action-title">Configure AI Tools</span>
430690
<span class="hs-action-desc">MCP servers &amp; agent skills</span>
431691
</span>
692+
<svg class="hs-chevron" id="hs-ai-chevron" width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true"><path d="M4.5 3L7.5 6L4.5 9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
432693
</button>
694+
695+
<!-- AI Tools accordion panel -->
696+
<div class="hs-ai-panel" id="hs-ai-panel" role="region" aria-label="Configure AI Tools">
697+
698+
<!-- Loading state -->
699+
<div class="hs-ai-panel-inner" id="hs-ai-state-loading">
700+
<div class="hs-ai-loading">
701+
<div class="hs-skeleton hs-skeleton--label"></div>
702+
<div class="hs-skeleton"></div>
703+
<div class="hs-skeleton"></div>
704+
<div class="hs-skeleton hs-skeleton--short"></div>
705+
<div style="height:6px"></div>
706+
<div class="hs-skeleton hs-skeleton--label"></div>
707+
<div class="hs-skeleton"></div>
708+
<div class="hs-skeleton"></div>
709+
</div>
710+
</div>
711+
712+
<!-- Ready / applying state -->
713+
<div class="hs-ai-panel-inner hidden" id="hs-ai-state-ready">
714+
<div>
715+
<div class="hs-ai-section-head">Skills</div>
716+
<div class="hs-ai-ide" id="hs-ai-ide" role="group" aria-label="Target IDE">
717+
<div class="hs-ai-ide-pill" id="hs-ai-ide-pill"></div>
718+
<button class="hs-ai-ide-btn active" data-ide="Claude Code">Claude Code</button>
719+
<button class="hs-ai-ide-btn" data-ide="Cursor">Cursor</button>
720+
<button class="hs-ai-ide-btn" data-ide="VS Code (Copilot)">VS Code</button>
721+
</div>
722+
<div id="hs-ai-skills-list"></div>
723+
</div>
724+
<div>
725+
<div class="hs-ai-section-head">MCP Servers</div>
726+
<div id="hs-ai-mcp-list"></div>
727+
</div>
728+
<button class="hs-ai-apply" id="hs-ai-apply" disabled>Apply</button>
729+
</div>
730+
731+
<!-- Done state -->
732+
<div class="hs-ai-panel-inner hidden" id="hs-ai-state-done">
733+
<div id="hs-ai-done-skills-list"></div>
734+
<div id="hs-ai-done-mcp-list"></div>
735+
<button class="hs-ai-apply" id="hs-ai-apply-again">Apply again</button>
736+
</div>
737+
738+
<!-- Error state -->
739+
<div class="hs-ai-panel-inner hidden" id="hs-ai-state-error">
740+
<div class="hs-ai-error" id="hs-ai-error-msg"></div>
741+
</div>
742+
743+
</div><!-- /hs-ai-panel -->
433744
</div>
434745
435746
<div class="hs-footer">

0 commit comments

Comments
 (0)