---
title: "UI Component Library"
description: "The Dub UI Component Library (@dub/ui) is a comprehensive design system and React component package engineered to power the Dub web application and ecosystem. Built on top of Radix UI primitives, T..."
last_updated: "2026-10-05T05:07:35.166923+00:00"
canonical_url: "https://www.doc0.dev/docs/934e554a-e6a1-476f-bb2f-23e62d86c3fd/technical/developer-tools/ui-component-library"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [packages/ui/tailwind.config.ts](https://github.com/blade47/dub/blob/HEAD/packages/ui/tailwind.config.ts)
- [packages/ui/package.json](https://github.com/blade47/dub/blob/HEAD/packages/ui/package.json)
- [packages/ui/src/index.tsx](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/index.tsx)
- [packages/embeds/react/tailwind.config.ts](https://github.com/blade47/dub/blob/HEAD/packages/embeds/react/tailwind.config.ts)
- [packages/ui/src/content.ts](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/content.ts)
- [packages/ui/src/styles.css](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/styles.css)
- [packages/ui/src/footer.tsx](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/footer.tsx)
- [apps/web/ui/modals/qr-code-design-fields.tsx](https://github.com/blade47/dub/blob/HEAD/apps/web/ui/modals/qr-code-design-fields.tsx)
- [packages/tailwind-config/package.json](https://github.com/blade47/dub/blob/HEAD/packages/tailwind-config/package.json)
- [packages/ui/src/date-picker/presets.tsx](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/date-picker/presets.tsx)
- [packages/ui/src/nav/nav.tsx](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/nav/nav.tsx)
- [packages/ui/src/nav/content/shared.tsx](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/nav/content/shared.tsx)
- [packages/ui/src/accordion.tsx](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/accordion.tsx)
- [packages/ui/src/label.tsx](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/label.tsx)
- [packages/ui/src/carousel/carousel.tsx](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/carousel/carousel.tsx)
- [packages/ui/src/alert.tsx](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/alert.tsx)
- [apps/web/app/app.dub.co/dashboard/layout.tsx](https://github.com/blade47/dub/blob/HEAD/apps/web/app/app.dub.co/(dashboard)/layout.tsx)
- [apps/web/app/app.dub.co/dashboard/slug/ee/settings/tracking/stack-picker.tsx](https://github.com/blade47/dub/blob/HEAD/apps/web/app/app.dub.co/(dashboard)/%5Bslug%5D/(ee)/settings/tracking/stack-picker.tsx)
- [packages/ui/src/sheet.tsx](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/sheet.tsx)
- [apps/web/app/domain/layout.tsx](https://github.com/blade47/dub/blob/HEAD/apps/web/app/%5Bdomain%5D/layout.tsx)
- [packages/ui/src/tooltip.tsx](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/tooltip.tsx)
- [packages/ui/src/nav/index.ts](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/nav/index.ts)
- [packages/ui/src/charts/index.ts](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/charts/index.ts)
- [apps/web/ui/modals/modal-provider.tsx](https://github.com/blade47/dub/blob/HEAD/apps/web/ui/modals/modal-provider.tsx)
- [apps/web/ui/shared/emoji-picker.tsx](https://github.com/blade47/dub/blob/HEAD/apps/web/ui/shared/emoji-picker.tsx)
- [packages/ui/src/button.tsx](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/button.tsx)
- [packages/ui/src/modal.tsx](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/modal.tsx)
- [apps/web/app/app.dub.co/dashboard/loading.tsx](https://github.com/blade47/dub/blob/HEAD/apps/web/app/app.dub.co/(dashboard)/loading.tsx)
- [packages/ui/src/radio-group.tsx](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/radio-group.tsx)
- [apps/web/app/api/callback/plain/utils.ts](https://github.com/blade47/dub/blob/HEAD/apps/web/app/api/callback/plain/utils.ts)
</details>

## Overview

The Dub UI Component Library (`@dub/ui`) is a comprehensive design system and React component package engineered to power the Dub web application and ecosystem. Built on top of Radix UI primitives, Tailwind CSS, and Class Variance Authority (CVA), it provides a robust foundation for building accessible, responsive, and type-safe interfaces. The library centralizes design tokens, styling presets, interactive controls, and specialized domain components—ranging from time-series charts and rich-text areas to adaptive modals and navigation bars—ensuring visual consistency and rapid feature development across all Dub properties.

Sources: [packages/ui/package.json:2-115](https://github.com/blade47/dub/blob/HEAD/packages/ui/package.json#L2-L115), [packages/ui/src/index.tsx:1-87](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/index.tsx#L1-L87)

## Design System Architecture and Styling

### Overview

The design system architecture relies on a structured monorepo package layout that separates shared styling tokens from component implementations. The core UI package `@dub/ui` consumes Tailwind configuration presets from `@dub/tailwind-config`, ensuring consistent token sharing across packages like `@dub/embeds/react`. Base CSS injection is handled centrally at the entry point of the package.

Sources: [packages/ui/tailwind.config.ts:1-10](https://github.com/blade47/dub/blob/HEAD/packages/ui/tailwind.config.ts#L1-L10), [packages/ui/src/index.tsx:1-3](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/index.tsx#L1-L3), [packages/embeds/react/tailwind.config.ts:1-10](https://github.com/blade47/dub/blob/HEAD/packages/embeds/react/tailwind.config.ts#L1-L10)

### Tailwind Presets and Base Styles

The styling pipeline integrates Tailwind CSS base, component, and utility layers through a dedicated stylesheet. Both `@dub/ui` and `@dub/embeds/react` extend the shared Tailwind configuration via the `presets` property to maintain uniform design constraints.

```typescript
import sharedConfig from "@dub/tailwind-config/tailwind.config.ts";
import type { Config } from "tailwindcss";

const config: Pick<Config, "presets"> = {
  presets: [sharedConfig],
};

export default config;
```

Sources: [packages/ui/tailwind.config.ts:1-10](https://github.com/blade47/dub/blob/HEAD/packages/ui/tailwind.config.ts#L1-L10), [packages/embeds/react/tailwind.config.ts:1-10](https://github.com/blade47/dub/blob/HEAD/packages/embeds/react/tailwind.config.ts#L1-L10)

The base style directives load the Tailwind layer architecture directly into the CSS bundle consumed by the component entry point.

```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

Sources: [packages/ui/src/styles.css:1-3](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/styles.css#L1-L3), [packages/ui/src/index.tsx:1-2](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/index.tsx#L1-L2)

### Monorepo Integration and Dependencies

The `@dub/tailwind-config` package bundles foundational Tailwind plugins and utility extensions that govern typography, forms, container queries, scrollbars, and Radix state integrations.

| Dependency Package | Version | Purpose |
| :--- | :--- | :--- |
| `@tailwindcss/container-queries` | `^0.1.1` | Enables container query utilities |
| `@tailwindcss/forms` | `^0.5.6` | Resets form element styling |
| `@tailwindcss/typography` | `^0.5.9` | Provides prose styling classes |
| `tailwind-scrollbar-hide` | `^1.1.7` | Utilities for hiding scrollbars |
| `tailwindcss-radix` | `^2.8.0` | Radix UI state variant integration |

Sources: [packages/tailwind-config/package.json:10-16](https://github.com/blade47/dub/blob/HEAD/packages/tailwind-config/package.json#L10-L16)

## Interactive Primitives and Variants

### Overview

The interactive primitive and form control layer of `@dub/ui` combines Radix UI headless components with Class Variance Authority (`cva`) and the `@dub/utils` `cn` class-merging helper. This architecture powers base components such as `Button`, `Tooltip`, `Label`, `Alert`, and `RadioGroup`, maintaining strict type safety, accessibility attributes, and dynamic styling variants across the library.

Sources: [packages/ui/src/label.tsx:1-24](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/label.tsx#L1-L24), [packages/ui/src/alert.tsx:1-64](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/alert.tsx#L1-L64), [packages/ui/src/tooltip.tsx:1-288](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/tooltip.tsx#L1-L288), [packages/ui/src/button.tsx:1-158](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/button.tsx#L1-L158), [packages/ui/src/radio-group.tsx:1-44](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/radio-group.tsx#L1-L44)

### Button Variants and Execution Lifecycle

The `Button` component supports multiple visual intents and states, including loading indicators, keyboard shortcut badges, icons, and disabled tooltips. When `disabledTooltip` is provided, the component renders a disabled container wrapped in a `Tooltip` rather than a standard button element.

| Variant | Styling Class Definition | Purpose / Interaction State |
| :--- | :--- | :--- |
| `primary` | `border-black bg-black dark:bg-white dark:border-white text-content-inverted hover:bg-inverted hover:ring-4 hover:ring-border-subtle` | High-emphasis primary actions |
| `secondary` | `border-border-subtle bg-bg-default text-content-emphasis hover:bg-bg-muted focus-visible:border-border-emphasis outline-none data-[state=open]:border-border-emphasis data-[state=open]:ring-4 data-[state=open]:ring-border-subtle` | Secondary or contextual actions, supporting open state rings |
| `outline` | `border-transparent text-content-default hover:bg-neutral-900/5` | Low-emphasis borderless buttons |
| `success` | `border-blue-500 bg-blue-500 text-white hover:bg-blue-600 hover:ring-4 hover:ring-blue-100` | Positive state actions |
| `danger` | `border-red-500 bg-red-500 text-white hover:bg-red-600 hover:ring-4 hover:ring-red-100` | Destructive high-emphasis actions |
| `danger-outline` | `border-transparent bg-white text-red-500 hover:bg-red-600 hover:text-white` | Destructive low-emphasis actions |

Sources: [packages/ui/src/button.tsx:7-28](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/button.tsx#L7-L28)

The button execution flow determines whether an interaction triggers form submission or handles click events directly based on props:

```
Button Input Props (onClick, disabled, loading, disabledTooltip)
  │
  ├─► Has disabledTooltip? ──► Render <Tooltip> + <div> (cursor-not-allowed, shortcut, icon)
  │
  └─► No disabledTooltip? ──► Render <button type={onClick ? "button" : "submit"}>
        │
        ├─► loading = true? ──► Render <LoadingSpinner />
        ├─► icon present?  ──► Render icon element
        ├─► text present?  ──► Render truncated text container
        ├─► shortcut?      ──► Render <kbd> shortcut badge with variant-specific styling
        └─► right present? ──► Render right accessory node
```

Sources: [packages/ui/src/button.tsx:60-152](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/button.tsx#L60-L152)

> [!NOTE]
> If a `Button` receives an `onClick` handler, its HTML `type` attribute defaults to `"button"`; otherwise, it defaults to `"submit"` for form integration.

Sources: [packages/ui/src/button.tsx:105-107](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/button.tsx#L105-L107)

### Tooltip Architecture and Specialized Wrappers

The `Tooltip` ecosystem builds upon `@radix-ui/react-tooltip`, integrating Markdown rendering via `react-markdown`, custom scroll progress tracking, and specialized wrappers for badges, buttons, and info icons.

| Component | Underlying Structure | Key Props / Features |
| :--- | :--- | :--- |
| `Tooltip` | `TooltipPrimitive.Root`, `Trigger`, `Portal`, `Content` | `content` (string, ReactNode, or render function), `disabled`, `side`, `delayDuration` |
| `InfoTooltip` | Wraps `Tooltip` | Renders a `HelpCircle` icon (`h-4 w-4 text-neutral-500`) as trigger |
| `BadgeTooltip` | Wraps `Tooltip` | Renders a `Badge` variant="gray" as trigger |
| `ButtonTooltip` | Wraps `Tooltip` | Renders a styled `<button>` element with hover and active states |
| `ScrollableTooltipContent` | `useScrollProgress` hook | Manages vertical scrolling with dynamic top and bottom fade gradients |

Sources: [packages/ui/src/tooltip.tsx:14-287](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/tooltip.tsx#L14-L287)

> [!TIP]
> The `ScrollableTooltipContent` component automatically evaluates `scrollHeight > clientHeight` to toggle gradient overlays indicating scrollability as the user navigates through scroll progress updates.

Sources: [packages/ui/src/tooltip.tsx:233-264](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/tooltip.tsx#L233-L264)

### Form Primitives and Variants

Basic form controls are structured using Radix primitives combined with `cva` styling definitions to enforce accessible states, disabled cursor behaviors, and consistent typography.

* **`Label`**: Wraps `@radix-ui/react-label` with `labelVariants` defining `text-sm font-medium leading-none text-content-emphasis` and peer disabled styles (`peer-disabled:cursor-not-allowed peer-disabled:opacity-70`).
* **`Alert`**: Implements `role="alert"` via `alertVariants`, supporting `default` and `destructive` variants with precise SVG icon positioning (`[&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4`). Accompanied by `AlertTitle` and `AlertDescription`.
* **`RadioGroup`**: Combines `@radix-ui/react-radio-group` Root and Item components, styling the active state with a centered `Circle` indicator (`aspect-square h-4 w-4 rounded-full border`).

Sources: [packages/ui/src/label.tsx:6-20](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/label.tsx#L6-L20), [packages/ui/src/alert.tsx:5-60](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/alert.tsx#L5-L60), [packages/ui/src/radio-group.tsx:9-42](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/radio-group.tsx#L9-L42)

> [!WARNING]
> When applying `Alert` with destructive states, ensure both border color classes (`border-destructive/50` and `border-red-500`) are maintained to guarantee compatibility across color schemes and dark mode configurations.

Sources: [packages/ui/src/alert.tsx:11-13](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/alert.tsx#L11-L13)

## Responsive Modals and Overlays

### Overview

The UI component library implements adaptive container overlays and modal architectures that dynamically switch rendering paradigms based on viewport media queries and functional scope. Components such as `Modal` evaluate device context to render either a mobile-optimized Vaul drawer or a Radix UI desktop dialog, while specialized sheet overlays provide right-side panel drawers with dedicated container query support.

Sources: [packages/ui/src/modal.tsx:47-50](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/modal.tsx#L47-L50), [packages/ui/src/sheet.tsx:35-39](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/sheet.tsx#L35-L39)

### Adaptive Modal Architecture and Lifecycle

The `Modal` component coordinates overlay display logic across mobile and desktop viewports using the `useMediaQuery` hook. When `isMobile` evaluates to true and `desktopOnly` is not set, the component mounts a `Drawer.Root` configuration with touch-friendly gestures, incorporating a `DrawerIsland` handle element. Otherwise, it defaults to a `@radix-ui/react-dialog` implementation featuring scale-in animations and blurred backdrops.

Sources: [packages/ui/src/modal.tsx:11-137](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/modal.tsx#L11-L137)

```
Modal Invocation (showModal / setShowModal / onClose)
  │
  ├─► isMobile && !desktopOnly? ──► Render <Drawer.Root> (direction="bottom", <DrawerIsland />)
  │
  └─► desktop or desktopOnly? ──► Render <Dialog.Root> (centered max-w-md, animate-scale-in)
        │
        ├─► User clicks backdrop / presses Esc? ──► Trigger closeModal()
        │     │
        │     ├─► preventDefaultClose && !dragged? ──► Abort close
        │     └─► else ──► Execute onClose?() → setShowModal(false) OR router.back()
```

Sources: [packages/ui/src/modal.tsx:32-136](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/modal.tsx#L32-L136)

> [!WARNING]
> When `preventDefaultClose` is active, closing events triggered by backdrop clicks or escape keys are blocked unless the dismissal originates from a dragged drawer gesture (`dragged: true`), preserving unsaved user input inside active forms.

Sources: [packages/ui/src/modal.tsx:32-35](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/modal.tsx#L32-L35)

### Sheet Overlays and Vaul Drawer Integration

Side-anchored slide-over panels are built using the `Sheet` component, which wraps Vaul's drawer primitives (`Drawer.Root` or `Drawer.NestedRoot`) with a fixed right-side direction and handle-only interaction model. The sheet content container applies container query scopes and dimension variables.

| Component Part | Underlying Library / Element | Key CSS Classes / Properties |
| :--- | :--- | :--- |
| `SheetRoot` | `Drawer.Root` / `Drawer.NestedRoot` | `direction="right"`, `handleOnly=true` |
| Sheet Overlay | `Drawer.Overlay` | `fixed inset-0 z-40 bg-black/20` |
| Sheet Content | `Drawer.Content` | `@container/sheet fixed bottom-2 right-2 top-2 z-40 w-[min(var(--sheet-width),calc(100%-2*var(--sheet-margin)))] [--sheet-width:540px]` |
| Scroll Container | `div` | `scrollbar-hide flex size-full grow flex-col overflow-y-auto rounded-xl bg-white` |

Sources: [packages/ui/src/sheet.tsx:5-51](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/sheet.tsx#L5-L51)

> [!TIP]
> Both `Modal` and `Sheet` components inspect pointer events during `onPointerDownOutside` callbacks to prevent accidental dismissal when a user clicks inside an active Sonner toast notification (`[data-sonner-toast]`).

Sources: [packages/ui/src/sheet.tsx:25-31](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/sheet.tsx#L25-L31), [packages/ui/src/modal.tsx:63-70](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/modal.tsx#L63-L70)

### Modal Context and Provider Architecture

Global modal visibility state across web views is managed through `ModalContext` and the `ModalProvider` client wrapper. The context exposes dispatch functions to control workspace creation, domain editing, link building, tag configuration, and bulk data imports.

```typescript
export const ModalContext = createContext<{
  setShowAddWorkspaceModal: Dispatch<SetStateAction<boolean>>;
  setShowAddEditDomainModal: Dispatch<SetStateAction<boolean>>;
  setShowLinkBuilder: Dispatch<SetStateAction<boolean>>;
  setShowAddEditTagModal: Dispatch<SetStateAction<boolean>>;
  setShowImportBitlyModal: Dispatch<SetStateAction<boolean>>;
  setShowImportShortModal: Dispatch<SetStateAction<boolean>>;
  setShowImportRebrandlyModal: Dispatch<SetStateAction<boolean>>;
  setShowImportCsvModal: Dispatch<SetStateAction<boolean>>;
}>({
  setShowAddWorkspaceModal: () => {},
  setShowAddEditDomainModal: () => {},
  setShowLinkBuilder: () => {},
  setShowAddEditTagModal: () => {},
  setShowImportBitlyModal: () => {},
  setShowImportShortModal: () => {},
  setShowImportRebrandlyModal: () => {},
  setShowImportCsvModal: () => {},
});
```

Sources: [apps/web/ui/modals/modal-provider.tsx:32-50](https://github.com/blade47/dub/blob/HEAD/apps/web/ui/modals/modal-provider.tsx#L32-L50)

The `ModalProviderClient` mounts these modal instances at the root layout level while evaluating query parameters such as `?newWorkspace`, `?newLink`, `?upgraded`, and `?onboarded-program` on initial render to trigger automated modal lifecycles.

Sources: [apps/web/ui/modals/modal-provider.tsx:60-194](https://github.com/blade47/dub/blob/HEAD/apps/web/ui/modals/modal-provider.tsx#L60-L194)

## Date Pickers and Advanced Filtering

### Overview

Date selection and advanced filtering primitives are constructed using command list mechanics, Radix UI accordion structures, and toggleable selection buttons. The `Presets` component handles date ranges and single dates within a command palette container (`cmdK`), while `Accordion` components manage hierarchical disclosure panels, and `StackPicker` provides grid-based multi-selection options.

Sources: [packages/ui/src/date-picker/presets.tsx:79-119](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/date-picker/presets.tsx#L79-L119), [packages/ui/src/accordion.tsx:7-67](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/accordion.tsx#L7-L67), [apps/web/app/app.dub.co/dashboard/slug/ee/settings/tracking/stack-picker.tsx:62-121](https://github.com/blade47/dub/blob/HEAD/apps/web/app/app.dub.co/(dashboard)/%5Bslug%5D/(ee)/settings/tracking/stack-picker.tsx#L62-L121)

### Preset Date Range Selections and Comparison Helpers

The `Presets` component evaluates and matches active date ranges or individual dates against predefined configurations. It distinguishes between `DateRangePreset` and `DatePreset` objects using type guards (`isDateRangePresets` and `isDatePresets`) and compares calendar days using `compareDates` and `compareRanges`.

```typescript
const compareDates = (date1: Date, date2: Date) =>
  date1.getDate() === date2.getDate() &&
  date1.getMonth() === date2.getMonth() &&
  date1.getFullYear() === date2.getFullYear();

const compareRanges = (range1: DateRange, range2: DateRange) => {
  const from1 = range1.from;
  const from2 = range2.from;
  let equalFrom = false;
  if (from1 && from2) {
    if (compareDates(from1, from2)) equalFrom = true;
  }
  const to1 = range1.to;
  const to2 = range2.to;
  let equalTo = false;
  if (to1 && to2) {
    if (compareDates(to1, to2)) equalTo = true;
  }
  return equalFrom && equalTo;
};
```

Sources: [packages/ui/src/date-picker/presets.tsx:24-58](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/date-picker/presets.tsx#L24-L58)

> [!NOTE]
> When `currentPresetId` is explicitly provided, `matchesCurrent` bypasses date-value comparisons and validates directly against the preset identifier (`currentPresetId === preset.id`).

Sources: [packages/ui/src/date-picker/presets.tsx:60-63](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/date-picker/presets.tsx#L60-L63)

### Accordion-Based Filter Primitives

Accordion structures wrap Radix UI's `AccordionPrimitive` primitives to provide collapsible filter groups with support for chevron and plus icon variants.

| Component Part | Underlying Primitive / Element | Key Class Names & Behavior |
| :--- | :--- | :--- |
| `Accordion` | `AccordionPrimitive.Root` | Root container for accordion items |
| `AccordionItem` | `AccordionPrimitive.Item` | `border-b border-b-slate-200 py-3 last:border-none` |
| `AccordionTrigger` | `AccordionPrimitive.Trigger` | `flex flex-1 items-center justify-between font-medium` with rotation transforms for `chevron` (`[&[data-state=open]>svg]:rotate-180`) and `plus` (`[&[data-state=open]>svg]:rotate-45`) variants |
| `AccordionContent` | `AccordionPrimitive.Content` | `data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm text-neutral-500` |

Sources: [packages/ui/src/accordion.tsx:7-68](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/accordion.tsx#L7-L68)

### Stack Picker and Selection State

The `StackPicker` component renders a grid of selectable tracking or integration items, managing toggle operations through an array-based value state.

```typescript
export function StackPicker({
  items,
  value,
  onChange,
  disabled,
}: {
  items: StackItem[];
  value: string[];
  onChange: (value: string[]) => void;
  disabled?: boolean;
}) {
  const toggleItem = (id: string) => {
    if (disabled) {
      return;
    }

    onChange(
      value.includes(id) ? value.filter((item) => item !== id) : [...value, id],
    );
  };

// ...
}
```

Sources: [apps/web/app/app.dub.co/dashboard/slug/ee/settings/tracking/stack-picker.tsx:62-81](https://github.com/blade47/dub/blob/HEAD/apps/web/app/app.dub.co/(dashboard)/%5Bslug%5D/(ee)/settings/tracking/stack-picker.tsx#L62-L81)

> [!WARNING]
> Interaction events inside `StackPicker` buttons are disabled when the `disabled` prop is set to `true`, preventing item toggling and applying `cursor-not-allowed opacity-50` styling classes.

Sources: [apps/web/app/app.dub.co/dashboard/slug/ee/settings/tracking/stack-picker.tsx:73-76](https://github.com/blade47/dub/blob/HEAD/apps/web/app/app.dub.co/(dashboard)/%5Bslug%5D/(ee)/settings/tracking/stack-picker.tsx#L73-L76), [apps/web/app/app.dub.co/dashboard/slug/ee/settings/tracking/stack-picker.tsx:108-109](https://github.com/blade47/dub/blob/HEAD/apps/web/app/app.dub.co/(dashboard)/%5Bslug%5D/(ee)/settings/tracking/stack-picker.tsx#L108-L109)

## Data Visualization and Chart Systems

### Overview

The chart and data visualization system is centralized through export modules that aggregate chart components, time-series modules, axes, and interactive overlays. The main entry point re-exports modules handling area charts, bar charts, chart contexts, funnel charts, time-series charts, tooltip synchronization, x-axes, and y-axes.

```typescript
export * from "./areas";
export * from "./bars";
export * from "./chart-context";
export * from "./funnel-chart";
export * from "./time-series-chart";
export * from "./tooltip-sync";
export * from "./x-axis";
export * from "./y-axis";
```

Sources: [packages/ui/src/charts/index.ts:1-9](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/charts/index.ts#L1-L9)

### Chart Component Exports

| Export Module | Target File | Purpose |
| :--- | :--- | :--- |
| `areas` | `./areas` | Area chart primitives and rendering configurations |
| `bars` | `./bars` | Bar chart components and column visualization primitives |
| `chart-context` | `./chart-context` | React context providers for shared chart states and dimensions |
| `funnel-chart` | `./funnel-chart` | Conversion funnel visualization components |
| `time-series-chart` | `./time-series-chart` | Time-series data rendering and temporal axis management |
| `tooltip-sync` | `./tooltip-sync` | Cross-chart tooltip synchronization and hover state coordination |
| `x-axis` | `./x-axis` | Horizontal axis formatting, ticks, and scaling |
| `y-axis` | `./y-axis` | Vertical axis scaling, grid lines, and value formatting |

Sources: [packages/ui/src/charts/index.ts:1-8](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/charts/index.ts#L1-L8)

## Navigation and Content Layout Systems

### Overview

The navigation and content layout subsystem comprises public navigation bars, content link cards, mobile menus, layout footers, and carousel display containers. It structures page routing and content discovery across public domains via `@dub/ui` package exports.

Sources: [packages/ui/src/content.ts:1-235](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/content.ts#L1-L235), [packages/ui/src/footer.tsx:1-121](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/footer.tsx#L1-L121), [packages/ui/src/nav/nav.tsx:1-166](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/nav/nav.tsx#L1-L166), [packages/ui/src/carousel/carousel.tsx:1-195](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/carousel/carousel.tsx#L1-L195)

### Navigation Structures and Content Constants

Navigation items and dropdown contents are defined via typed structures supporting nested items, icons, and UTM tagging. The `navItems` array in `nav.tsx` configures primary site routes with associated segment matching and content components.

| Navigation Item | Target Href / Content | Segments | Mobile Only |
| :--- | :--- | :--- | :--- |
| `Product` | `ProductContent` | `/links`, `/analytics`, `/partners`, `/integrations`, `/compare`, `/features` | false |
| `Solutions` | `SolutionsContent` | `/solutions`, `/enterprise`, `/startups`, `/sdks` | false |
| `Resources` | `ResourcesContent` | `/help`, `/docs`, `/about`, `/careers`, `/brand`, `/blog`, `/changelog`, `/contact`, `/marketplace` | false |
| `Customers` | `/customers` | `/customers` | false |
| `Pricing` | `/pricing` | `/pricing` | false |
| `Enterprise` | `/enterprise` | `/enterprise` | true |
| `Startups` | `/startups` | `/startups` | true |

Sources: [packages/ui/src/nav/nav.tsx:47-111](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/nav/nav.tsx#L47-L111)

> [!NOTE]
> The `NavContext` provides a `theme` setting defaulting to `"light"`, while `sessionFetcher` handles SWR requests to the session route, specifically caching `401` responses as `null` to prevent revalidation from resetting `isLoading` states.

Sources: [packages/ui/src/nav/nav.tsx:32-36](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/nav/nav.tsx#L32-L36), [packages/ui/src/nav/nav.tsx:141-146](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/nav/nav.tsx#L141-L146)

### Carousel Component Architecture

### Carousel Subsystem Overview

The carousel implementation is built around `embla-carousel-react` and `embla-carousel-autoplay`. It exports a React context (`CarouselContext`) exposing state values and control callbacks.

```typescript
export function useCarousel() {
  const context = useContext(CarouselContext);

  if (!context) {
    throw new Error("useCarousel must be used within a <Carousel />");
  }

  return context;
}
```

Sources: [packages/ui/src/carousel/carousel.tsx:46-54](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/carousel/carousel.tsx#L46-L54)

### Carousel Subcomponents

| Component | Description |
| :--- | :--- |
| `Carousel` | Root container managing Embla initialization, autoplay plugins, orientation, and keyboard navigation (`ArrowLeft`, `ArrowRight`) |
| `CarouselContent` | Viewport wrapper container applying flex layout and orientation-based margins |
| `CarouselItem` | Individual slide wrapper with `min-w-0 shrink-0 grow-0 basis-full` styling |
| `CarouselPrevious` | Absolute positioned previous slide navigation button controlled by `canScrollPrev` |
| `CarouselNext` | Absolute positioned next slide navigation button controlled by `canScrollNext` |

Sources: [packages/ui/src/carousel/carousel.tsx:77-295](https://github.com/blade47/dub/blob/HEAD/packages/ui/src/carousel/carousel.tsx#L77-L295)

## Related

- [Project Structure](https://www.doc0.dev/docs/934e554a-e6a1-476f-bb2f-23e62d86c3fd/technical/getting-started/project-structure)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/934e554a-e6a1-476f-bb2f-23e62d86c3fd/llms.txt) for all pages in this wiki.
