mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-18 13:23:33 +08:00
fix: float browser preview zoom controls (#952)
Move the preview zoom control out of the address toolbar and into a bottom-right floating control area inside the browser preview stage. Keep the native WebContentsView bounds clear of the control strip so the DOM control remains interactive on high-DPI Windows displays. Tested: cd desktop && bun run test -- src/components/browser/BrowserSurface.test.tsx Tested: cd desktop && bun run lint Tested: cd desktop && bun run build Not-tested: Windows high-DPI real-device smoke. Confidence: medium Scope-risk: narrow
This commit is contained in:
parent
e4e7026cde
commit
f269887fe7
@ -182,16 +182,19 @@ describe('BrowserSurface', () => {
|
||||
expect(bridge.message).toHaveBeenLastCalledWith({ v: 1, type: 'exit-picker' })
|
||||
})
|
||||
|
||||
it('renders toolbar preview zoom controls that update the native preview zoom', async () => {
|
||||
it('renders floating preview zoom controls that update the native preview zoom', async () => {
|
||||
useBrowserPanelStore.getState().open('s1', 'http://localhost:5173/')
|
||||
useBrowserPanelStore.getState().setReady('s1')
|
||||
render(<BrowserSurface sessionId="s1" />)
|
||||
|
||||
const controls = screen.getByTestId('browser-zoom-controls')
|
||||
const actions = screen.getByTestId('browser-toolbar-actions')
|
||||
const floatingControls = screen.getByTestId('browser-preview-floating-controls')
|
||||
expect(controls).toHaveTextContent('100%')
|
||||
expect(actions).toContainElement(controls)
|
||||
expect(controls.compareDocumentPosition(screen.getByTestId('preview-host')) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy()
|
||||
expect(actions).not.toContainElement(controls)
|
||||
expect(floatingControls).toContainElement(controls)
|
||||
expect(screen.getByTestId('browser-preview-stage')).toContainElement(floatingControls)
|
||||
expect(screen.getByTestId('preview-host').compareDocumentPosition(floatingControls) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy()
|
||||
|
||||
fireEvent.click(screen.getByLabelText('缩小预览'))
|
||||
expect(useBrowserPanelStore.getState().bySession['s1']!.zoom).toBe(0.9)
|
||||
|
||||
@ -208,7 +208,7 @@ export function BrowserSurface({ sessionId }: { sessionId: string }) {
|
||||
}
|
||||
|
||||
const zoomButtonClass = [
|
||||
'inline-flex h-7 w-7 items-center justify-center rounded-full transition-colors',
|
||||
'inline-flex h-8 w-8 items-center justify-center rounded-full transition-colors',
|
||||
'text-[var(--color-text-secondary)] hover:bg-[var(--color-surface-container-low)] hover:text-[var(--color-text-primary)]',
|
||||
'disabled:cursor-default disabled:opacity-35 disabled:hover:bg-transparent disabled:hover:text-[var(--color-text-secondary)]',
|
||||
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-brand)]',
|
||||
@ -217,7 +217,9 @@ export function BrowserSurface({ sessionId }: { sessionId: string }) {
|
||||
const zoomControls = (
|
||||
<div
|
||||
data-testid="browser-zoom-controls"
|
||||
className="inline-flex h-8 shrink-0 items-center gap-1 rounded-full border border-[var(--color-border)] bg-[var(--color-surface)] px-1 shadow-sm"
|
||||
role="group"
|
||||
aria-label="预览缩放控制"
|
||||
className="inline-flex h-10 shrink-0 items-center gap-1 rounded-full border border-[var(--color-border)] bg-[var(--color-surface)] px-1.5 shadow-lg"
|
||||
>
|
||||
<button
|
||||
aria-label="缩小预览"
|
||||
@ -285,7 +287,6 @@ export function BrowserSurface({ sessionId }: { sessionId: string }) {
|
||||
>
|
||||
<MousePointer2 size={16} />
|
||||
</button>
|
||||
{zoomControls}
|
||||
</>
|
||||
)
|
||||
|
||||
@ -317,12 +318,23 @@ export function BrowserSurface({ sessionId }: { sessionId: string }) {
|
||||
rightActions={previewActions}
|
||||
/>
|
||||
<div className="flex min-h-0 flex-1 flex-col bg-[var(--color-surface)]">
|
||||
<div ref={hostRef} className="relative min-h-0 flex-1 overflow-hidden" data-testid="preview-host">
|
||||
{session.loading && (
|
||||
<div className="pointer-events-none absolute inset-0 flex items-center justify-center bg-[var(--color-surface)] text-[var(--color-text-tertiary)]">
|
||||
<Loader2 size={18} className="animate-spin" aria-label="加载中" />
|
||||
<div className="relative min-h-0 flex-1 overflow-hidden" data-testid="browser-preview-stage">
|
||||
{/* WebContentsView renders above DOM, so keep the floating controls outside its bounds. */}
|
||||
<div ref={hostRef} className="absolute inset-x-0 top-0 bottom-12 overflow-hidden" data-testid="preview-host">
|
||||
{session.loading && (
|
||||
<div className="pointer-events-none absolute inset-0 flex items-center justify-center bg-[var(--color-surface)] text-[var(--color-text-tertiary)]">
|
||||
<Loader2 size={18} className="animate-spin" aria-label="加载中" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
data-testid="browser-preview-floating-controls"
|
||||
className="pointer-events-none absolute inset-x-0 bottom-0 z-10 flex h-12 items-end justify-end px-3 pb-2"
|
||||
>
|
||||
<div className="pointer-events-auto">
|
||||
{zoomControls}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user