Ink Web

Modal

A full-screen modal overlay with border and keyboard dismiss. Useful for overlaying chat panels, settings, or any content on top of existing UI.

Terminal

Installation

npx shadcn@latest add https://raw.githubusercontent.com/cjroth/ink-web/main/packages/ink-ui/registry/modal.json
npx shadcn@latest add https://raw.githubusercontent.com/cjroth/ink-web/main/packages/ink-ui/registry/modal.json
pnpm dlx shadcn@latest add https://raw.githubusercontent.com/cjroth/ink-web/main/packages/ink-ui/registry/modal.json
bunx shadcn@latest add https://raw.githubusercontent.com/cjroth/ink-web/main/packages/ink-ui/registry/modal.json

Usage

app/page.tsx
"use client";

import dynamic from "next/dynamic";

const Terminal = dynamic(() => import("./terminal"), {
  ssr: false,
});

export default function Home() {
  return <Terminal />;
}
app/terminal.tsx
"use client";

import { useState } from "react";
import { Box, Text } from "ink";
import { InkXterm } from "ink-web";
import { Modal } from '@/components/ui/modal'
import "ink-web/css";
import "@xterm/xterm/css/xterm.css";

export default function Terminal() {
  const [isOpen, setIsOpen] = useState(true);

  return (
    <InkXterm focus>
      {isOpen ? (
        <Modal title="Settings" onClose={() => setIsOpen(false)}>
          <Box paddingX={1}>
            <Text>Modal content goes here</Text>
          </Box>
        </Modal>
      ) : (
        <Text>Modal closed. Press any key to reopen.</Text>
      )}
    </InkXterm>
  )
}

Props

PropTypeDefaultDescription
childrenReactNode-Content to display inside the modal
titlestring-Optional title displayed at the top
borderColorstring"blue"Color of the border
borderStylestring"round"Border style (single, double, round, bold, etc.)
onClose() => void-Called when Escape key is pressed

Examples

Basic Modal

<Modal onClose={() => setOpen(false)}>
  <Box paddingX={1}>
    <Text>Hello from the modal!</Text>
  </Box>
</Modal>

With Title

<Modal title="My Modal" onClose={() => setOpen(false)}>
  <Box paddingX={1}>
    <Text>Content with a title above</Text>
  </Box>
</Modal>

Custom Border

<Modal
  title="Warning"
  borderColor="red"
  borderStyle="double"
  onClose={() => setOpen(false)}
>
  <Box paddingX={1}>
    <Text color="red">Something went wrong!</Text>
  </Box>
</Modal>

With Chat Panel

import { ChatPanel } from '@/components/ui/chat'
import { Modal } from '@/components/ui/modal'

<Modal title="AI Chat" onClose={() => setOpen(false)}>
  <ChatPanel
    messages={messages}
    onSendMessage={handleSend}
  />
</Modal>

On this page