mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-16 13:03:31 +08:00
feat(desktop): add BrowserAddressBar component
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
25ea37bb3d
commit
bdfedcd2e7
37
desktop/src/components/browser/BrowserAddressBar.test.tsx
Normal file
37
desktop/src/components/browser/BrowserAddressBar.test.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import '@testing-library/jest-dom'
|
||||
import { BrowserAddressBar } from './BrowserAddressBar'
|
||||
|
||||
const baseProps = {
|
||||
url: 'http://localhost:5173/', canGoBack: false, canGoForward: false,
|
||||
onNavigate: vi.fn(), onBack: vi.fn(), onForward: vi.fn(), onReload: vi.fn(),
|
||||
}
|
||||
|
||||
describe('BrowserAddressBar', () => {
|
||||
it('shows the current url in the input', () => {
|
||||
render(<BrowserAddressBar {...baseProps} />)
|
||||
expect(screen.getByRole('textbox')).toHaveValue('http://localhost:5173/')
|
||||
})
|
||||
|
||||
it('submits the edited url via onNavigate', () => {
|
||||
const onNavigate = vi.fn()
|
||||
render(<BrowserAddressBar {...baseProps} onNavigate={onNavigate} />)
|
||||
const input = screen.getByRole('textbox')
|
||||
fireEvent.change(input, { target: { value: 'http://localhost:3000/x' } })
|
||||
fireEvent.submit(input.closest('form')!)
|
||||
expect(onNavigate).toHaveBeenCalledWith('http://localhost:3000/x')
|
||||
})
|
||||
|
||||
it('disables back when cannot go back', () => {
|
||||
render(<BrowserAddressBar {...baseProps} canGoBack={false} />)
|
||||
expect(screen.getByLabelText('后退')).toBeDisabled()
|
||||
})
|
||||
|
||||
it('enables back and fires onBack when canGoBack', () => {
|
||||
const onBack = vi.fn()
|
||||
render(<BrowserAddressBar {...baseProps} canGoBack onBack={onBack} />)
|
||||
fireEvent.click(screen.getByLabelText('后退'))
|
||||
expect(onBack).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
33
desktop/src/components/browser/BrowserAddressBar.tsx
Normal file
33
desktop/src/components/browser/BrowserAddressBar.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { ArrowLeft, ArrowRight, RotateCw } from 'lucide-react'
|
||||
|
||||
type Props = {
|
||||
url: string
|
||||
canGoBack: boolean
|
||||
canGoForward: boolean
|
||||
onNavigate: (url: string) => void
|
||||
onBack: () => void
|
||||
onForward: () => void
|
||||
onReload: () => void
|
||||
}
|
||||
|
||||
export function BrowserAddressBar({ url, canGoBack, canGoForward, onNavigate, onBack, onForward, onReload }: Props) {
|
||||
const [draft, setDraft] = useState(url)
|
||||
useEffect(() => { setDraft(url) }, [url])
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-1 px-2 py-1.5 border-b border-[var(--color-border)]">
|
||||
<button aria-label="后退" disabled={!canGoBack} onClick={onBack} className="p-1 disabled:opacity-40"><ArrowLeft size={16} /></button>
|
||||
<button aria-label="前进" disabled={!canGoForward} onClick={onForward} className="p-1 disabled:opacity-40"><ArrowRight size={16} /></button>
|
||||
<button aria-label="刷新" onClick={onReload} className="p-1"><RotateCw size={16} /></button>
|
||||
<form className="flex-1" onSubmit={(e) => { e.preventDefault(); onNavigate(draft.trim()) }}>
|
||||
<input
|
||||
className="w-full rounded-md bg-[var(--color-surface)] px-2 py-1 text-xs text-[var(--color-text-primary)]"
|
||||
value={draft}
|
||||
onChange={(e) => setDraft(e.target.value)}
|
||||
spellCheck={false}
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user