Service 05

Component Library

Polished. Accessible. Keyboard-navigable. Conversation UI, agentic primitives, sidebars, dialogs — all included, all composable.


The problem

Custom components reinvent forms, dialogs, accessibility. Every time.

Every team writes their own select, dialog, dropdown, and tooltip — badly. Focus management is hard. Keyboard navigation is hard. Screen-reader semantics are hard. Most custom components fail accessibility audits and feel janky to power users.

The teams that use a real component library save the time. The teams that don't spend the year and ship something worse.


How it works

Radix UI primitives + Tailwind + composable agentic UI components.

Sage ships with Radix UI primitives for the hard parts — focus traps, ARIA roles, keyboard event handling, scroll containment. Tailwind handles styling with utility classes mapped to the brand design tokens.

On top of Radix, Sage ships agentic UI primitives: a chat thread component with streaming, a message bubble that opens its trace in Grafana on click, a composer with attachment + voice support, a tool-call card for visualizing agent actions, and a contextual AI sidebar pattern that fits every page.

  • Radix UI for focus management, ARIA, keyboard nav — the parts that are hardest to get right
  • Tailwind for styling — utility-first, design tokens from the brand system
  • Pre-built agentic primitives: ChatThread, MessageBubble, ComposerInput, ToolCallCard
  • Sidebar + contextual AI panel patterns — keyboard shortcuts, persistent state
  • Theming hooks for tenant-specific brand voice + colors (WorldviewPack-compatible)
  • Storybook + visual regression tests scaffold-installed; no design-system rot
web/components/conversation/ChatThread.tsx tsx
// web/components/conversation/ChatThread.tsx — example agentic UI primitive
import * as ScrollArea from "@radix-ui/react-scroll-area";
import { useConversation } from "@/hooks/use-conversation";
import { MessageBubble } from "./MessageBubble";
import { ComposerInput } from "./ComposerInput";

export function ChatThread({ sessionId }: { sessionId: string }) {
  const { messages, send, streaming } = useConversation(sessionId);

  return (
    <div className="flex h-full flex-col">
      <ScrollArea.Root className="flex-1 overflow-hidden">
        <ScrollArea.Viewport className="h-full w-full">
          {messages.map((m) => (
            <MessageBubble
              key={m.id}
              role={m.role}
              content={m.content}
              traceId={m.traceId}      // click to open trace in Grafana
            />
          ))}
        </ScrollArea.Viewport>
        <ScrollArea.Scrollbar orientation="vertical" />
      </ScrollArea.Root>

      <ComposerInput onSubmit={send} disabled={streaming} />
    </div>
  );
}

// All components are keyboard-navigable, screen-reader friendly,
// and use Radix primitives for focus management + ARIA semantics.

Pricing relevance

The component library is OSS and ships in every tier. The brand-voice + tenant-theming primitives (WorldviewPack integration) are in Business and Enterprise.

Open-source posture

Component library is OSS (Apache-2.0). Radix UI + Tailwind are OSS. The agentic primitives (ChatThread, ToolCallCard, etc.) are the contributed art — improvements welcome upstream.

Get Started

Stop reinventing forms and dialogs.

Radix + Tailwind + agentic UI primitives, all keyboard-navigable and screen-reader friendly. The polish that takes a year to get right — already done.