fix(sidebar): float setup script prompt (#11439)

This commit is contained in:
Brennan Benson 2026-07-29 18:43:04 -07:00 committed by GitHub
parent 64aa726301
commit 0fe7759c64
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 68 additions and 19 deletions

View File

@ -1218,16 +1218,6 @@ html.native-shell .app-layout {
background: color-mix(in srgb, var(--accent) 70%, transparent);
}
/* Why: sidebar-accent sits too close to sidebar for this persistent prompt;
a foreground mix creates the requested light/dark separation without a new token. */
.setup-script-prompt-card {
background: color-mix(in srgb, var(--sidebar-foreground) 5%, var(--sidebar));
}
.dark .setup-script-prompt-card {
background: color-mix(in srgb, var(--sidebar-foreground) 12%, var(--sidebar));
}
/* Why: one-shot sidebar education cards need stronger separation than
worktree-sidebar-accent, which sits almost on top of the sidebar fill. */
.worktree-sidebar-notice-card {

View File

@ -0,0 +1,43 @@
// @vitest-environment happy-dom
import { render } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'
import { TooltipProvider } from '@/components/ui/tooltip'
import { SetupScriptPromptCardShell } from './SetupScriptPromptCardShell'
describe('SetupScriptPromptCardShell', () => {
it('floats above its anchor without reserving a sidebar background panel', () => {
const view = render(
<TooltipProvider>
<SetupScriptPromptCardShell
repoBadgeColor="blue"
repoDisplayName="orca"
isInspectionError={false}
sharedSetupIgnored={false}
isPackageManagerSuggestion={false}
hasCandidate={false}
candidateSource={null}
candidateProvenance={null}
detectedSetupDraft=""
isImporting={false}
renderedStateOk
onDismiss={vi.fn()}
onRetryInspection={vi.fn()}
onConfigure={vi.fn()}
onImport={vi.fn()}
onSetupDraftChange={vi.fn()}
/>
</TooltipProvider>
)
const layer = view.container.querySelector('[data-setup-script-prompt-layer]')
const surface = layer?.firstElementChild
expect(layer?.classList.contains('absolute')).toBe(true)
expect(layer?.classList.contains('inset-x-0')).toBe(true)
expect(layer?.classList.contains('bottom-full')).toBe(true)
expect(layer?.classList.contains('pointer-events-none')).toBe(true)
expect(surface?.classList.contains('pointer-events-auto')).toBe(true)
expect(surface?.classList.contains('bg-popover')).toBe(true)
expect(surface?.classList.contains('text-popover-foreground')).toBe(true)
})
})

View File

@ -48,8 +48,11 @@ export function SetupScriptPromptCardShell({
onSetupDraftChange
}: SetupScriptPromptCardShellProps): React.JSX.Element {
return (
<div className="shrink-0 px-3 pb-2">
<div className="setup-script-prompt-card rounded-lg border border-worktree-sidebar-border p-3 text-worktree-sidebar-accent-foreground shadow-xs">
<div
data-setup-script-prompt-layer=""
className="pointer-events-none absolute inset-x-0 bottom-full z-40 px-3 pb-2"
>
<div className="pointer-events-auto rounded-lg border border-border bg-popover p-3 text-popover-foreground shadow-[0_10px_24px_rgba(0,0,0,0.18)]">
<div className="flex items-center justify-between gap-2">
<p className="text-sm font-semibold leading-snug">
{translate(

View File

@ -134,6 +134,17 @@ beforeEach(() => {
afterEach(cleanup)
describe('Sidebar', () => {
it('anchors the setup script popup to the bottom toolbar', () => {
setSidebarState(getDefaultSettings(tmpdir()))
const view = render(sidebarElement())
const prompt = view.getByTestId('setup-script-prompt-card')
const toolbar = view.getByTestId('sidebar-toolbar')
expect(prompt.parentElement).toBe(toolbar.parentElement)
expect(prompt.parentElement?.classList.contains('relative')).toBe(true)
expect(prompt.parentElement?.classList.contains('shrink-0')).toBe(true)
})
it('applies left sidebar appearance variables to the workspace sidebar surface', () => {
setSidebarState({
...getDefaultSettings(tmpdir()),

View File

@ -188,14 +188,16 @@ function Sidebar({
onWorkspaceBoardDragPreviewCancel={cancelWorkspaceBoardDragPreview}
/>
<SetupScriptPromptCard />
<div className="relative shrink-0">
<SetupScriptPromptCard />
{/* Fixed bottom toolbar */}
<SidebarToolbar
workspaceBoardOpen={workspaceBoardOpen}
workspaceBoardDragPreviewOpen={workspaceBoardDragPreviewOpen}
onWorkspaceBoardToggle={toggleWorkspaceBoard}
/>
{/* Fixed bottom toolbar */}
<SidebarToolbar
workspaceBoardOpen={workspaceBoardOpen}
workspaceBoardDragPreviewOpen={workspaceBoardDragPreviewOpen}
onWorkspaceBoardToggle={toggleWorkspaceBoard}
/>
</div>
</>
)}