{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "segmented-control",
  "title": "Segmented control",
  "description": "2–4 options, animated thumb",
  "dependencies": [],
  "registryDependencies": [
    "@kit-native/lib-haptics",
    "@kit-native/lib-reduced-motion",
    "@kit-native/lib-theme",
    "@kit-native/lib-utils",
    "@kit-native/text"
  ],
  "files": [
    {
      "path": "components/kit/segmented-control.tsx",
      "content": "import { Text } from '@/components/ui/text';\nimport { haptic } from '@/lib/haptics';\nimport { TOKENS } from '@/lib/theme';\nimport { cn } from '@/lib/utils';\nimport { useMotion } from '@/lib/reduced-motion';\nimport * as React from 'react';\nimport { Animated, Easing, type LayoutChangeEvent, Pressable, View } from 'react-native';\n\ntype Props<T extends string> = {\n  segments: readonly { value: T; label: string }[];\n  value: T;\n  onChange: (value: T) => void;\n  className?: string;\n};\n\nconst INSET = 3;\n\n/** iOS-style sliding segmented control for 2–4 mutually exclusive options. */\nexport function SegmentedControl<T extends string>({ segments, value, onChange, className }: Props<T>) {\n  const [trackW, setTrackW] = React.useState(0);\n  const activeIndex = Math.max(\n    0,\n    segments.findIndex((s) => s.value === value)\n  );\n  const [anim] = React.useState(() => new Animated.Value(activeIndex));\n  const segW = trackW > 0 ? (trackW - INSET * 2) / segments.length : 0;\n  const motion = useMotion();\n\n  React.useEffect(() => {\n    Animated.timing(anim, {\n      toValue: activeIndex,\n      duration: motion(TOKENS.duration.base),\n      easing: Easing.out(Easing.cubic),\n      useNativeDriver: true,\n    }).start();\n  }, [activeIndex, anim, motion]);\n\n  const onLayout = (e: LayoutChangeEvent) => setTrackW(e.nativeEvent.layout.width);\n\n  return (\n    <View onLayout={onLayout} className={cn('bg-muted flex-row rounded-lg', className)} style={{ padding: INSET }}>\n      {segW > 0 ? (\n        <Animated.View\n          pointerEvents=\"none\"\n          style={{\n            position: 'absolute',\n            top: INSET,\n            bottom: INSET,\n            left: INSET,\n            width: segW,\n            transform: [{ translateX: anim.interpolate({ inputRange: [0, 1], outputRange: [0, segW] }) }],\n          }}>\n          {/* The surface lives on a plain View: NativeWind drops classNames on\n              Animated.View on web, which left the thumb invisible in the preview. */}\n          <View className=\"bg-card h-full w-full rounded-md shadow-sm shadow-black/10\" />\n        </Animated.View>\n      ) : null}\n      {segments.map((seg) => {\n        const active = seg.value === value;\n        return (\n          <Pressable\n            key={seg.value}\n            accessibilityRole=\"button\"\n            accessibilityState={{ selected: active }}\n            // aria-pressed is web-only (react-native-web drops accessibilityState, and a button may not carry aria-selected).\n            aria-pressed={active}\n            onPress={() => {\n              if (active) return;\n              haptic('selection');\n              onChange(seg.value);\n            }}\n            className=\"h-9 flex-1 items-center justify-center\">\n            <Text numberOfLines={1} className={cn('text-sm', active ? 'font-semibold' : 'text-muted-foreground')}>\n              {seg.label}\n            </Text>\n          </Pressable>\n        );\n      })}\n    </View>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/kit/segmented-control.tsx"
    }
  ],
  "meta": {
    "exports": [
      "SegmentedControl"
    ],
    "api": "<SegmentedControl segments={[{value,label}]} value onChange />"
  },
  "docs": "Run `npx expo install --fix` afterwards so Expo SDK packages match your SDK. Needs the kit theme (`@kit-native/theme`) and `KitThemeProvider` from `@kit-native/lib-theme-context` at the root.",
  "categories": [
    "inputs"
  ],
  "type": "registry:component"
}