Repository: OneKeyHQ/app-monorepo
Pull request #6935: fix: OK-36729, OK-36736, OK-36749
Author: login: limichange
Created: 2025-03-24T16:12:01Z | Merged: 2025-03-25T02:27:11Z



<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **New Features**
  - Introduced an enhanced toolbar input that improves search capabilities along with bookmark and pin functionalities.
  - Added a new tool for managing popover interactions with optimized keyboard shortcut support.

- **Refactor**
  - Streamlined search input and popover handling for a more modular and responsive experience.

- **Style**
  - Updated theme color schemes and layout elements for both light and dark modes, improving hover effects and component visuals.

- **Chores**
  - Removed unused hooks and redundant imports to optimize performance.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/packages/components/tamagui.config.ts b/packages/components/tamagui.config.ts
index f286d8625855..69deeb881512 100644
--- a/packages/components/tamagui.config.ts
+++ b/packages/components/tamagui.config.ts
@@ -187,12 +187,9 @@ const lightColors = {
   ...critical,
   ...purple,
   ...pink,
-  bgApp: '#FFFFFF',
   bg: '#FFFFFF',
-  bgReverse: '#1b1b1b',
-  shadowColor: gray.gray8,
-  bgHover: neutral.neutral3,
   bgActive: neutral.neutral4,
+  bgApp: '#FFFFFF',
   bgBackdrop: grayA.grayA8,
   bgCaution: caution.caution3,
   bgCautionStrong: caution.caution9,
@@ -203,6 +200,7 @@ const lightColors = {
   bgCriticalStrongHover: critical.critical10,
   bgCriticalSubdued: critical.critical2,
   bgDisabled: neutral.neutral3,
+  bgHover: neutral.neutral3,
   bgInfo: info.info3,
   bgInfoStrong: info.info9,
   bgInfoSubdued: info.info2,
@@ -212,14 +210,15 @@ const lightColors = {
   bgPrimary: primary.primary12,
   bgPrimaryActive: primary.primary10,
   bgPrimaryHover: primary.primary11,
-  bgSubdued: gray.gray2,
+  bgReverse: '#1b1b1b',
+  bgSidebar: gray.gray2,
   bgStrong: neutral.neutral3,
-  bgStrongHover: neutral.neutral4,
   bgStrongActive: neutral.neutral5,
+  bgStrongHover: neutral.neutral4,
+  bgSubdued: gray.gray2,
   bgSuccess: success.success3,
   bgSuccessStrong: success.success9,
   bgSuccessSubdued: success.success2,
-  bgSidebar: gray.gray2,
   border: neutral.neutral6,
   borderActive: primary.primary12,
   borderCaution: caution.caution7,
@@ -252,6 +251,7 @@ const lightColors = {
   iconStrong: neutral.neutral12,
   iconSubdued: neutral.neutral9,
   iconSuccess: success.success11,
+  popoverShadowColor: grayA.grayA8,
   text: neutral.neutral12,
   textCaution: caution.caution11,
   textCautionStrong: caution.caution12,
@@ -283,12 +283,9 @@ const darkColors: typeof lightColors = {
   ...criticalDark,
   ...purpleDark,
   ...pinkDark,
-  bgApp: '#0f0f0f',
   bg: '#1b1b1b',
-  bgReverse: '#ffffff',
-  shadowColor: grayDark.gray6,
-  bgHover: neutralDark.neutral3,
   bgActive: neutralDark.neutral4,
+  bgApp: '#0f0f0f',
   bgBackdrop: grayA.grayA8,
   bgCaution: cautionDark.caution3,
   bgCautionStrong: cautionDark.caution9,
@@ -299,6 +296,7 @@ const darkColors: typeof lightColors = {
   bgCriticalStrongHover: criticalDark.critical10,
   bgCriticalSubdued: criticalDark.critical2,
   bgDisabled: neutralDark.neutral3,
+  bgHover: neutralDark.neutral3,
   bgInfo: infoDark.info3,
   bgInfoStrong: infoDark.info9,
   bgInfoSubdued: infoDark.info2,
@@ -308,14 +306,15 @@ const darkColors: typeof lightColors = {
   bgPrimary: primaryDark.primary12,
   bgPrimaryActive: primaryDark.primary10,
   bgPrimaryHover: primaryDark.primary11,
-  bgSubdued: grayDark.gray2,
+  bgReverse: '#ffffff',
+  bgSidebar: grayDark.gray2,
   bgStrong: neutralDark.neutral3,
-  bgStrongHover: neutralDark.neutral4,
   bgStrongActive: neutralDark.neutral5,
+  bgStrongHover: neutralDark.neutral4,
+  bgSubdued: grayDark.gray2,
   bgSuccess: successDark.success3,
   bgSuccessStrong: successDark.success9,
   bgSuccessSubdued: successDark.success2,
-  bgSidebar: grayDark.gray2,
   border: neutralDark.neutral6,
   borderActive: primaryDark.primary12,
   borderCaution: cautionDark.caution7,
@@ -348,6 +347,7 @@ const darkColors: typeof lightColors = {
   iconStrong: neutralDark.neutral12,
   iconSubdued: neutralDark.neutral9,
   iconSuccess: successDark.success11,
+  popoverShadowColor: grayA.grayA8,
   text: neutralDark.neutral12,
   textCaution: cautionDark.caution11,
   textCautionStrong: cautionDark.caution12,
diff --git a/packages/kit/src/views/AppUpdate/pages/WhatsNew.tsx b/packages/kit/src/views/AppUpdate/pages/WhatsNew.tsx
index 6179a53a8a6c..6902b66d991d 100644
--- a/packages/kit/src/views/AppUpdate/pages/WhatsNew.tsx
+++ b/packages/kit/src/views/AppUpdate/pages/WhatsNew.tsx
@@ -6,7 +6,6 @@ import {
   Page,
   ScrollView,
   YStack,
-  useMedia,
 } from '@onekeyhq/components';
 import { ETranslations } from '@onekeyhq/shared/src/locale';
 import platformEnv from '@onekeyhq/shared/src/platformEnv';
diff --git a/packages/kit/src/views/Discovery/components/HeaderLeftToolBar/HeaderLeftToolBarInput.tsx b/packages/kit/src/views/Discovery/components/HeaderLeftToolBar/HeaderLeftToolBarInput.tsx
new file mode 100644
index 000000000000..91806a511b9b
--- /dev/null
+++ b/packages/kit/src/views/Discovery/components/HeaderLeftToolBar/HeaderLeftToolBarInput.tsx
@@ -0,0 +1,213 @@
+import { useEffect, useRef, useState } from 'react';
+
+import { useIntl } from 'react-intl';
+
+import type { ColorTokens, IScrollViewRef, Icon } from '@onekeyhq/components';
+import { Input, Popover, ScrollView, Stack } from '@onekeyhq/components';
+import { useShortcutsOnRouteFocused } from '@onekeyhq/kit/src/hooks/useShortcutsOnRouteFocused';
+import { ETranslations } from '@onekeyhq/shared/src/locale';
+import platformEnv from '@onekeyhq/shared/src/platformEnv';
+import { EShortcutEvents } from '@onekeyhq/shared/src/shortcuts/shortcuts.enum';
+
+import { useSearchModalData } from '../../hooks/useSearchModalData';
+import { useSearchPopover } from '../../hooks/useSearchPopover';
+import { SearchPopover } from '../../pages/Dashboard/Welcome/SearchPopover';
+import { formatHiddenHttpsUrl } from '../../utils/explorerUtils';
+import { DappInfoPopoverContent } from '../DappInfoPopoverContent';
+import { SearchResultContent } from '../SearchResultContent';
+
+import type { ISearchResultContentRef } from '../SearchResultContent';
+import type { TextInput } from 'react-native';
+
+interface IHeaderLeftToolBarInputProps {
+  iconConfig: {
+    iconName: NonNullable<Parameters<typeof Icon>[0]['name']>;
+    iconColor: ColorTokens;
+  };
+  url: string;
+  isBookmark?: boolean;
+  isPinned?: boolean;
+  onBookmarkPress?: (bookmark: boolean) => void;
+  onPinnedPress?: (pinned: boolean) => void;
+  inputProps?: {
+    onPress?: () => void;
+  };
+  hostSecurity: any;
+}
+
+function HeaderLeftToolBarInput({
+  iconConfig,
+  url,
+  isBookmark,
+  isPinned,
+  onBookmarkPress,
+  onPinnedPress,
+  inputProps,
+  hostSecurity,
+}: IHeaderLeftToolBarInputProps) {
+  const intl = useIntl();
+  const [dappInfoIsOpen, setDappInfoIsOpen] = useState(false);
+  const [searchValue, setSearchValue] = useState('');
+  const [internalValue, setInternalValue] = useState('');
+  const scrollViewRef = useRef<IScrollViewRef>(null);
+  const searchResultRef = useRef<ISearchResultContentRef>(null);
+  const inputRef = useRef<TextInput>(null);
+  const { hiddenHttpsUrl } = formatHiddenHttpsUrl(url);
+
+  useEffect(() => {
+    if (hiddenHttpsUrl) {
+      setInternalValue(hiddenHttpsUrl);
+    }
+  }, [hiddenHttpsUrl]);
+
+  const {
+    localData,
+    searchList,
+    displaySearchList,
+    displayHistoryList,
+    SEARCH_ITEM_ID,
+    totalItems,
+  } = useSearchModalData(searchValue);
+
+  const {
+    selectedIndex,
+    handleKeyDown,
+    handleInputBlur,
+    isPopoverOpen,
+    setIsPopoverOpen,
+  } = useSearchPopover({
+    scrollViewRef,
+    totalItems,
+    searchValue,
+    displaySearchList,
+    displayHistoryList,
+    onEnterPress: () => {
+      if (searchResultRef.current) {
+        searchResultRef.current.openSelectedItem();
+        setIsPopoverOpen(false);
+      }
+    },
+    onEscape: () => {
+      setIsPopoverOpen(false);
+      inputRef.current?.blur();
+    },
+  });
+
+  useShortcutsOnRouteFocused(EShortcutEvents.ChangeCurrentTabUrl, () => {
+    if (platformEnv.isDesktop) {
+      inputRef.current?.focus();
+    }
+  });
+
+  return (
+    <Stack flex={1}>
+      <Input
+        ref={inputRef}
+        containerProps={{ mx: '$6', flex: 1 } as any}
+        size="small"
+        leftAddOnProps={{
+          ...iconConfig,
+          iconSize: '$4',
+          mr: '$-2',
+          onPress: () => {
+            setDappInfoIsOpen(true);
+          },
+        }}
+        pb="$1.5"
+        value={internalValue}
+        onChangeText={(text) => {
+          setInternalValue(text);
+          setSearchValue(text);
+          setIsPopoverOpen(true);
+        }}
+        onBlur={handleInputBlur}
+        selectTextOnFocus
+        testID="explore-index-search-input"
+        onFocus={() => setIsPopoverOpen(true)}
+        // @ts-expect-error
+        onKeyPress={handleKeyDown}
+        addOns={[
+          {
+            iconName: isBookmark ? 'StarSolid' : 'StarOutline',
+            onPress: () => onBookmarkPress?.(!isBookmark),
+            tooltipProps: {
+              shortcutKey: EShortcutEvents.AddOrRemoveBookmark,
+              renderContent: intl.formatMessage({
+                id: isBookmark
+                  ? ETranslations.explore_remove_bookmark
+                  : ETranslations.explore_add_bookmark,
+              }),
+            },
+            testID: `action-header-item-${
+              !isBookmark ? 'bookmark' : 'remove-bookmark'
+            }`,
+            ...(isBookmark && {
+              iconColor: '$icon',
+            }),
+          },
+          {
+            iconName: isPinned ? 'ThumbtackSolid' : 'ThumbtackOutline',
+            onPress: () => onPinnedPress?.(!isPinned),
+            tooltipProps: {
+              shortcutKey: EShortcutEvents.PinOrUnpinTab,
+              renderContent: intl.formatMessage({
+                id: isPinned
+                  ? ETranslations.explore_unpin
+                  : ETranslations.explore_pin,
+              }),
+            },
+            testID: `action-header-item-${!isPinned ? 'pin' : 'un-pin'}`,
+            ...(isPinned && {
+              iconColor: '$icon',
+            }),
+          },
+        ]}
+        {...inputProps}
+      />
+      <Stack ml={24}>
+        <Popover
+          placement="bottom-start"
+          title="dApp info"
+          open={dappInfoIsOpen}
+          onOpenChange={setDappInfoIsOpen}
+          renderTrigger={<Stack />}
+          renderContent={({ closePopover }) => (
+            <DappInfoPopoverContent
+              iconConfig={iconConfig}
+              hostSecurity={hostSecurity}
+              closePopover={closePopover}
+            />
+          )}
+        />
+      </Stack>
+
+      <SearchPopover
+        containerProps={{
+          px: 24,
+        }}
+        isOpen={isPopoverOpen}
+      >
+        <ScrollView ref={scrollViewRef} maxHeight={310}>
+          <Stack py="$2">
+            <SearchResultContent
+              searchValue={searchValue}
+              localData={localData}
+              searchList={searchList}
+              displaySearchList={displaySearchList}
+              displayBookmarkList={false}
+              displayHistoryList={displayHistoryList}
+              SEARCH_ITEM_ID={SEARCH_ITEM_ID}
+              selectedIndex={selectedIndex}
+              innerRef={searchResultRef}
+              onItemClick={() => {
+                setIsPopoverOpen(false);
+              }}
+            />
+          </Stack>
+        </ScrollView>
+      </SearchPopover>
+    </Stack>
+  );
+}
+
+export default HeaderLeftToolBarInput;
diff --git a/packages/kit/src/views/Discovery/components/HeaderLeftToolBar/index.tsx b/packages/kit/src/views/Discovery/components/HeaderLeftToolBar/index.tsx
index 9814b33c12bf..f5ef3f452dcf 100644
--- a/packages/kit/src/views/Discovery/components/HeaderLeftToolBar/index.tsx
+++ b/packages/kit/src/views/Discovery/components/HeaderLeftToolBar/index.tsx
@@ -1,11 +1,7 @@
-import { useState } from 'react';
-
 import { useIntl } from 'react-intl';
 
 import {
   Icon,
-  Input,
-  Popover,
   SizableText,
   Stack,
   Tooltip,
@@ -17,11 +13,12 @@ import {
   HeaderIconButton,
 } from '@onekeyhq/components/src/layouts/Navigation/Header';
 import { ETranslations } from '@onekeyhq/shared/src/locale';
+import platformEnv from '@onekeyhq/shared/src/platformEnv';
 import { EShortcutEvents } from '@onekeyhq/shared/src/shortcuts/shortcuts.enum';
 
 import { useUrlRiskConfig } from '../../hooks/useUrlRiskConfig';
-import { formatHiddenHttpsUrl } from '../../utils/explorerUtils';
-import { DappInfoPopoverContent } from '../DappInfoPopoverContent';
+
+import HeaderLeftToolBarInput from './HeaderLeftToolBarInput';
 
 function HeaderLeftToolBar({
   url,
@@ -53,12 +50,9 @@ function HeaderLeftToolBar({
   onPinnedPress?: (pinned: boolean) => void;
 }) {
   const { hostSecurity, iconConfig } = useUrlRiskConfig(url);
-  const [dappInfoIsOpen, setDappInfoIsOpen] = useState(false);
   const intl = useIntl();
   const media = useMedia();
 
-  const { isHttpsUrl, hiddenHttpsUrl } = formatHiddenHttpsUrl(url);
-
   if (media.md) {
     return (
       <Stack
@@ -86,11 +80,6 @@ function HeaderLeftToolBar({
       </Stack>
     );
   }
-  const inputProps = {
-    onPress: () => {
-      onSearch?.(url);
-    },
-  };
 
   return (
     <XStack alignItems="center" justifyContent="center" pl="$2">
@@ -131,77 +120,18 @@ function HeaderLeftToolBar({
           testID={`action-header-item-${loading ? 'stop-loading' : 'reload'}`}
         />
       </HeaderButtonGroup>
-      <Stack flex={1}>
-        <Input
-          containerProps={{ mx: '$6', flex: 1 } as any}
-          size="small"
-          leftAddOnProps={{
-            ...iconConfig,
-            iconSize: '$4',
-            mr: '$-2',
-            onPress: () => {
-              setDappInfoIsOpen(true);
-            },
-          }}
-          pb="$1.5"
-          value={hiddenHttpsUrl}
-          selectTextOnFocus
-          testID="explore-index-search-input"
-          addOns={[
-            {
-              iconName: isBookmark ? 'StarSolid' : 'StarOutline',
-              onPress: () => onBookmarkPress?.(!isBookmark),
-              tooltipProps: {
-                shortcutKey: EShortcutEvents.AddOrRemoveBookmark,
-                renderContent: intl.formatMessage({
-                  id: isBookmark
-                    ? ETranslations.explore_remove_bookmark
-                    : ETranslations.explore_add_bookmark,
-                }),
-              },
-              testID: `action-header-item-${
-                !isBookmark ? 'bookmark' : 'remove-bookmark'
-              }`,
-              ...(isBookmark && {
-                iconColor: '$icon',
-              }),
-            },
-            {
-              iconName: isPinned ? 'ThumbtackSolid' : 'ThumbtackOutline',
-              onPress: () => onPinnedPress?.(!isPinned),
-              tooltipProps: {
-                shortcutKey: EShortcutEvents.PinOrUnpinTab,
-                renderContent: intl.formatMessage({
-                  id: isPinned
-                    ? ETranslations.explore_unpin
-                    : ETranslations.explore_pin,
-                }),
-              },
-              testID: `action-header-item-${!isPinned ? 'pin' : 'un-pin'}`,
-              ...(isPinned && {
-                iconColor: '$icon',
-              }),
-            },
-          ]}
-          {...(inputProps as any)}
-        />
-        <Stack ml={24}>
-          <Popover
-            placement="bottom-start"
-            title="dApp info"
-            open={dappInfoIsOpen}
-            onOpenChange={setDappInfoIsOpen}
-            renderTrigger={<Stack />}
-            renderContent={({ closePopover }) => (
-              <DappInfoPopoverContent
-                iconConfig={iconConfig}
-                hostSecurity={hostSecurity}
-                closePopover={closePopover}
-              />
-            )}
-          />
-        </Stack>
-      </Stack>
+      <HeaderLeftToolBarInput
+        url={url}
+        hostSecurity={hostSecurity}
+        iconConfig={iconConfig}
+        inputProps={{
+          onPress: !platformEnv.isDesktop ? () => onSearch?.(url) : undefined,
+        }}
+        isBookmark={isBookmark}
+        isPinned={isPinned}
+        onBookmarkPress={onBookmarkPress}
+        onPinnedPress={onPinnedPress}
+      />
     </XStack>
   );
 }
diff --git a/packages/kit/src/views/Discovery/hooks/useSearchModalData.ts b/packages/kit/src/views/Discovery/hooks/useSearchModalData.ts
index 2e21909be0ab..f6be43788995 100644
--- a/packages/kit/src/views/Discovery/hooks/useSearchModalData.ts
+++ b/packages/kit/src/views/Discovery/hooks/useSearchModalData.ts
@@ -1,4 +1,4 @@
-import { useEffect, useState } from 'react';
+import { useEffect, useMemo, useState } from 'react';
 
 import { useIntl } from 'react-intl';
 
@@ -88,6 +88,20 @@ export function useSearchModalData(searchValue: string) {
     (localData?.bookmarkData ?? []).length > 0 && !displaySearchList;
   const displayHistoryList = (localData?.historyData ?? []).length > 0;
 
+  // Calculate total items
+  const totalItems = useMemo(() => {
+    const searchCount = displaySearchList ? searchList.length : 0;
+    const historyCount = displayHistoryList
+      ? localData?.historyData?.length || 0
+      : 0;
+    return searchCount + historyCount;
+  }, [
+    displaySearchList,
+    searchList.length,
+    displayHistoryList,
+    localData?.historyData?.length,
+  ]);
+
   return {
     localData: localData ?? null,
     refreshLocalData,
@@ -96,5 +110,7 @@ export function useSearchModalData(searchValue: string) {
     displayBookmarkList,
     displayHistoryList,
     SEARCH_ITEM_ID,
+    isEmpty: !displaySearchList && !displayBookmarkList && !displayHistoryList,
+    totalItems,
   };
 }
diff --git a/packages/kit/src/views/Discovery/hooks/useSearchPopover.ts b/packages/kit/src/views/Discovery/hooks/useSearchPopover.ts
new file mode 100644
index 000000000000..1885d65ccc21
--- /dev/null
+++ b/packages/kit/src/views/Discovery/hooks/useSearchPopover.ts
@@ -0,0 +1,124 @@
+import { useCallback, useEffect, useMemo, useState } from 'react';
+
+import type { IScrollViewRef } from '@onekeyhq/components';
+import useAppNavigation from '@onekeyhq/kit/src/hooks/useAppNavigation';
+import platformEnv from '@onekeyhq/shared/src/platformEnv';
+import { EDiscoveryModalRoutes } from '@onekeyhq/shared/src/routes/discovery';
+import { EModalRoutes } from '@onekeyhq/shared/src/routes/modal';
+
+const ITEM_HEIGHT = 48; // Height of each item in the search results
+
+interface IUseSearchPopoverProps {
+  scrollViewRef: React.RefObject<IScrollViewRef>;
+  totalItems: number;
+  onEnterPress?: () => void;
+  onEscape?: () => void;
+  searchValue?: string;
+  displaySearchList: boolean;
+  displayHistoryList: boolean;
+}
+
+export function useSearchPopover({
+  scrollViewRef,
+  totalItems,
+  onEnterPress,
+  onEscape,
+  searchValue,
+  displaySearchList,
+  displayHistoryList,
+}: IUseSearchPopoverProps) {
+  const [selectedIndex, setSelectedIndex] = useState(-1);
+  const [isPopoverOpen, setIsPopoverOpen] = useState(false);
+
+  const navigation = useAppNavigation();
+
+  // Scroll to selected item
+  useEffect(() => {
+    if (scrollViewRef.current) {
+      const getSelectedItemDistance = () => {
+        if (selectedIndex < 4) return 0;
+        return selectedIndex * ITEM_HEIGHT;
+      };
+
+      const distance = getSelectedItemDistance();
+      scrollViewRef.current.scrollTo({
+        y: distance,
+        animated: true,
+      });
+    }
+  }, [selectedIndex, scrollViewRef]);
+
+  // Reset scroll position when search value changes
+  useEffect(() => {
+    if (scrollViewRef.current) {
+      scrollViewRef.current.scrollTo({
+        y: 0,
+      });
+    }
+  }, [searchValue, scrollViewRef]);
+
+  const handleKeyDown = useCallback(
+    (e: KeyboardEvent) => {
+      if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
+        e.preventDefault();
+
+        if (totalItems === 0) return;
+
+        if (e.key === 'ArrowDown') {
+          setSelectedIndex((prev) => (prev + 2 > totalItems ? prev : prev + 1));
+        } else if (e.key === 'ArrowUp') {
+          setSelectedIndex((prev) => (prev > -1 ? prev - 1 : -1));
+        }
+      }
+
+      if (e.key === 'Enter') {
+        e.preventDefault();
+        onEnterPress?.();
+      }
+
+      if (e.key === 'Escape') {
+        onEscape?.();
+        setIsPopoverOpen(false);
+      }
+    },
+    [totalItems, onEnterPress, onEscape],
+  );
+
+  const resetSelectedIndex = () => {
+    setSelectedIndex(-1);
+  };
+
+  const isPopoverVisible = useMemo(
+    () =>
+      isPopoverOpen && searchValue && searchValue.length > 0
+        ? displaySearchList || displayHistoryList
+        : false,
+    [isPopoverOpen, searchValue, displaySearchList, displayHistoryList],
+  );
+
+  const handleInputBlur = useCallback(() => {
+    setTimeout(() => {
+      setIsPopoverOpen(false);
+    }, 200);
+  }, [setIsPopoverOpen]);
+
+  const handleSearchBarPress = useCallback(() => {
+    // only on mobile
+    if (!platformEnv.isDesktop) {
+      navigation.pushModal(EModalRoutes.DiscoveryModal, {
+        screen: EDiscoveryModalRoutes.SearchModal,
+      });
+    }
+  }, [navigation]);
+
+  return {
+    handleSearchBarPress,
+    selectedIndex,
+    handleKeyDown,
+    resetSelectedIndex,
+    isPopoverVisible,
+    isPopoverOpen,
+    setIsPopoverOpen,
+    handleInputBlur,
+  };
+}
diff --git a/packages/kit/src/views/Discovery/pages/Browser/DesktopBrowserNavigationContainer.tsx b/packages/kit/src/views/Discovery/pages/Browser/DesktopBrowserNavigationContainer.tsx
index 0ca1eb92810e..d16c89b44537 100644
--- a/packages/kit/src/views/Discovery/pages/Browser/DesktopBrowserNavigationContainer.tsx
+++ b/packages/kit/src/views/Discovery/pages/Browser/DesktopBrowserNavigationContainer.tsx
@@ -9,6 +9,7 @@ import {
   useBrowserBookmarkAction,
   useBrowserTabActions,
 } from '@onekeyhq/kit/src/states/jotai/contexts/discovery';
+import platformEnv from '@onekeyhq/shared/src/platformEnv';
 import {
   EDiscoveryModalRoutes,
   EModalRoutes,
@@ -153,7 +154,7 @@ function DesktopBrowserNavigationBar({
   useShortcutsOnRouteFocused(EShortcutEvents.PinOrUnpinTab, onShortcutsPin);
 
   const onShortcutsChangeUrl = useCallback(() => {
-    if (tab?.url && isActive) {
+    if (tab?.url && isActive && !platformEnv.isDesktop) {
       handleSearch(tab.url);
     }
   }, [handleSearch, isActive, tab?.url]);
diff --git a/packages/kit/src/views/Discovery/pages/Dashboard/Welcome/KeyboardShortcutKey.tsx b/packages/kit/src/views/Discovery/pages/Dashboard/Welcome/KeyboardShortcutKey.tsx
index 271eb5b93af6..df561bf3960c 100644
--- a/packages/kit/src/views/Discovery/pages/Dashboard/Welcome/KeyboardShortcutKey.tsx
+++ b/packages/kit/src/views/Discovery/pages/Dashboard/Welcome/KeyboardShortcutKey.tsx
@@ -9,7 +9,8 @@ export function KeyboardShortcutKey({ label }: IKeyboardShortcutKeyProps) {
     <Stack
       bg="$bgStrong"
       borderRadius="$1"
-      w="$4"
+      px="$0.5"
+      minWidth="$4"
       h="$4"
       alignItems="center"
       justifyContent="center"
diff --git a/packages/kit/src/views/Discovery/pages/Dashboard/Welcome/SearchInput.tsx b/packages/kit/src/views/Discovery/pages/Dashboard/Welcome/SearchInput.tsx
index a13efa8d83f4..a1dd46f2c507 100644
--- a/packages/kit/src/views/Discovery/pages/Dashboard/Welcome/SearchInput.tsx
+++ b/packages/kit/src/views/Discovery/pages/Dashboard/Welcome/SearchInput.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useEffect, useRef, useState } from 'react';
+import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
 
 import { useIntl } from 'react-intl';
 
@@ -25,6 +25,7 @@ import { shortcutsKeys } from '@onekeyhq/shared/src/shortcuts/shortcutsKeys.enum
 
 import { SearchResultContent } from '../../../components/SearchResultContent';
 import { useSearchModalData } from '../../../hooks/useSearchModalData';
+import { useSearchPopover } from '../../../hooks/useSearchPopover';
 
 import { KeyboardShortcutKey } from './KeyboardShortcutKey';
 import { SearchPopover } from './SearchPopover';
@@ -32,20 +33,13 @@ import { SearchPopover } from './SearchPopover';
 import type { ISearchResultContentRef } from '../../../components/SearchResultContent';
 import type { TextInput } from 'react-native';
 
-const ITEM_HEIGHT = 48; // Height of each item in the search results
-
 export function SearchInput() {
   const intl = useIntl();
   const [searchValue, setSearchValue] = useState('');
-  const [isPopoverOpen, setIsPopoverOpen] = useState(false);
-  const [selectedIndex, setSelectedIndex] = useState(-1);
   const searchResultRef = useRef<ISearchResultContentRef>(null);
   const scrollViewRef = useRef<IScrollViewRef>(null);
   const inputRef = useRef<TextInput>(null);
-
-  useEffect(() => {
-    setSelectedIndex(-1);
-  }, [isPopoverOpen]);
+  const navigation = useAppNavigation();
 
   const {
     localData,
@@ -53,33 +47,59 @@ export function SearchInput() {
     displaySearchList,
     displayHistoryList,
     SEARCH_ITEM_ID,
+    refreshLocalData,
+    totalItems,
   } = useSearchModalData(searchValue);
 
+  const {
+    handleInputBlur,
+    handleKeyDown,
+    handleSearchBarPress,
+    isPopoverOpen,
+    isPopoverVisible,
+    resetSelectedIndex,
+    selectedIndex,
+    setIsPopoverOpen,
+  } = useSearchPopover({
+    scrollViewRef,
+    totalItems,
+    searchValue,
+    onEnterPress: () => {
+      if (searchResultRef.current) {
+        searchResultRef.current.openSelectedItem();
+        setIsPopoverOpen(false);
+      }
+    },
+    onEscape: () => {
+      setIsPopoverOpen(false);
+      inputRef.current?.blur();
+    },
+    displaySearchList: Boolean(displaySearchList),
+    displayHistoryList: Boolean(displayHistoryList),
+  });
+
   useEffect(() => {
-    scrollViewRef?.current?.scrollTo({
-      y: 0,
-    });
-  }, [searchValue]);
+    if (platformEnv.isDesktop) {
+      setTimeout(() => {
+        inputRef.current?.focus();
+      }, 200);
+    }
+  }, []);
 
-  const navigation = useAppNavigation();
-  const handleSearchBarPress = useCallback(() => {
-    // only on mobile
-    if (!platformEnv.isDesktop) {
-      navigation.pushModal(EModalRoutes.DiscoveryModal, {
-        screen: EDiscoveryModalRoutes.SearchModal,
-      });
+  useEffect(() => {
+    if (isPopoverOpen) {
+      void refreshLocalData();
     }
-  }, [navigation]);
+  }, [refreshLocalData, isPopoverOpen]);
+
+  useEffect(() => {
+    if (!isPopoverOpen) {
+      resetSelectedIndex();
+    }
+  }, [isPopoverOpen, resetSelectedIndex]);
 
   const handleInputChange = useCallback((text: string) => {
     setSearchValue(text);
-    setSelectedIndex(-1);
-  }, []);
-
-  const handleInputBlur = useCallback(() => {
-    setTimeout(() => {
-      setIsPopoverOpen(false);
-    }, 100);
   }, []);
 
   useShortcuts(EShortcutEvents.NewTab, () => {
@@ -93,68 +113,6 @@ export function SearchInput() {
     }
   });
 
-  useEffect(() => {
-    if (scrollViewRef.current) {
-      const getSelectedItemDistance = () => {
-        if (selectedIndex < 4) return 0;
-
-        // Calculate item height based on your UI design
-        return selectedIndex * ITEM_HEIGHT;
-      };
-
-      const distance = getSelectedItemDistance();
-      scrollViewRef.current.scrollTo({
-        y: distance,
-        animated: true,
-      });
-    }
-  }, [selectedIndex]);
-
-  const handleKeyDown = useCallback(
-    (e: KeyboardEvent) => {
-      // Prevent default behavior for up and down arrow keys
-      if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
-        e.preventDefault();
-
-        // Calculate total items count
-        const searchCount = displaySearchList ? searchList.length : 0;
-        const historyCount = displayHistoryList
-          ? localData?.historyData?.length || 0
-          : 0;
-        const totalItems = searchCount + historyCount;
-
-        if (totalItems === 0) return;
-
-        // Update selected index based on arrow key
-        if (e.key === 'ArrowDown') {
-          setSelectedIndex((prev) => (prev + 2 > totalItems ? prev : prev + 1));
-        } else if (e.key === 'ArrowUp') {
-          setSelectedIndex((prev) => (prev > -1 ? prev - 1 : -1));
-        }
-      }
-
-      // Handle Enter key press - call openSelectedItem
-      if (e.key === 'Enter') {
-        e.preventDefault();
-        if (searchResultRef.current) {
-          searchResultRef.current.openSelectedItem();
-          setIsPopoverOpen(false);
-        }
-      }
-
-      if (e.key === 'Escape') {
-        setIsPopoverOpen(false);
-        inputRef.current?.blur();
-      }
-    },
-    [
-      displaySearchList,
-      searchList.length,
-      displayHistoryList,
-      localData?.historyData?.length,
-    ],
-  );
-
   return (
     <>
       <View position="relative" width="100%">
@@ -228,7 +186,12 @@ export function SearchInput() {
           ) : null}
         </XStack>
 
-        <SearchPopover isOpen={isPopoverOpen}>
+        <SearchPopover
+          containerProps={{
+            $gtSm: { width: 384 },
+          }}
+          isOpen={isPopoverVisible}
+        >
           <ScrollView ref={scrollViewRef} maxHeight={310}>
             <Stack py="$2">
               <SearchResultContent
diff --git a/packages/kit/src/views/Discovery/pages/Dashboard/Welcome/SearchPopover.tsx b/packages/kit/src/views/Discovery/pages/Dashboard/Welcome/SearchPopover.tsx
index bcbde42061fb..78db8becaeb4 100644
--- a/packages/kit/src/views/Discovery/pages/Dashboard/Welcome/SearchPopover.tsx
+++ b/packages/kit/src/views/Discovery/pages/Dashboard/Welcome/SearchPopover.tsx
@@ -1,15 +1,18 @@
 import type { FC, ReactNode } from 'react';
 
 import { Portal, Stack } from '@onekeyhq/components';
+import type { IStackProps } from '@onekeyhq/components';
 
 export interface ISearchPopoverProps {
   isOpen: boolean;
   children: ReactNode;
+  containerProps?: Partial<IStackProps>;
 }
 
 export const SearchPopover: FC<ISearchPopoverProps> = ({
   isOpen,
   children,
+  containerProps,
 }) => (
   <Portal name="search-popover">
     {isOpen ? (
@@ -20,15 +23,6 @@ export const SearchPopover: FC<ISearchPopoverProps> = ({
         right={0}
         width="100%"
         marginTop="$2"
-        borderRadius="$3"
-        backgroundColor="$bg"
-        borderWidth={1}
-        borderColor="$borderSubdued"
-        shadowColor="$shadowColor"
-        shadowOffset={{ width: 0, height: 4 }}
-        shadowOpacity={0.15}
-        shadowRadius={8}
-        $gtSm={{ width: 384 }}
         animation="quick"
         enterStyle={{
           opacity: 0,
@@ -40,8 +34,20 @@ export const SearchPopover: FC<ISearchPopoverProps> = ({
         }}
         opacity={1}
         scale={1}
+        {...containerProps}
       >
-        {children}
+        <Stack
+          borderRadius="$3"
+          backgroundColor="$bg"
+          borderWidth={1}
+          borderColor="$borderSubdued"
+          shadowColor="$popoverShadowColor"
+          shadowOffset={{ width: 0, height: 4 }}
+          shadowOpacity={0.05}
+          shadowRadius={8}
+        >
+          {children}
+        </Stack>
       </Stack>
     ) : null}
   </Portal>
diff --git a/packages/kit/src/views/Discovery/pages/Dashboard/Welcome/WelcomeItem.tsx b/packages/kit/src/views/Discovery/pages/Dashboard/Welcome/WelcomeItem.tsx
index af223fda1d2e..4b410dc5840a 100644
--- a/packages/kit/src/views/Discovery/pages/Dashboard/Welcome/WelcomeItem.tsx
+++ b/packages/kit/src/views/Discovery/pages/Dashboard/Welcome/WelcomeItem.tsx
@@ -38,7 +38,7 @@ const SCALE_DURATION_BASE = 3500;
 const SCALE_DURATION_VARIANCE = 1000;
 const SCALE_MAX_DELAY = 1000;
 
-const DEFAULT_SHADOW_OPACITY = 0.3;
+const DEFAULT_SHADOW_OPACITY = 0.4;
 const HOVER_SHADOW_OPACITY = 0.2;
 const ANIMATION_SHADOW_OPACITY = 0.25;
 
@@ -109,7 +109,7 @@ export const WelcomeItem = memo(
     const scale = useSharedValue(1);
     const shadowOpacity = useSharedValue(DEFAULT_SHADOW_OPACITY);
     const handleWebSite = useWebSiteHandler();
-    const shadowColor = useThemeValue('shadowColor');
+    const shadowColor = useThemeValue('popoverShadowColor');
 
     useEffect(() => {
       setTimeout(
diff --git a/packages/kit/src/views/Staking/components/TradeOrBuy.tsx b/packages/kit/src/views/Staking/components/TradeOrBuy.tsx
index 6381c013b286..15b9491b47da 100644
--- a/packages/kit/src/views/Staking/components/TradeOrBuy.tsx
+++ b/packages/kit/src/views/Staking/components/TradeOrBuy.tsx
@@ -2,7 +2,7 @@ import { useCallback } from 'react';
 
 import { useIntl } from 'react-intl';
 
-import type { IPageNavigationProp, IStackProps } from '@onekeyhq/components';
+import type { IPageNavigationProp } from '@onekeyhq/components';
 import { Button, SizableText, XStack } from '@onekeyhq/components';
 import { getNetworkIdsMap } from '@onekeyhq/shared/src/config/networkIds';
 import { ETranslations } from '@onekeyhq/shared/src/locale';


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 3**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: ASSERTIVE**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between d776ff25f9711dc46f153fde48a9ff3a7c918ecf and 912e5882d7ef320c9f37d63460970c445c7e653b.

</details>

<details>
<summary>📒 Files selected for processing (12)</summary>

* `packages/components/tamagui.config.ts` (8 hunks)
* `packages/kit/src/views/AppUpdate/pages/WhatsNew.tsx` (0 hunks)
* `packages/kit/src/views/Discovery/components/HeaderLeftToolBar/HeaderLeftToolBarInput.tsx` (1 hunks)
* `packages/kit/src/views/Discovery/components/HeaderLeftToolBar/index.tsx` (2 hunks)
* `packages/kit/src/views/Discovery/hooks/useSearchModalData.ts` (3 hunks)
* `packages/kit/src/views/Discovery/hooks/useSearchPopover.ts` (1 hunks)
* `packages/kit/src/views/Discovery/pages/Browser/DesktopBrowserNavigationContainer.tsx` (2 hunks)
* `packages/kit/src/views/Discovery/pages/Dashboard/Welcome/KeyboardShortcutKey.tsx` (1 hunks)
* `packages/kit/src/views/Discovery/pages/Dashboard/Welcome/SearchInput.tsx` (3 hunks)
* `packages/kit/src/views/Discovery/pages/Dashboard/Welcome/SearchPopover.tsx` (2 hunks)
* `packages/kit/src/views/Discovery/pages/Dashboard/Welcome/WelcomeItem.tsx` (2 hunks)
* `packages/kit/src/views/Staking/components/TradeOrBuy.tsx` (1 hunks)

</details>

<details>
<summary>💤 Files with no reviewable changes (1)</summary>

* packages/kit/src/views/AppUpdate/pages/WhatsNew.tsx

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Definitions (1)</summary>

<details>
<summary>packages/kit/src/views/Discovery/components/HeaderLeftToolBar/HeaderLeftToolBarInput.tsx (3)</summary><blockquote>

<details>
<summary>packages/kit/src/views/Discovery/hooks/useSearchModalData.ts (2)</summary>

* `useSearchModalData` (29-116)
* `SEARCH_ITEM_ID` (11-11)

</details>
<details>
<summary>packages/kit/src/views/Discovery/hooks/useSearchPopover.ts (1)</summary>

* `useSearchPopover` (21-124)

</details>
<details>
<summary>packages/kit/src/views/Discovery/pages/Dashboard/Welcome/SearchPopover.tsx (1)</summary>

* `SearchPopover` (12-54)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>🔇 Additional comments (41)</summary><blockquote>

<details>
<summary>packages/kit/src/views/Staking/components/TradeOrBuy.tsx (1)</summary>

`5-5`: **Clean import removal.**

Removed unused `IStackProps` type import. Good code hygiene.

</details>
<details>
<summary>packages/kit/src/views/Discovery/pages/Browser/DesktopBrowserNavigationContainer.tsx (2)</summary>

`12-12`: **Good addition for platform detection**

Adding the platformEnv import enables better platform-specific behavior handling.

---

`157-157`: **Smart platform condition added**

Adding the `!platformEnv.isDesktop` check prevents the search modal from opening on desktop platforms. This makes sense if desktop has a different search interaction pattern.

</details>
<details>
<summary>packages/kit/src/views/Discovery/pages/Dashboard/Welcome/KeyboardShortcutKey.tsx (1)</summary>

`12-13`: **Better responsive sizing approach**

Replacing fixed width with padding and minimum width improves how the component handles different text lengths. The component will now adapt better to different content sizes while maintaining a minimum width.

</details>
<details>
<summary>packages/kit/src/views/Discovery/pages/Dashboard/Welcome/SearchPopover.tsx (4)</summary>

`4-4`: **Proper type import added**

Adding the IStackProps type import supports the new containerProps feature.

---

`9-9`: **Good flexibility enhancement**

Adding the containerProps option makes the component more reusable and customizable.

---

`15-15`: **Properly implemented props passing**

The containerProps parameter is correctly passed to the component and spread onto the Stack element.



Also applies to: 37-37

---

`39-50`: **Clean separation of concerns**

Moving visual styling to an inner Stack separates positioning/animation from visual styling. This creates better component architecture by:
1. Outer Stack handles positioning and animation
2. Inner Stack manages visual appearance

This structure is more maintainable and follows better component design principles.

</details>
<details>
<summary>packages/kit/src/views/Discovery/hooks/useSearchModalData.ts (3)</summary>

`1-1`: **Added useMemo for optimization**

Adding useMemo import supports the new performance optimizations.

---

`92-103`: **Good performance optimization**

The totalItems calculation uses useMemo to avoid unnecessary recalculations. It properly considers both search and history data based on display conditions.

The dependencies array correctly includes all variables used in the calculation.

---

`113-114`: **Useful metadata properties added**

The isEmpty and totalItems properties provide valuable information for components using this hook. They'll help with rendering decisions and UI state handling.

</details>
<details>
<summary>packages/kit/src/views/Discovery/components/HeaderLeftToolBar/index.tsx (3)</summary>

`16-16`: **Added platformEnv import for conditional rendering.**

The import of `platformEnv` enables platform-specific behavior in the component.

---

`21-21`: **Added new component import for better code organization.**

Extracting input functionality to a dedicated component is a good refactoring practice.

---

`123-134`: **Improved component structure by extracting input logic.**

The refactoring replaces inline input handling with a dedicated component, making the code more maintainable. The platform check for desktop environments correctly handles different interaction patterns.

</details>
<details>
<summary>packages/kit/src/views/Discovery/hooks/useSearchPopover.ts (7)</summary>

`1-8`: **Good hook setup with appropriate imports.**

The imports include necessary React hooks and components for the search popover functionality.

---

`9-19`: **Well-defined interface with clear prop types.**

The constants and interface definition provide a solid foundation for the hook's parameters.

---

`21-59`: **Effective scroll management for search results.**

The hook properly handles scrolling behavior for selected items and resets scroll position when search input changes.

---

`60-85`: **Comprehensive keyboard event handling.**

The keyboard handling correctly manages arrow navigation, enter press, and escape key, with proper event prevention.

---

`87-97`: **Smart visibility control for the popover.**

The visibility logic correctly considers multiple factors: popover state, search value presence, and display states of search and history lists.

---

`99-113`: **Platform-specific navigation handling.**

The hook correctly implements different behaviors for desktop versus mobile platforms, with a small delay for blur actions to prevent accidental closures.

---

`114-124`: **Clean API surface with all necessary functions.**

The returned object provides a complete set of functions and state for components to consume.

</details>
<details>
<summary>packages/kit/src/views/Discovery/pages/Dashboard/Welcome/WelcomeItem.tsx (2)</summary>

`41-41`: **Increased shadow opacity for better visibility.**

Shadow opacity changed from 0.3 to 0.4, improving the visual hierarchy of the component.

---

`112-112`: **Updated shadow color to use the new theme variable.**

Changed from 'shadowColor' to 'popoverShadowColor' to maintain consistency with other components in the application.

</details>
<details>
<summary>packages/kit/src/views/Discovery/components/HeaderLeftToolBar/HeaderLeftToolBarInput.tsx (8)</summary>

`1-21`: **Well-structured imports with clear organization.**

The imports are logically grouped and include all necessary components and hooks.

---

`22-36`: **Clear props interface with TypeScript type safety.**

The interface properly defines all required and optional props with appropriate types.

---

`38-71`: **Effective state management and URL formatting.**

The component initializes state variables and uses effects to properly update the internal value when the URL changes.

---

`72-94`: **Clean integration with search popover hook.**

The component effectively uses the custom hook to manage popover state and behavior, with appropriate callback handlers.

---

`96-100`: **Keyboard shortcut integration for desktop users.**

The component registers a shortcut to focus the input field when the route is focused, enhancing keyboard navigation.

---

`102-166`: **Well-implemented input component with addon buttons.**

The input implementation includes proper event handlers, state updates, and platform-specific behavior. The bookmark and pin buttons provide clear visual feedback.

---

`167-182`: **Functional dApp info popover with proper positioning.**

The dApp info popover is correctly implemented with appropriate props passed to the content component.

---

`184-209`: **Comprehensive search results display with scroll view.**

The search popover shows results in a scrollable container with appropriate height limits and handles item selection.

</details>
<details>
<summary>packages/components/tamagui.config.ts (4)</summary>

`192-218`: **Color scheme updates look good, ensuring consistent light theme appearance.**

The light theme color updates create a solid foundation by:
- Maintaining crucial colors like `bgApp`
- Adding necessary hover states with `bgHover`
- Setting appropriate sidebar color with `bgSidebar`
- Creating proper contrast with `bgReverse`

These changes work together to ensure UI elements have appropriate visual hierarchy and interaction states.

---

`254-254`: **Good addition of shadow color for popovers.**

Adding `popoverShadowColor` improves visual depth for popover components, making them stand out properly against backgrounds.

---

`288-314`: **Dark theme color updates are well-balanced.**

The dark theme colors:
- Maintain proper contrast ratios
- Use appropriate neutral tones
- Match the light theme's structure
- Provide clear visual separation between elements

These updates ensure consistent appearance across themes while maintaining proper accessibility.

---

`350-350`: **Consistent popover shadow in dark theme.**

Using the same shadow color in both themes ensures visual consistency for popovers.

</details>
<details>
<summary>packages/kit/src/views/Discovery/pages/Dashboard/Welcome/SearchInput.tsx (6)</summary>

`28-28`: **Good addition of useSearchPopover hook.**

Importing the custom hook helps centralize state management logic.

---

`54-79`: **Nice refactoring of state management to a custom hook.**

Moving popover state and logic to a dedicated hook:
- Simplifies component complexity
- Makes the code more reusable
- Separates concerns effectively

The hook provides clear handlers with meaningful names (handleInputBlur, handleKeyDown, etc.) that reveal their purpose.

---

`89-99`: **Good separation of effects for distinct functionality.**

Separating effects for different concerns:
- First effect refreshes data when popover opens
- Second effect resets selection when popover closes

This structure makes the code easier to maintain and understand.

---

`158-158`: **Delegate keyboard handling to the hook for cleaner code.**

Using the hook's keyboard handler reduces duplication and centralizes event logic.

---

`169-169`: **Consistent event handling with hook pattern.**

Delegating blur handling to the hook maintains consistency with other event handlers.

---

`190-194`: **Improved SearchPopover props with container customization.**

Adding container props allows flexibility in sizing and styling across different viewports.
Using `isPopoverVisible` from the hook ensures state is managed consistently.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T16:25:53Z
user: login: originalix
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-25T01:44:46Z
user: login: huhuanming
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T02:27:09Z

Review comments:
diff_hunk: @@ -0,0 +1,213 @@
+import { useEffect, useRef, useState } from 'react';
+
+import { useIntl } from 'react-intl';
+
+import type { ColorTokens, IScrollViewRef, Icon } from '@onekeyhq/components';
+import { Input, Popover, ScrollView, Stack } from '@onekeyhq/components';
+import { useShortcutsOnRouteFocused } from '@onekeyhq/kit/src/hooks/useShortcutsOnRouteFocused';
+import { ETranslations } from '@onekeyhq/shared/src/locale';
+import platformEnv from '@onekeyhq/shared/src/platformEnv';
+import { EShortcutEvents } from '@onekeyhq/shared/src/shortcuts/shortcuts.enum';
+
+import { useSearchModalData } from '../../hooks/useSearchModalData';
+import { useSearchPopover } from '../../hooks/useSearchPopover';
+import { SearchPopover } from '../../pages/Dashboard/Welcome/SearchPopover';
+import { formatHiddenHttpsUrl } from '../../utils/explorerUtils';
+import { DappInfoPopoverContent } from '../DappInfoPopoverContent';
+import { SearchResultContent } from '../SearchResultContent';
+
+import type { ISearchResultContentRef } from '../SearchResultContent';
+import type { TextInput } from 'react-native';
+
+interface IHeaderLeftToolBarInputProps {
+  iconConfig: {
+    iconName: NonNullable<Parameters<typeof Icon>[0]['name']>;
+    iconColor: ColorTokens;
+  };
+  url: string;
+  isBookmark?: boolean;
+  isPinned?: boolean;
+  onBookmarkPress?: (bookmark: boolean) => void;
+  onPinnedPress?: (pinned: boolean) => void;
+  inputProps?: {
+    onPress?: () => void;
+  };
+  hostSecurity: any;
+}
+
+function HeaderLeftToolBarInput({
+  iconConfig,
+  url,
+  isBookmark,
+  isPinned,
+  onBookmarkPress,
+  onPinnedPress,
+  inputProps,
+  hostSecurity,
+}: IHeaderLeftToolBarInputProps) {
+  const intl = useIntl();
+  const [dappInfoIsOpen, setDappInfoIsOpen] = useState(false);
+  const [searchValue, setSearchValue] = useState('');
+  const [internalValue, setInternalValue] = useState('');
+  const scrollViewRef = useRef<IScrollViewRef>(null);
+  const searchResultRef = useRef<ISearchResultContentRef>(null);
+  const inputRef = useRef<TextInput>(null);
+  const { hiddenHttpsUrl } = formatHiddenHttpsUrl(url);
+
+  useEffect(() => {
+    if (hiddenHttpsUrl) {
+      setInternalValue(hiddenHttpsUrl);
+    }
+  }, [hiddenHttpsUrl]);
+
+  const {
+    localData,
+    searchList,
+    displaySearchList,
+    displayHistoryList,
+    SEARCH_ITEM_ID,
+    totalItems,
+  } = useSearchModalData(searchValue);
+
+  const {
+    selectedIndex,
+    handleKeyDown,
+    handleInputBlur,
+    isPopoverOpen,
+    setIsPopoverOpen,
+  } = useSearchPopover({
+    scrollViewRef,
+    totalItems,
+    searchValue,
+    displaySearchList,
+    displayHistoryList,
+    onEnterPress: () => {
+      if (searchResultRef.current) {
+        searchResultRef.current.openSelectedItem();
+        setIsPopoverOpen(false);
+      }
+    },
+    onEscape: () => {
+      setIsPopoverOpen(false);
+      inputRef.current?.blur();
+    },
+  });
+
+  useShortcutsOnRouteFocused(EShortcutEvents.ChangeCurrentTabUrl, () => {
+    if (platformEnv.isDesktop) {
+      inputRef.current?.focus();
+    }
+  });
+
+  return (
+    <Stack flex={1}>
+      <Input
+        ref={inputRef}
+        containerProps={{ mx: '$6', flex: 1 } as any}
+        size="small"
+        leftAddOnProps={{
+          ...iconConfig,
+          iconSize: '$4',
+          mr: '$-2',
+          onPress: () => {
+            setDappInfoIsOpen(true);
+          },
+        }}
+        pb="$1.5"
+        value={internalValue}
+        onChangeText={(text) => {
+          setInternalValue(text);
+          setSearchValue(text);
+          setIsPopoverOpen(true);
+        }}
+        onBlur={handleInputBlur}
+        selectTextOnFocus
+        testID="explore-index-search-input"
+        onFocus={() => setIsPopoverOpen(true)}
+        // @ts-expect-error
+        onKeyPress={handleKeyDown}
path: packages/kit/src/views/Discovery/components/HeaderLeftToolBar/HeaderLeftToolBarInput.tsx
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Consider using a more descriptive condition.**

The condition `!platformEnv.isDesktop` could be refactored for better readability.

```diff
-          onPress: !platformEnv.isDesktop ? () => onSearch?.(url) : undefined,
+          onPress: platformEnv.isMobile ? () => onSearch?.(url) : undefined,
```


> Committable suggestion skipped: line range outside the PR's diff.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-24T16:25:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,4 +1,4 @@
-import { useCallback, useEffect, useRef, useState } from 'react';
+import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
path: packages/kit/src/views/Discovery/pages/Dashboard/Welcome/SearchInput.tsx
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Added useMemo import but it's not used in the code.**

You've imported `useMemo` but I don't see it being used in this component.

```diff
-import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
+import { useCallback, useEffect, useRef, useState } from 'react';
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
import { useCallback, useEffect, useRef, useState } from 'react';
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-24T16:25:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -25,61 +25,81 @@
 
 import { SearchResultContent } from '../../../components/SearchResultContent';
 import { useSearchModalData } from '../../../hooks/useSearchModalData';
+import { useSearchPopover } from '../../../hooks/useSearchPopover';
 
 import { KeyboardShortcutKey } from './KeyboardShortcutKey';
 import { SearchPopover } from './SearchPopover';
 
 import type { ISearchResultContentRef } from '../../../components/SearchResultContent';
 import type { TextInput } from 'react-native';
 
-const ITEM_HEIGHT = 48; // Height of each item in the search results
-
 export function SearchInput() {
   const intl = useIntl();
   const [searchValue, setSearchValue] = useState('');
-  const [isPopoverOpen, setIsPopoverOpen] = useState(false);
-  const [selectedIndex, setSelectedIndex] = useState(-1);
   const searchResultRef = useRef<ISearchResultContentRef>(null);
   const scrollViewRef = useRef<IScrollViewRef>(null);
   const inputRef = useRef<TextInput>(null);
-
-  useEffect(() => {
-    setSelectedIndex(-1);
-  }, [isPopoverOpen]);
+  const navigation = useAppNavigation();
 
   const {
     localData,
     searchList,
     displaySearchList,
     displayHistoryList,
     SEARCH_ITEM_ID,
+    refreshLocalData,
+    totalItems,
   } = useSearchModalData(searchValue);
 
+  const {
+    handleInputBlur,
+    handleKeyDown,
+    handleSearchBarPress,
+    isPopoverOpen,
+    isPopoverVisible,
+    resetSelectedIndex,
+    selectedIndex,
+    setIsPopoverOpen,
+  } = useSearchPopover({
+    scrollViewRef,
+    totalItems,
+    searchValue,
+    onEnterPress: () => {
+      if (searchResultRef.current) {
+        searchResultRef.current.openSelectedItem();
+        setIsPopoverOpen(false);
+      }
+    },
+    onEscape: () => {
+      setIsPopoverOpen(false);
+      inputRef.current?.blur();
+    },
+    displaySearchList: Boolean(displaySearchList),
+    displayHistoryList: Boolean(displayHistoryList),
+  });
+
   useEffect(() => {
-    scrollViewRef?.current?.scrollTo({
-      y: 0,
-    });
-  }, [searchValue]);
+    if (platformEnv.isDesktop) {
+      setTimeout(() => {
+        inputRef.current?.focus();
+      }, 200);
+    }
+  }, []);
path: packages/kit/src/views/Discovery/pages/Dashboard/Welcome/SearchInput.tsx
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Add a comment explaining the timeout for desktop focus.**

The 200ms timeout for focusing the input on desktop isn't immediately clear why it's needed.

```diff
  useEffect(() => {
    if (platformEnv.isDesktop) {
      setTimeout(() => {
        inputRef.current?.focus();
+       // Delay focus to ensure DOM is fully rendered
      }, 200);
    }
  }, []);
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
  useEffect(() => {
    if (platformEnv.isDesktop) {
      setTimeout(() => {
        inputRef.current?.focus();
        // Delay focus to ensure DOM is fully rendered
      }, 200);
    }
  }, []);
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-24T16:25:52Z
author_association: CONTRIBUTOR

PR comments:
user: login: codesandbox[bot]
created_at: 2025-03-24T16:12:04Z
body: #### Review or Edit in CodeSandbox

Open the branch in <a href="https://codesandbox.io/p/github/OneKeyHQ/app-monorepo/OK-36729?mode=review&utm_source=gh_app">Web Editor</a> &bull; <a href="https://codesandbox.io/p/vscode?owner=OneKeyHQ&repo=app-monorepo&branch=OK-36729&utm_source=gh_app">VS Code</a> &bull; <a href="https://codesandbox.io/p/vscode?owner=OneKeyHQ&repo=app-monorepo&branch=OK-36729&insiders=true&utm_source=gh_app">Insiders</a><br>
Open <a href="https://codesandbox.io/p/devtool/preview/OneKeyHQ/app-monorepo/OK-36729?task=preview&port=51423&redirect=true&utm_source=gh_app">Preview</a>

<!-- open-in-codesandbox:complete -->

author_association: NONE
user: login: coderabbitai[bot]
created_at: 2025-03-24T16:12:11Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough
This pull request updates the theme color configuration and refactors the search functionality in Discovery views. It revises light/dark color values in the Tamagui config, extracts search input logic into a new component, and centralizes popover state management with a custom hook. Additionally, it adjusts styles and event conditions in browser navigation and other UI components while removing unused imports.

## Changes

| Files | Change Summary |
| --- | --- |
| `packages/components/tamagui.config.ts` | Updated light/dark colors: modified `bgReverse`, added `bgSidebar` and `popoverShadowColor`, and adjusted background/hover colors. |
| `packages/kit/src/views/Discovery/components/HeaderLeftToolBar*.tsx` | Added new `HeaderLeftToolBarInput` component and refactored `HeaderLeftToolBar` to remove inline input/popover logic. |
| `packages/kit/src/views/Discovery/{hooks/*,pages/Dashboard/Welcome/*}` | Introduced `useMemo` for `totalItems` & `isEmpty`; added new `useSearchPopover` hook; refactored `SearchInput` and `SearchPopover` for improved state, keyboard handling, and layout customization. |
| `packages/kit/src/views/{Discovery/pages/Browser/DesktopBrowserNavigationContainer.tsx,Discovery/pages/Dashboard/Welcome/KeyboardShortcutKey.tsx,AppUpdate/WhatsNew.tsx,Staking/components/TradeOrBuy.tsx}` | Updated platform condition in navigation logic; modified styling (shadow opacity, padding, minWidth); removed unused imports. |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant User
    participant SearchInput
    participant useSearchPopover
    participant SearchPopover

    User->>SearchInput: Enter text
    SearchInput->>useSearchPopover: Process input change
    useSearchPopover-->>SearchInput: Update popover state
    SearchInput->>SearchPopover: Render popover with updated state
    User->>SearchInput: Press arrow keys or Enter
    SearchInput->>useSearchPopover: Handle keyboard event
    useSearchPopover-->>SearchInput: Adjust selection
```

```mermaid
sequenceDiagram
    participant User
    participant DesktopNav
    participant platformEnv
    participant SearchHandler

    User->>DesktopNav: Trigger shortcut
    DesktopNav->>platformEnv: Check if non-desktop
    platformEnv-->>DesktopNav: Return platform flag
    alt Not Desktop
      DesktopNav->>SearchHandler: Invoke search update
    else
      DesktopNav->>SearchHandler: Skip search update
    end
```

## Assessment against linked issues

| Objective (Issue) | Addressed | Explanation |
| --- | --- | --- |
| Browser input update on closed tab deletion (OK-36729) | ❓ | Empty state recalculation is introduced, but explicit handling of tab deletion events is not evident. |
| Windows App search box styling (CTRL+T) (OK-36736) | ✅ | Styling adjustments in `KeyboardShortcutKey` address the label and background positioning issues. |
| Search box "See All History" event (OK-36749) | ❓ | No explicit modifications for triggering the "See All History" event are visible. |


<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details>
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=OneKeyHQ/app-monorepo&utm_content=6935):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` or `Summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR