Ink Web

Tab Bar

A horizontal tab bar with inverse highlight on the selected option. Supports labels, focus states, and custom active colors.

Terminal

Installation

npx shadcn@latest add https://raw.githubusercontent.com/cjroth/ink-web/main/packages/ink-ui/registry/tab-bar.json
npx shadcn@latest add https://raw.githubusercontent.com/cjroth/ink-web/main/packages/ink-ui/registry/tab-bar.json
pnpm dlx shadcn@latest add https://raw.githubusercontent.com/cjroth/ink-web/main/packages/ink-ui/registry/tab-bar.json
bunx shadcn@latest add https://raw.githubusercontent.com/cjroth/ink-web/main/packages/ink-ui/registry/tab-bar.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, useInput } from "ink";
import { InkXterm } from "ink-web";
import { TabBar } from '@/components/ui/tab-bar'
import "ink-web/css";
import "@xterm/xterm/css/xterm.css";

const tabs = ["Home", "Settings", "Help"];

export default function Terminal() {
  const [selectedIndex, setSelectedIndex] = useState(0);

  useInput((_input, key) => {
    if (key.leftArrow) {
      setSelectedIndex((i) => (i > 0 ? i - 1 : tabs.length - 1));
    }
    if (key.rightArrow) {
      setSelectedIndex((i) => (i < tabs.length - 1 ? i + 1 : 0));
    }
  });

  return (
    <InkXterm focus>
      <Box flexDirection="column">
        <TabBar options={tabs} selectedIndex={selectedIndex} />
      </Box>
    </InkXterm>
  )
}

Props

PropTypeDefaultDescription
optionsstring[]Array of tab labels to display
selectedIndexnumberIndex of the currently selected tab
labelstringOptional label displayed before the tabs
focusedbooleantrueWhether the tab bar is focused (affects styling)
activeColorstring'cyan'Color of the selected tab when focused

Examples

Basic Tab Bar

<TabBar options={["Home", "Settings", "Help"]} selectedIndex={0} />

With Label

<TabBar label="View" options={["Files", "Search", "Git"]} selectedIndex={1} />

Custom Active Color

<TabBar
  options={["Tab 1", "Tab 2", "Tab 3"]}
  selectedIndex={0}
  activeColor="magenta"
/>

Unfocused State

<TabBar
  options={["Tab 1", "Tab 2", "Tab 3"]}
  selectedIndex={0}
  focused={false}
/>

Keyboard Navigation

The TabBar component is a display-only component. You need to handle keyboard input yourself using Ink's useInput hook:

const [selectedIndex, setSelectedIndex] = useState(0);

useInput((_input, key) => {
  if (key.leftArrow) {
    setSelectedIndex((i) => (i > 0 ? i - 1 : options.length - 1));
  }
  if (key.rightArrow) {
    setSelectedIndex((i) => (i < options.length - 1 ? i + 1 : 0));
  }
});

<TabBar options={options} selectedIndex={selectedIndex} />

On this page