feat(search): 点击放大镜切换搜索引擎

- 搜索框左侧图标改为触发器,点击展开效果五快捷栏
- 选中后左侧图标切换为对应引擎图标(本地放大镜 / Google / Bing / 百度 / 搜狗 / 360)
- 搜索框占位文案随当前模式变化,原有过滤与回车行为保留
This commit is contained in:
2026-11-04 12:50:02 +08:00
parent 8c1c658b15
commit 56f362f921
2 changed files with 66 additions and 31 deletions
+16 -21
View File
@@ -1444,42 +1444,37 @@ html.theme-transition .site-background {
align-items: center; align-items: center;
} }
.engine-toggle { .engine-trigger {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 3px; justify-content: center;
height: 24px; width: 26px;
padding: 0 var(--su-space-2); height: 26px;
border: 1px solid var(--su-border); padding: 0;
border: 0;
border-radius: var(--su-radius-xs); border-radius: var(--su-radius-xs);
background-color: var(--su-bg-subtle); background: transparent;
color: var(--su-text-sub); color: var(--su-text-muted);
font: inherit;
font-size: 11px;
line-height: 1;
cursor: pointer; cursor: pointer;
transition: transition:
color var(--su-duration-fast) var(--su-ease-in-out), color var(--su-duration-fast) var(--su-ease-in-out),
background-color var(--su-duration-fast) var(--su-ease-in-out), background-color var(--su-duration-fast) var(--su-ease-in-out);
border-color var(--su-duration-fast) var(--su-ease-in-out);
} }
.engine-toggle:hover, .engine-trigger:hover,
.engine-toggle[aria-expanded='true'] { .engine-trigger[aria-expanded='true'] {
border-color: var(--su-border-strong); background-color: var(--su-bg-subtle);
background-color: var(--su-bg-hover);
color: var(--su-text-main); color: var(--su-text-main);
} }
.engine-toggle span { .engine-trigger svg {
font-size: 9px; display: block;
opacity: 0.6;
} }
.engine-menu { .engine-menu {
position: absolute; position: absolute;
top: 50%; top: 50%;
right: calc(100% + 6px); left: calc(100% + 6px);
z-index: var(--su-z-float); z-index: var(--su-z-float);
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@@ -1496,7 +1491,7 @@ html.theme-transition .site-background {
@keyframes engine-bar-in { @keyframes engine-bar-in {
from { from {
opacity: 0; opacity: 0;
transform: translate(6px, -50%); transform: translate(-6px, -50%);
} }
to { to {
opacity: 1; opacity: 1;
+50 -10
View File
@@ -1,5 +1,6 @@
import { import {
Empty, Empty,
Icon,
Layout, Layout,
Menu, Menu,
Notice, Notice,
@@ -63,12 +64,42 @@ type Route =
| { kind: 'api' } | { kind: 'api' }
const SEARCH_ENGINES = [ const SEARCH_ENGINES = [
{ key: 'local', name: '本地', search: '' }, { key: 'local', name: '本地', search: '', path: '', color: '' },
{ key: 'google', name: 'Google', search: 'https://www.google.com/search?q=' }, {
{ key: 'bing', name: 'Bing', search: 'https://www.bing.com/search?q=' }, key: 'google',
{ key: 'baidu', name: '百度', search: 'https://www.baidu.com/s?wd=' }, name: 'Google',
{ key: 'sogou', name: '搜狗', search: 'https://www.sogou.com/web?query=' }, search: 'https://www.google.com/search?q=',
{ key: '360', name: '360', search: 'https://www.so.com/s?q=' }, path: 'M12.24 10.285V14.4h6.806c-.275 1.765-2.056 5.174-6.806 5.174-4.095 0-7.439-3.389-7.439-7.574s3.345-7.574 7.439-7.574c2.33 0 3.891.989 4.785 1.849l3.254-3.138C18.189 1.186 15.479 0 12.24 0c-6.635 0-12 5.365-12 12s5.365 12 12 12c6.926 0 11.52-4.869 11.52-11.726 0-.788-.085-1.39-.189-1.989H12.24z',
color: '#4285F4',
},
{
key: 'bing',
name: 'Bing',
search: 'https://www.bing.com/search?q=',
path: 'M5 3v14.895l4.09 2.33v-9.497l6.218 3.535 4.692-2.63-8.724-5.031V3z',
color: '#00809D',
},
{
key: 'baidu',
name: '百度',
search: 'https://www.baidu.com/s?wd=',
path: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm-3-9c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm6 0c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-3 6.5c-2.33 0-4.31-1.46-5.11-3.5h10.22c-.8 2.04-2.78 3.5-5.11 3.5z',
color: '#2932E1',
},
{
key: 'sogou',
name: '搜狗',
search: 'https://www.sogou.com/web?query=',
path: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1.5 14.5c-2.48 0-4.5-2.02-4.5-4.5h2c0 1.38 1.12 2.5 2.5 2.5s2.5-1.12 2.5-2.5h2c0 2.48-2.02 4.5-4.5 4.5zM8 9c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm8 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1z',
color: '#FB6022',
},
{
key: '360',
name: '360',
search: 'https://www.so.com/s?q=',
path: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 16c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6zm0-9c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z',
color: '#19B955',
},
] as const ] as const
type SearchEngine = (typeof SEARCH_ENGINES)[number] type SearchEngine = (typeof SEARCH_ENGINES)[number]
@@ -84,6 +115,16 @@ function readSearchEngine(): SearchEngine {
} }
} }
/** 本地用放大镜;外部引擎用各自的品牌轮廓 */
function SearchEngineIcon({ engine }: { engine: SearchEngine }) {
if (engine.path === '') return <Icon name="search_3_line" />
return (
<svg viewBox="0 0 24 24" width="18" height="18" aria-hidden="true" focusable="false">
<path d={engine.path} fill={engine.color} />
</svg>
)
}
function parseRoute(pathname: string): Route { function parseRoute(pathname: string): Route {
const segments = pathname.split('/').filter(Boolean) const segments = pathname.split('/').filter(Boolean)
if (segments[0] === 'interface') return { kind: 'api' } if (segments[0] === 'interface') return { kind: 'api' }
@@ -842,11 +883,11 @@ export default function AppNext() {
} }
variant="card" variant="card"
hotkey="k" hotkey="k"
suffix={ leading={
<div className="engine-switch" ref={engineRef}> <div className="engine-switch" ref={engineRef}>
<button <button
type="button" type="button"
className="engine-toggle" className="engine-trigger"
aria-haspopup="menu" aria-haspopup="menu"
aria-expanded={engineOpen} aria-expanded={engineOpen}
aria-label={`搜索引擎:${searchEngine.name},点击切换`} aria-label={`搜索引擎:${searchEngine.name},点击切换`}
@@ -857,8 +898,7 @@ export default function AppNext() {
} }
onClick={() => setEngineOpen((open) => !open)} onClick={() => setEngineOpen((open) => !open)}
> >
{searchEngine.name} <SearchEngineIcon engine={searchEngine} />
<span aria-hidden="true">▾</span>
</button> </button>
{engineOpen && ( {engineOpen && (
<div className="engine-menu" role="menu" aria-label="选择搜索引擎"> <div className="engine-menu" role="menu" aria-label="选择搜索引擎">