Skip to content

UI Components Reference

All components are imported from tango-api. They use CSS classes prefixed with tui- and inherit the Tango theme automatically when wrapped in UIRoot.

import { UIRoot, UIPanelHeader, UISection, UICard, UIButton, UIIconButton, UIIcon, Icon } from "tango-api";

For non-React/DOM usage, use the DOM surface from tango-api/dom:

import { UIDOM, Icon } from "tango-api/dom";
UIDOM.ensureStyles(document);
const commitBtn = UIDOM.UIButton({ label: "Commit", variant: "primary", size: "sm" });
const filesBtn = UIDOM.UIIconButton({ icon: Icon.Post, label: "Toggle files changed" });

Required wrapper for every panel. Injects the Tango UI stylesheet.

props: {
className?: string;
children?: React.ReactNode;
}

Standard panel header with title, optional subtitle, back button, and right-side actions.

props: {
title: string;
subtitle?: string;
onBack?: () => void;
rightActions?: React.ReactNode;
}

When onBack is provided, a back arrow button appears to the left of the title.


Groups related content with optional title and description.

props: {
title?: string;
description?: string;
children?: React.ReactNode;
}

Bordered container for content blocks.

props: {
className?: string;
children?: React.ReactNode;
}

Action trigger button.

props: {
label: string;
icon?: UIIconName | React.ReactNode; // optional left icon
variant?: "primary" | "secondary" | "danger" | "ghost"; // default: "secondary"
size?: "sm" | "md"; // default: "md"
disabled?: boolean;
onClick?: () => void;
}
VariantUse case
primaryMain action (submit, save, create)
secondarySecondary actions
dangerDestructive actions (delete, remove)
ghostSubtle actions (inline, toolbar)

Using Tango icons:

<UIButton label="Run task" variant="primary" icon={Icon.Play} />
<UIButton label="Create branch" variant="secondary" icon={Icon.Branch} />

Icon-only button for toolbars and compact actions.

props: {
icon: UIIconName | React.ReactNode;
label: string; // required (aria-label)
title?: string; // tooltip/title, defaults to label
variant?: "ghost" | "secondary"; // default: "ghost"
size?: "sm" | "md"; // default: "sm"
active?: boolean;
disabled?: boolean;
onClick?: () => void;
}
<UIIconButton icon={Icon.Branch} label="Toggle branch panel" />
<UIIconButton icon={Icon.Post} label="Open files panel" active />

Tango-standard icon set for consistent visuals across instruments.

UIIcon props: {
name: UIIconName;
className?: string;
size?: number; // default: 16
title?: string; // accessibility label
}

Icon provides named constants (initial set):

  • Icon.Branch
  • Icon.Play
  • Icon.Post
  • Icon.AI
  • Icon.Check
  • Icon.Pause
<UIIcon name={Icon.AI} />

Single-line text input. The onInput callback receives the string value directly.

props: {
value?: string;
placeholder?: string;
onInput?: (value: string) => void;
}

Multi-line text input.

props: {
value?: string;
placeholder?: string;
rows?: number; // default: 6
onInput?: (value: string) => void;
}

Dropdown selection.

props: {
options: Array<{ value: string; label: string }>;
value?: string;
onChange?: (value: string) => void;
}

Custom Tango-style dropdown with trigger + menu options.

props: {
options: Array<{ value: string; label: string }>;
value?: string;
initialValue?: string;
placeholder?: string;
disabled?: boolean;
onChange?: (value: string) => void;
}

UIDropdown supports uncontrolled (initialValue) and controlled (value) usage.


On/off switch with label.

props: {
label: string;
checked?: boolean;
onChange?: (checked: boolean) => void;
}

Checkbox with label.

props: {
label: string;
checked?: boolean;
onChange?: (checked: boolean) => void;
}

Radio button group.

props: {
name: string;
options: Array<{ value: string; label: string }>;
value?: string;
onChange?: (value: string) => void;
}

Segmented button strip.

props: {
options: Array<{ value: string; label: string }>;
value?: string;
onChange?: (value: string) => void;
}

Tab navigation with content panels.

props: {
tabs: Array<{
value: string;
label: string;
content: React.ReactNode;
}>;
value?: string;
initialValue?: string;
onChange?: (value: string) => void;
}

UITabs supports uncontrolled and controlled usage:

  • Uncontrolled: pass initialValue (or omit it to select the first tab).
  • Controlled: pass value and update it in your parent state from onChange.

Colored label for status or metadata.

props: {
label: string;
tone?: "neutral" | "info" | "success" | "warning" | "danger"; // default: "neutral"
}

Placeholder for empty views.

props: {
title: string;
description?: string;
action?: React.ReactNode;
}

Container for UIListItem components.

props: {
children?: React.ReactNode;
}

Clickable list item with title, subtitle, and active state.

props: {
title: string;
subtitle?: string;
active?: boolean;
onClick?: () => void;
}

Renders as a <button> when onClick is provided, otherwise a <div>.


List with single or multi-select support.

props: {
items: Array<{ value: string; title: string; subtitle?: string }>;
selected: string[];
multiple?: boolean;
onChange?: (next: string[]) => void;
}

Collapsible section with header, metadata, and actions.

props: {
title: React.ReactNode;
subtitle?: React.ReactNode;
expanded?: boolean; // default: true
active?: boolean;
animate?: boolean;
meta?: React.ReactNode;
actions?: React.ReactNode;
onToggle?: (nextExpanded: boolean) => void;
children?: React.ReactNode;
}

When onToggle is provided, the header becomes clickable and shows a caret icon. The group body collapses/expands based on the expanded prop.


Container for UIGroupItem components inside a UIGroup.

props: {
children?: React.ReactNode;
}

Item inside a UIGroupList. Supports title, subtitle, metadata, active state, and click.

props: {
title: string;
subtitle?: string;
meta?: React.ReactNode;
active?: boolean;
onClick?: () => void;
}

Renders as a <button> when onClick is provided, otherwise a <div>.


Placeholder text for an empty group.

props: {
text: string;
}

Alias for UIBadge. Displays a colored token.

props: {
label: string;
tone?: "neutral" | "info" | "success" | "warning" | "danger";
}

Alias for UIBadge. Displays a status indicator.

props: {
label: string;
tone?: "neutral" | "info" | "success" | "warning" | "danger";
}

The UI kit provides utility classes you can use directly:

ClassDescription
tui-rootRoot container (applied by UIRoot)
tui-rowHorizontal flex row with gap
tui-colVertical flex column with gap
tui-spreadSpace-between flex row