Компоненты/Тягучий поиск

Тягучий поиск

21 августа 2026

Панель вкладок перетекает в поле поиска тягучим переходом

Установка

npx astra-rn add gooey-search-tabs
pnpm dlx astra-rn add gooey-search-tabs
yarn dlx astra-rn add gooey-search-tabs
bunx --bun astra-rn add gooey-search-tabs

Файлы

index.tsx
НазадТягучий поповерДалееГрадиентный аватар

Вручную

Поставьте зависимости:

npm install @expo/vector-icons @shopify/react-native-skia react-native-reanimated
pnpm add @expo/vector-icons @shopify/react-native-skia react-native-reanimated
yarn add @expo/vector-icons @shopify/react-native-skia react-native-reanimated
bun add @expo/vector-icons @shopify/react-native-skia react-native-reanimated

Скопируйте эти файлы в src/shared/components/molecules/gooey-search-tabs/:

Проверьте алиас путей. Импорты в коде выше записаны так, как их пишет astra-rn add: @/shared/components, @/shared/utils и @/shared/hooks. Нужен алиас "@/*": ["./src/*"] в tsconfig.json — или поправьте импорты под свои пути.

Использование

import React from "react";
import { StyleSheet, View } from "react-native";
import { Feather } from "@expo/vector-icons";
import { useFonts } from "expo-font";
import { GooeySearchTabs } from "@/shared/components/molecules/gooey-search-tabs";
import { useGooey } from "@/shared/components/molecules/gooey-search-tabs/context";
import { Showcase, useAutoplay, useCustomize } from "~/showcase";

const _TRIGGER_ICON_SIZE: number = 20;
const _ICON_SIZE: number = _TRIGGER_ICON_SIZE * 0.7_5;

const CUSTOMIZE = [
  { key: "intensity", label: "Вязкость", type: "slider", min: 0, max: 1, step: 0.05, default: 0.2 },
  { key: "damping", label: "Затухание", type: "slider", min: 4, max: 40, step: 1, default: 12 },
  { key: "stiffness", label: "Жёсткость", type: "slider", min: 40, max: 400, step: 5, default: 150 },
  { key: "mass", label: "Масса", type: "slider", min: 0.1, max: 3, step: 0.1, default: 0.5 },
  { key: "bg", label: "Фон", type: "color", default: "#1e1e1e" },
  { key: "fg", label: "Текст и иконки", type: "color", default: "#f5f5f7" },
  { key: "muted", label: "Неактивный", type: "color", default: "#8a8a90" },
  { key: "docsLabel", label: "Вкладка 1", type: "text", default: "Docs", maxLength: 16 },
  { key: "mediaLabel", label: "Вкладка 2", type: "text", default: "Media", maxLength: 16 },
] as const;

function SearchTabsAutoplay(): null {
  const { selectTab, expand, collapse } = useGooey();

  useAutoplay(async ({ wait }) => {
    await wait(200);
    selectTab("media");
    await wait(650);
    selectTab("docs");
    await wait(550);
    expand();
    await wait(850);
    collapse();
    await wait(450);
  });

  return null;
}

export default function GooeySearchTabsScreen() {
  const [iconsLoaded] = useFonts(Feather.font);
  const custom = useCustomize(CUSTOMIZE);
  if (!iconsLoaded) return null;
  return (
    <Showcase>
      <View
        style={[
          styles.stage,
          {
            justifyContent: "center",
            alignItems: "center",
            flex: 1,
          },
        ]}
      >
        <GooeySearchTabs
          intensity={custom.intensity}
          springConfig={{
            damping: custom.damping,
            stiffness: custom.stiffness,
            mass: custom.mass,
          }}
          colorScheme={{
            bg: custom.bg,
            fg: custom.fg,
            muted: custom.muted,
            indicator: "rgba(255,255,255,0.10)",
          }}
        >
          <GooeySearchTabs.Trigger>
            <Feather
              name="search"
              size={_TRIGGER_ICON_SIZE}
              color={custom.fg}
            />
          </GooeySearchTabs.Trigger>

          <GooeySearchTabs.Tabs>
            <GooeySearchTabs.Tab value="docs">
              <GooeySearchTabs.TabIcon>
                <Feather name="file-text" size={_ICON_SIZE} color={custom.fg} />
              </GooeySearchTabs.TabIcon>
              <GooeySearchTabs.TabLabel>{custom.docsLabel}</GooeySearchTabs.TabLabel>
            </GooeySearchTabs.Tab>

            <GooeySearchTabs.Tab value="media">
              <GooeySearchTabs.TabIcon>
                <Feather name="image" size={_ICON_SIZE} color={custom.fg} />
              </GooeySearchTabs.TabIcon>
              <GooeySearchTabs.TabLabel>{custom.mediaLabel}</GooeySearchTabs.TabLabel>
            </GooeySearchTabs.Tab>
          </GooeySearchTabs.Tabs>

          <SearchTabsAutoplay />
        </GooeySearchTabs>
      </View>
    </Showcase>
  );
}

const styles = StyleSheet.create({
  stage: {
    alignItems: "center",
    justifyContent: "center",
  },
});

Пропсы

Пропс
Описание
children

Тип ReactNode

value?

Тип string

defaultValue?

Тип string

onChange?

Тип (value: string) => void

onSearch?

Тип (value: string) => void

activeTab?

Тип string

defaultActiveTab?

Тип string

onTabChange?

Тип (value: string) => void

defaultExpanded?

Тип boolean

onExpandedChange?

Тип (expanded: boolean) => void

placeholder?

Тип string

intensity?

Тип number

springConfig?

Тип WithSpringConfig

colorScheme?

Тип Partial<IColorScheme>

style?

Тип StyleProp<ViewStyle>

textStyle?

Тип StyleProp<TextStyle>