fix(sidebar): float setup script prompt (#11439)
This commit is contained in:
parent
64aa726301
commit
0fe7759c64
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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()),
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
</>
|
||||
)}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue