Skip to main content
The @packages/ui package provides a comprehensive collection of reusable React components for Answer Overflow, built with Radix UI primitives and styled with Tailwind CSS.

Installation

npm install @packages/ui

Overview

This package includes:
  • 50+ UI components (buttons, dialogs, forms, etc.)
  • AI-specific components for chat interfaces
  • Discord components for rendering Discord content
  • Radix UI primitives for accessibility
  • Tailwind CSS for styling
  • Dark mode support with next-themes
  • Analytics integration with PostHog

Core Components

Button

import { Button } from "@packages/ui/components/button";

function MyComponent() {
  return (
    <>
      <Button variant="default">Default</Button>
      <Button variant="destructive">Delete</Button>
      <Button variant="outline">Outline</Button>
      <Button variant="ghost">Ghost</Button>
      <Button variant="link">Link</Button>
      <Button size="sm">Small</Button>
      <Button size="lg">Large</Button>
      <Button disabled>Disabled</Button>
    </>
  );
}
variant
enum
Button style variant
  • default - Primary button
  • destructive - Dangerous actions
  • outline - Secondary button
  • ghost - Minimal button
  • link - Link-style button
size
enum
Button size
  • sm - Small
  • default - Medium
  • lg - Large
  • icon - Icon-only

Dialog

import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@packages/ui/components/dialog";

function MyDialog() {
  return (
    <Dialog>
      <DialogTrigger asChild>
        <Button>Open Dialog</Button>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Dialog Title</DialogTitle>
          <DialogDescription>
            Dialog description goes here.
          </DialogDescription>
        </DialogHeader>
        <div>Dialog content</div>
      </DialogContent>
    </Dialog>
  );
}

Card

import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@packages/ui/components/card";

function MyCard() {
  return (
    <Card>
      <CardHeader>
        <CardTitle>Card Title</CardTitle>
        <CardDescription>Card description</CardDescription>
      </CardHeader>
      <CardContent>
        <p>Card content goes here</p>
      </CardContent>
      <CardFooter>
        <Button>Action</Button>
      </CardFooter>
    </Card>
  );
}

Input & Form

import { Input } from "@packages/ui/components/input";
import { Label } from "@packages/ui/components/label";
import { useForm } from "react-hook-form";

function MyForm() {
  const { register, handleSubmit } = useForm();
  
  return (
    <form onSubmit={handleSubmit((data) => console.log(data))}>
      <div>
        <Label htmlFor="email">Email</Label>
        <Input
          id="email"
          type="email"
          placeholder="you@example.com"
          {...register("email")}
        />
      </div>
      <Button type="submit">Submit</Button>
    </form>
  );
}

Select

import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@packages/ui/components/select";

function MySelect() {
  return (
    <Select>
      <SelectTrigger>
        <SelectValue placeholder="Select an option" />
      </SelectTrigger>
      <SelectContent>
        <SelectItem value="option1">Option 1</SelectItem>
        <SelectItem value="option2">Option 2</SelectItem>
        <SelectItem value="option3">Option 3</SelectItem>
      </SelectContent>
    </Select>
  );
}

AI Components

Specialized components for AI chat interfaces:

AI Chat Message

import { AIChatMessage } from "@packages/ui/components/ai-elements/chat-message";

function ChatInterface() {
  return (
    <div>
      <AIChatMessage
        role="user"
        content="Hello, how can you help me?"
      />
      <AIChatMessage
        role="assistant"
        content="I can help you with various tasks!"
        streaming={false}
      />
    </div>
  );
}
role
enum
required
Message role: user, assistant, or system
content
string
required
Message content (supports markdown)
streaming
boolean
Whether the message is currently being streamed

AI Typing Indicator

import { TypingIndicator } from "@packages/ui/components/ai-elements/typing-indicator";

function Chat() {
  const [isTyping, setIsTyping] = useState(true);
  
  return (
    <div>
      {messages.map(msg => <AIChatMessage {...msg} />)}
      {isTyping && <TypingIndicator />}
    </div>
  );
}

Discord Components

Discord Message

import { DiscordMessage } from "@packages/ui/components/discord-message";

function Messages() {
  return (
    <DiscordMessage
      author={{
        username: "User123",
        avatar: "https://cdn.discordapp.com/...",
      }}
      content="Hello from Discord!"
      timestamp={new Date()}
      embeds={[]}
    />
  );
}

Discord Embed

import { DiscordEmbed } from "@packages/ui/components/discord-embed";

function MyEmbed() {
  return (
    <DiscordEmbed
      title="Embed Title"
      description="Embed description"
      color={0x5865F2}
      fields={[
        { name: "Field 1", value: "Value 1", inline: true },
        { name: "Field 2", value: "Value 2", inline: true },
      ]}
      footer={{ text: "Footer text" }}
      timestamp={new Date()}
    />
  );
}

Code Display

import { Code } from "@packages/ui/components/code";

function CodeExample() {
  return (
    <Code
      code={`function hello() {\n  console.log("Hello!");\n}`}
      language="typescript"
      showLineNumbers
      highlightLines={[2]}
    />
  );
}
code
string
required
Code to display
language
string
Language for syntax highlighting (uses Shiki)
showLineNumbers
boolean
Show line numbers
highlightLines
number[]
Lines to highlight

Utilities

Class Name Utilities

import { cn } from "@packages/ui/lib/utils";

function MyComponent({ className }: { className?: string }) {
  return (
    <div className={cn("base-class", "another-class", className)}>
      Content
    </div>
  );
}

Hooks

import { useToast } from "@packages/ui/hooks/use-toast";
import { useMediaQuery } from "@packages/ui/hooks/use-media-query";
import { useScrollContainer } from "@packages/ui/hooks/use-scroll-container";

function MyComponent() {
  const { toast } = useToast();
  const isMobile = useMediaQuery("(max-width: 768px)");
  const { scrollRef, isAtBottom } = useScrollContainer();
  
  return (
    <div ref={scrollRef}>
      <Button onClick={() => toast({ title: "Success!" })}>
        Show Toast
      </Button>
    </div>
  );
}

Analytics

import { trackEvent } from "@packages/ui/analytics";
import { usePostHog } from "@packages/ui/analytics/client";

function MyComponent() {
  const posthog = usePostHog();
  
  const handleClick = () => {
    trackEvent("button_clicked", {
      component: "MyComponent",
    });
    
    posthog?.capture("custom_event", {
      property: "value",
    });
  };
  
  return <Button onClick={handleClick}>Track Me</Button>;
}

Theme

import { ThemeProvider } from "next-themes";
import { useTheme } from "next-themes";

function App({ children }) {
  return (
    <ThemeProvider attribute="class" defaultTheme="system">
      {children}
    </ThemeProvider>
  );
}

function ThemeToggle() {
  const { theme, setTheme } = useTheme();
  
  return (
    <Button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>
      Toggle Theme
    </Button>
  );
}

Available Components

  • Accordion
  • Alert / Alert Dialog
  • Avatar
  • Badge
  • Button / Button Group
  • Calendar
  • Card
  • Carousel
  • Chart (Recharts)
  • Checkbox
  • Collapsible
  • Command
  • Context Menu
  • Dialog
  • Dropdown Menu
  • Form
  • Input / OTP Input
  • Label
  • Menubar
  • Navigation Menu
  • Popover
  • Progress
  • Radio Group
  • Scroll Area
  • Select
  • Separator
  • Slider
  • Switch
  • Table
  • Tabs
  • Toast / Sonner
  • Toggle / Toggle Group
  • Tooltip

Exports

./components/*
module
Individual UI components
./components/ai-elements/*
module
AI-specific components
./lib/*
module
Utility functions
./hooks/*
module
React hooks
./analytics
module
Analytics utilities
./globals.css
file
Global CSS styles

Dependencies

  • Radix UI - Accessible component primitives
  • Tailwind CSS - Utility-first CSS
  • class-variance-authority - Component variants
  • lucide-react - Icon library
  • next-themes - Theme management
  • react-hook-form - Form handling
  • recharts - Charts
  • sonner - Toast notifications