{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "chat-thread-list",
  "title": "Chat thread list",
  "description": "past conversations, grouped by when · `threads activeId onSelect onNew?`",
  "dependencies": [
    "lucide-react-native@^1.21.0"
  ],
  "registryDependencies": [
    "@kit-native/button",
    "@kit-native/icon",
    "@kit-native/lib-utils",
    "@kit-native/text"
  ],
  "files": [
    {
      "path": "components/kit/chat-thread-list.tsx",
      "content": "import { Button } from '@/components/ui/button';\nimport { Icon } from '@/components/ui/icon';\nimport { Text } from '@/components/ui/text';\nimport { cn } from '@/lib/utils';\nimport { PlusIcon } from 'lucide-react-native';\nimport { Pressable, View } from 'react-native';\n\nexport type ChatThread = {\n  id: string;\n  title: string;\n  /** The last line of the conversation, one line. */\n  preview?: string;\n  /** A heading the thread sits under: \"Today\", \"Previous 7 days\". Threads in a group must be adjacent. */\n  group?: string;\n};\n\ntype Props = {\n  threads: ChatThread[];\n  activeId?: string;\n  onSelect: (id: string) => void;\n  /** Shows a \"New chat\" button above the list. */\n  onNew?: () => void;\n  className?: string;\n};\n\n/**\n * Past conversations in an AI product: a screen of its own on phones, or the content of a Sheet. Newest\n * first, grouped by when. The open conversation is marked selected.\n */\nexport function ChatThreadList({ threads, activeId, onSelect, onNew, className }: Props) {\n  const groups: { label?: string; threads: ChatThread[] }[] = [];\n  for (const t of threads) {\n    const last = groups.at(-1);\n    if (last && last.label === t.group) last.threads.push(t);\n    else groups.push({ label: t.group, threads: [t] });\n  }\n\n  return (\n    <View role=\"navigation\" aria-label=\"Conversations\" className={cn('gap-4', className)}>\n      {onNew ? (\n        <Button variant=\"outline\" className=\"justify-start\" onPress={onNew}>\n          <Icon as={PlusIcon} size={16} />\n          <Text>New chat</Text>\n        </Button>\n      ) : null}\n      {threads.length === 0 ? <Text className=\"text-muted-foreground px-3 text-sm\">No conversations yet.</Text> : null}\n      {groups.map((g, i) => (\n        <View key={`${g.label ?? ''}-${i}`} className=\"gap-1\">\n          {g.label ? (\n            <Text role=\"heading\" className=\"text-muted-foreground px-3 pb-1 text-xs font-medium\">\n              {g.label}\n            </Text>\n          ) : null}\n          {g.threads.map((t) => {\n            const active = t.id === activeId;\n            return (\n              <Pressable\n                key={t.id}\n                onPress={() => onSelect(t.id)}\n                accessibilityRole=\"button\"\n                accessibilityState={{ selected: active }}\n                aria-current={active ? 'page' : undefined}\n                className={cn('min-h-11 justify-center gap-0.5 rounded-lg px-3 py-2', active ? 'bg-accent' : 'active:bg-accent/60')}>\n                <Text numberOfLines={1} className={cn('text-sm font-medium', active && 'text-accent-foreground')}>\n                  {t.title}\n                </Text>\n                {t.preview ? (\n                  <Text numberOfLines={1} className=\"text-muted-foreground text-xs\">\n                    {t.preview}\n                  </Text>\n                ) : null}\n              </Pressable>\n            );\n          })}\n        </View>\n      ))}\n    </View>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/kit/chat-thread-list.tsx"
    }
  ],
  "meta": {
    "exports": [
      "ChatThreadList"
    ],
    "api": "<ChatThreadList threads={[{id,title,preview?,group?}]} activeId onSelect onNew? />"
  },
  "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": [
    "ai"
  ],
  "type": "registry:component"
}