# Conversation History

Arrow-key scrollable stack for long chat threads

## Installation

  <TabsTrigger value="cli">Command</TabsTrigger>
  <TabsTrigger value="manual">Manual</TabsTrigger>

```bash
npx shadcn@latest add @termcn/conversation-history
```

<Step>Copy and paste the following code into your project.</Step>

```tsx
import { Box, Text } from "ink";
import React, { useState } from "react";
import type { ReactNode } from "react";

import { useTheme } from "@/components/ui/theme-provider";
import { useInput } from "@/hooks/use-input";

export interface ConversationHistoryProps {
  maxHeight?: number;
  children?: ReactNode;
  showScrollHint?: boolean;
  isActive?: boolean;
}

export function ConversationHistory({
  maxHeight = 20,
  children,
  showScrollHint = true,
  isActive = true,
}: ConversationHistoryProps) {
  const theme = useTheme();
  const childArray = React.Children.toArray(children);
  const totalChildren = childArray.length;

  const maxOffset = Math.max(0, totalChildren - maxHeight);
  const [scrollOffset, setScrollOffset] = useState(maxOffset);

  useInput(
    (_input, key) => {
      if (key.upArrow) {
        setScrollOffset((o) => Math.max(0, o - 1));
      } else if (key.downArrow) {
        setScrollOffset((o) =>
          Math.min(Math.max(0, totalChildren - maxHeight), o + 1)
        );
      }
    },
    { isActive }
  );

  const visibleChildren = childArray.slice(
    scrollOffset,
    scrollOffset + maxHeight
  );

  return (
    <Box flexDirection="column">
      <Box flexDirection="column" overflow="hidden" height={maxHeight}>
        {visibleChildren}
      </Box>
      {showScrollHint && isActive && (
        <Text dimColor color={theme.colors.mutedForeground}>
          ↑↓ scroll
        </Text>
      )}
    </Box>
  );
}
```

<Step>Update the import paths to match your project setup.</Step>

## Usage

```tsx
import { ConversationHistory } from "@/components/ui/conversation-history";
import { Text } from "ink";
```

```tsx
<ConversationHistory maxHeight={12} isActive>
  <Text>user: Hello</Text>
  <Text>assistant: Hi — how can I help?</Text>
</ConversationHistory>
```

When `isActive` is true, **↑** / **↓** move the window over `children`. The view starts scrolled to the bottom (`maxHeight` lines visible).

## API Reference

### ConversationHistory

| Prop             | Type        | Default |
| ---------------- | ----------- | ------- |
| `maxHeight`      | `number`    | `20`    |
| `children`       | `ReactNode` | -       |
| `showScrollHint` | `boolean`   | `true`  |
| `isActive`       | `boolean`   | `true`  |