# Info Box

Bordered info panel with header, key-value rows, and tree-prefix rows

## Installation

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

```bash
npx shadcn@latest add @termcn/info-box
```

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

```tsx
/* @jsxImportSource @opentui/react */
import type { ReactNode } from "react";

import { useTheme } from "@/components/ui/theme-provider";

export interface InfoBoxProps {
  borderStyle?: "single" | "round" | "double" | "bold";
  borderColor?: string;
  padding?: [number, number];
  width?: number | "full";
  children: ReactNode;
}

export interface InfoBoxHeaderProps {
  icon?: string;
  iconColor?: string;
  label: string;
  description?: string;
  version?: string;
  versionColor?: string;
}

export interface InfoBoxRowProps {
  label: string;
  value?: string;
  valueDetail?: string;
  valueColor?: string;
  bold?: boolean;
  tree?: boolean;
  color?: string;
}

const InfoBoxRoot = ({
  borderStyle = "single",
  borderColor,
  padding = [0, 1],
  width,
  children,
}: InfoBoxProps) => {
  const theme = useTheme();
  const resolvedBorderColor = borderColor ?? theme.colors.border;

  return (
    <box
      borderColor={resolvedBorderColor}
      flexDirection="column"
      paddingLeft={padding[1]}
      paddingRight={padding[1]}
      paddingTop={padding[0]}
      paddingBottom={padding[0]}
      width={width === "full" ? undefined : width}
      flexGrow={width === "full" ? 1 : undefined}
    >
      {children}
    </box>
  );
};

const InfoBoxHeader = ({
  icon,
  iconColor = "green",
  label,
  description,
  version,
  versionColor = "cyan",
}: InfoBoxHeaderProps) => (
  <box flexDirection="row" gap={1}>
    {icon ? <text fg={iconColor}>{icon}</text> : null}
    <text>
      <b>{label}</b>
    </text>
    {description ? <text fg="#666">{description}</text> : null}
    {version ? <text fg={versionColor}>{version}</text> : null}
  </box>
);

const InfoBoxRow = ({
  label,
  value,
  valueDetail,
  valueColor,
  bold: boldValue = false,
  tree = false,
  color,
}: InfoBoxRowProps) => {
  const theme = useTheme();
  const prefix = tree ? "└ " : "";

  return (
    <box flexDirection="row">
      <text
        fg={color ?? theme.colors.mutedForeground}
      >{`${prefix}${label}${value ? ":" : ""}`}</text>
      {value ? (
        boldValue ? (
          <text fg={color}>
            <b>{`  ${value}`}</b>
          </text>
        ) : (
          <text fg={color}>{`  ${value}`}</text>
        )
      ) : null}
      {valueDetail ? (
        <text fg={valueColor ?? "cyan"}>{`  ${valueDetail}`}</text>
      ) : null}
    </box>
  );
};

const InfoBoxTreeRow = (props: Omit<InfoBoxRowProps, "tree">) => (
  <InfoBoxRow {...props} tree={true} />
);

export const InfoBox = Object.assign(InfoBoxRoot, {
  Header: InfoBoxHeader,
  Row: InfoBoxRow,
  TreeRow: InfoBoxTreeRow,
});
```

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

## Usage

```tsx
import { InfoBox } from "@/components/ui/info-box";
```

```tsx
<InfoBox borderStyle="round" width={40}>
  <InfoBox.Header icon="📦" label="my-package" version="v2.4.1" />
  <InfoBox.Row label="License" value="MIT" />
  <InfoBox.Row label="Engine" value="node" valueDetail=">=18.0.0" />
  <InfoBox.TreeRow label="Platform" value="darwin-arm64" />
</InfoBox>
```

## API Reference

### InfoBox

| Prop          | Type                                        | Default    |
| ------------- | ------------------------------------------- | ---------- |
| `borderStyle` | `"single" \| "round" \| "double" \| "bold"` | `"single"` |
| `borderColor` | `string`                                    | -          |
| `padding`     | `[number, number]`                          | `[0, 1]`   |
| `width`       | `number \| "full"`                          | -          |
| `children`    | `ReactNode`                                 | `required` |

### InfoBox.Header

| Prop           | Type     | Default    |
| -------------- | -------- | ---------- |
| `icon`         | `string` | -          |
| `iconColor`    | `string` | `"green"`  |
| `label`        | `string` | `required` |
| `description`  | `string` | -          |
| `version`      | `string` | -          |
| `versionColor` | `string` | `"cyan"`   |

### InfoBox.Row

| Prop          | Type      | Default    |
| ------------- | --------- | ---------- |
| `label`       | `string`  | `required` |
| `value`       | `string`  | -          |
| `valueDetail` | `string`  | -          |
| `valueColor`  | `string`  | -          |
| `bold`        | `boolean` | `false`    |
| `tree`        | `boolean` | `false`    |
| `color`       | `string`  | -          |

### InfoBox.TreeRow

Same props as `InfoBox.Row` except `tree` is always `true`.