Getting Started
Core Architecture
Link Engine
Analytics & Attribution
Partners & Affiliates
Third-Party Integrations
Identity & Security
Automation & Messaging
Developer Tools
The following files were used as context for generating this wiki page:
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.
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, packages/ui/src/index.tsx:1-3, packages/embeds/react/tailwind.config.ts:1-10
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.
import sharedConfig from "@dub/tailwind-config/tailwind.config.ts";
import type { Config } from "tailwindcss";
const config: Pick<Config, "presets"> = {
presets: [sharedConfig],
};
export default config;The base style directives load the Tailwind layer architecture directly into the CSS bundle consumed by the component entry point.
@tailwind base;
@tailwind components;
@tailwind utilities;The @dub/tailwind-config package bundles foundational Tailwind plugins and utility extensions that govern typography, forms, container queries, scrollbars, and Radix state integrations.
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, packages/ui/src/alert.tsx:1-64, packages/ui/src/tooltip.tsx:1-288, packages/ui/src/button.tsx:1-158, packages/ui/src/radio-group.tsx:1-44
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.
Sources: packages/ui/src/button.tsx:7-28
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
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
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.
Sources: packages/ui/src/tooltip.tsx:14-287
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
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, packages/ui/src/alert.tsx:5-60, packages/ui/src/radio-group.tsx:9-42
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
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.
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
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
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
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.
Sources: packages/ui/src/sheet.tsx:5-51
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]).
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.
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: () => {},
});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.
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, packages/ui/src/accordion.tsx:7-67, apps/web/app/app.dub.co/dashboard/slug/ee/settings/tracking/stack-picker.tsx:62-121
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.
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;
};Note
When currentPresetId is explicitly provided, matchesCurrent bypasses date-value comparisons and validates directly against the preset identifier (currentPresetId === preset.id).
Accordion structures wrap Radix UI's AccordionPrimitive primitives to provide collapsible filter groups with support for chevron and plus icon variants.
Sources: packages/ui/src/accordion.tsx:7-68
The StackPicker component renders a grid of selectable tracking or integration items, managing toggle operations through an array-based value state.
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],
);
};
// ...
}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, apps/web/app/app.dub.co/dashboard/slug/ee/settings/tracking/stack-picker.tsx:108-109
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.
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
Sources: packages/ui/src/charts/index.ts:1-8
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, packages/ui/src/footer.tsx:1-121, packages/ui/src/nav/nav.tsx:1-166, packages/ui/src/carousel/carousel.tsx:1-195
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.
Sources: packages/ui/src/nav/nav.tsx:47-111
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.
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.
export function useCarousel() {
const context = useContext(CarouselContext);
if (!context) {
throw new Error("useCarousel must be used within a <Carousel />");
}
return context;
}