Поставьте зависимости:
npm install expo-haptics react-native-reanimatedpnpm add expo-haptics react-native-reanimatedyarn add expo-haptics react-native-reanimatedbun add expo-haptics react-native-reanimatedСкопируйте эти файлы в src/shared/components/molecules/animated-chip/:
Он импортирует ещё один модуль — astra-rn add кладёт их рядом сам, вручную скопируйте и их:
Проверьте алиас путей. Импорты в коде выше записаны так, как их пишет astra-rn add: @/shared/components, @/shared/utils и @/shared/hooks. Нужен алиас "@/*": ["./src/*"] в tsconfig.json — или поправьте импорты под свои пути.
import { StatusBar } from "expo-status-bar";
import { SymbolView, type SymbolViewProps } from "expo-symbols";
import { useMemo, useState } from "react";
import { StyleSheet, View } from "react-native";
import { AnimatedChip } from "@/shared/components/molecules/animated-chip";
import { Showcase, useAutoplay, useCustomize } from "~/showcase";
const FILTERS: {
value: string;
label: string;
icon: SymbolViewProps["name"];
color: string;
tint: string;
}[] = [
{
value: "all",
label: "All",
icon: "square.grid.2x2.fill",
color: "#ffffff",
tint: "#000000",
},
{
value: "music",
label: "Music",
icon: "music.note",
color: "#ff375f",
tint: "#ffffff",
},
{
value: "videos",
label: "Videos",
icon: "play.fill",
color: "#5e5ce6",
tint: "#ffffff",
},
];
const CUSTOMIZE = [
{ key: "label1", label: "Подпись 1", type: "text", default: "All", maxLength: 14 },
{ key: "label2", label: "Подпись 2", type: "text", default: "Music", maxLength: 14 },
{ key: "label3", label: "Подпись 3", type: "text", default: "Videos", maxLength: 14 },
{ key: "color1", label: "Цвет 1", type: "color", default: "#ffffff" },
{ key: "color2", label: "Цвет 2", type: "color", default: "#ff375f" },
{ key: "color3", label: "Цвет 3", type: "color", default: "#5e5ce6" },
{ key: "inactive", label: "Фон неактивных", type: "color", default: "#1a1a1a" },
{ key: "iconTint", label: "Иконки неактивных", type: "color", default: "#5c5c60" },
{ key: "gap", label: "Зазор", type: "slider", min: 0, max: 24, step: 1, unit: "px", default: 8 },
{ key: "damping", label: "Затухание", type: "slider", min: 5, max: 40, step: 1, default: 13 },
{ key: "stiffness", label: "Жёсткость", type: "slider", min: 50, max: 500, step: 10, default: 180 },
] as const;
export default function App() {
const [filter, setFilter] = useState<string | number>("all");
const custom = useCustomize(CUSTOMIZE);
const labels = [custom.label1, custom.label2, custom.label3];
const colors = [custom.color1, custom.color2, custom.color3];
const { damping, stiffness } = custom;
const springConfig = useMemo(
() => ({ damping, stiffness, mass: 0.5, overshootClamping: false }),
[damping, stiffness],
);
useAutoplay(async ({ wait }) => {
setFilter("all");
await wait(1000);
setFilter("music");
await wait(900);
setFilter("videos");
await wait(1300);
setFilter("music");
await wait(900);
setFilter("all");
await wait(1000);
});
return (
<Showcase>
<View style={styles.container}>
<StatusBar style="light" />
<AnimatedChip.Group
value={filter}
onValueChange={setFilter}
gap={custom.gap}
springConfig={springConfig}
>
{FILTERS.map(({ value, icon, tint }, index) => (
<AnimatedChip.Item
key={value}
value={value}
activeColor={colors[index]}
inactiveColor={custom.inactive}
>
<AnimatedChip.Icon>
{({ selected }) => (
<SymbolView
name={icon}
size={18}
tintColor={selected ? tint : custom.iconTint}
resizeMode="scaleAspectFit"
/>
)}
</AnimatedChip.Icon>
<AnimatedChip.Label color={tint}>{labels[index]}</AnimatedChip.Label>
</AnimatedChip.Item>
))}
</AnimatedChip.Group>
</View>
</Showcase>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
backgroundColor: "#0a0a0a",
},
});childrenТип ReactNode
value?Selected value — pass with `onValueChange` to control the group.
Тип TChipValue
defaultValue?Selected value on first render when the group is uncontrolled.
Тип TChipValue
onValueChange?Тип (value: TChipValue) => void
gap?Space between chips.
Тип number
springConfig?Spring driving every chip's expansion.
Тип WithSpringConfig
haptics?Fire a light haptic tap on selection. Native only.
Тип boolean
reserveWidth?Hold the row at the width of its widest arrangement so the group never resizes as the selection moves. Turn off for a row that should shrink to whatever is currently selected.
Тип boolean
style?Тип StyleProp<ViewStyle>