Компоненты/Переключатель темы

Переключатель темы

1 февраля 2025

Плавный переключатель темы на React Native Svg

Установка

npx astra-rn add animated-theme-toggle
pnpm dlx astra-rn add animated-theme-toggle
yarn dlx astra-rn add animated-theme-toggle
bunx --bun astra-rn add animated-theme-toggle

Файлы

index.tsx
НазадАнимированный ввод числаДалееКнопка-плеер

Вручную

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

npm install react-native-reanimated react-native-svg
pnpm add react-native-reanimated react-native-svg
yarn add react-native-reanimated react-native-svg
bun add react-native-reanimated react-native-svg

Скопируйте эти файлы в src/shared/components/micro-interactions/animated-theme-toggle/:

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

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

import { View, Text, StyleSheet } from "react-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { StatusBar } from "expo-status-bar";
import { useFonts } from "expo-font";
import { useRef, useState } from "react";
import { AnimatedThemeToggle } from "@/shared/components/micro-interactions/animated-theme-toggle";
import { Showcase, useAutoplay, useCustomize } from "~/showcase";

const CUSTOMIZE = [
  { key: "size", label: "Размер", type: "slider", min: 32, max: 180, step: 1, unit: "px", default: 98 },
  { key: "color", label: "Цвет", type: "color", default: "#ffffff" },
  { key: "strokeWidth", label: "Толщина линии", type: "slider", min: 0.5, max: 4, step: 0.1, default: 1.3 },
  { key: "duration", label: "Длительность", type: "slider", min: 200, max: 2000, step: 50, unit: "ms", default: 700 },
  { key: "background", label: "Фон", type: "color", default: "#0a0a0a" },
  { key: "hold", label: "Пауза автопоказа", type: "slider", min: 400, max: 4000, step: 100, unit: "ms", default: 1300 },
] as const;

export default function App() {
  const [fontLoaded] = useFonts({
    SfProRounded: require("@/assets/fonts/sf-pro-rounded.ttf"),
  });

  const [isDark, setIsDark] = useState(false);
  const custom = useCustomize(CUSTOMIZE);
  const holdRef = useRef<number>(custom.hold);
  holdRef.current = custom.hold;

  useAutoplay(async ({ wait }) => {
    await wait(600);
    setIsDark(true);
    await wait(holdRef.current);
    setIsDark(false);
    await wait(700);
  });

  return (
    <Showcase>
      <View style={[styles.container, { backgroundColor: custom.background }]}>
        <View style={styles.row}>
          <AnimatedThemeToggle
            isDark={isDark}
            onToggle={() => setIsDark(!isDark)}
            size={custom.size}
            duration={custom.duration}
            color={custom.color}
            strokeWidth={custom.strokeWidth}
          />
        </View>
      </View>
    </Showcase>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#0a0a0a",
    alignItems: "center",
    justifyContent: "center",
  },
  row: {},
  label: {
    fontSize: 16,
    color: "#fff",
    width: 40,
  },
});

Пропсы

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

Тип boolean

onToggle

Тип () => void

size?

Тип number

duration?

Тип number

color?

Тип string

strokeWidth?

Тип number

style?

Тип StyleProp<ViewStyle>