@dub/ui Package

Purpose and Scope

@dub/ui is Dub's shared React component library. Its README defines it as a library of React components used across Dub's web applications, which makes it the design-system package rather than an application feature package. When contributors build dashboard flows for links, analytics, conversion tracking, partner programs, or settings, this package is the place where reusable interface primitives and larger component families are expected to live. The goal is consistency: a button, chart, carousel, or card-list pattern should behave the same way wherever it appears in Dub's product UI.

Sources: packages/ui/README.md, packages/ui/package.json

The package is published as a public npm package named @dub/ui, with the package description UI components for Dub. Its package metadata exposes compiled JavaScript and TypeScript declaration files from dist, and the published file set is limited to dist/**. That means consumers should treat the TypeScript source tree as the development implementation and the dist output as the package contract produced by the build step. The package also declares sideEffects: false, which signals that bundlers can tree-shake unused exports when imports are structured appropriately.

Sources: packages/ui/package.json

Installation and Runtime Assumptions

Install the package with the command shown in the package README:

pnpm i @dub/ui

The package is built for React and Next.js applications. Its peer dependencies require next, react, and react-dom, while its development dependencies include Tailwind, TypeScript, tsup, and Dub workspace packages such as @dub/tailwind-config and @dub/utils. In practical terms, consumers should already be running a React application with compatible Next.js and React versions, and they should expect components to rely on Dub's shared utility conventions and Tailwind class names. The component code uses cn from @dub/utils, so class composition follows the same helper style as other Dub packages.

Sources: packages/ui/package.json, packages/ui/src/button.tsx

The package scripts define the contributor workflow for this library. pnpm build runs tsup, pnpm dev runs tsup --watch, pnpm lint runs ESLint over src/, and pnpm check-types runs tsc --noEmit. Those scripts make the package fit the wider monorepo pattern: source code is authored in TypeScript and React, validated through linting and type-checking, and compiled into the dist artifacts referenced by the npm export map. For local package work, start with the watch build when iterating and use the build and type-check commands before publishing or depending on new exported types.

Sources: packages/ui/package.json

Public Entry Points

The package export map exposes three top-level import surfaces. The root entry point @dub/ui resolves to ./dist/index.mjs for ESM imports, ./dist/index.js for CommonJS require, and ./dist/index.d.ts for TypeScript. The @dub/ui/icons subpath exposes icon declarations and compiled icon modules. The @dub/ui/charts subpath exposes chart-specific declarations and compiled chart modules. This split lets consumers import broad UI primitives from the root while keeping icon and chart usage addressable as separate package subpaths.

Sources: packages/ui/package.json

Import pathTypesESMCommonJSPurpose
@dub/ui./dist/index.d.ts./dist/index.mjs./dist/index.jsMain UI component surface
@dub/ui/icons./dist/icons/index.d.ts./dist/icons/index.mjs./dist/icons/index.jsIcon component surface
@dub/ui/charts./dist/charts/index.d.ts./dist/charts/index.mjs./dist/charts/index.jsChart component surface

The package dependencies explain what kinds of components the public surface can support. Radix UI packages back accessible primitives such as dialogs, popovers, labels, accordions, switches, sliders, navigation menus, tooltips, checkboxes, and radio groups. Visx packages support chart rendering, axes, shapes, gradients, groups, responsive layouts, scales, and tooltips. TipTap packages support rich-text editor functionality. Other dependencies, including embla-carousel-react, cmdk, sonner, vaul, react-day-picker, react-markdown, swr, and motion, indicate that the UI package includes higher-level interaction patterns beyond simple presentational components.

Sources: packages/ui/package.json

Core Primitives and Component Families

The button implementation is a useful example of the package's component style. buttonVariants is created with class-variance-authority and defines named visual variants: primary, secondary, outline, success, danger, and danger-outline, with primary as the default. ButtonProps extends the standard React button attributes and variant props, then adds Dub-specific options such as text, textWrapperClassName, shortcutClassName, loading, icon, shortcut, right, and disabledTooltip. The component is implemented with forwardRef, so it can participate in React ref-driven integrations while preserving normal button behavior.

Sources: packages/ui/src/button.tsx

The button also encodes several interaction decisions that consumers should understand before wrapping or reimplementing it. When disabledTooltip is supplied, the component renders a tooltip around a disabled-looking div instead of a native button, allowing the UI to explain why an action is unavailable. In normal operation, it renders a button whose type defaults to button when an onClick handler exists and to submit otherwise, matching form usage without requiring each caller to specify a type. Loading and disabled states share a non-interactive visual treatment, and loading replaces the icon area with LoadingSpinner.

Sources: packages/ui/src/button.tsx

Several supplied source files are barrel or composition modules that define family-level entry points. CardList composes a base CardListComponent with nested Card and Context properties, and the nested Card itself receives a Context property. This gives consumers a namespaced API for list and card subcomponents rather than forcing separate imports for every internal piece. The carousel index re-exports carousel, nav-bar, and thumbnails, which frames carousel UI as a coordinated set of moving parts. The charts index re-exports areas, bars, chart context, funnel chart, time-series chart, tooltip sync, and axes, defining charts as a multi-module visualization family.

Sources: packages/ui/src/card-list/index.ts, packages/ui/src/carousel/index.ts, packages/ui/src/charts/index.ts

Compact Reference

AreaConcrete names visible in sourceNotes
Package name@dub/uiPublic package for Dub UI components
Install commandpnpm i @dub/uiDocumented in the package README
Build outputdist/**Only compiled output is included in the published package files
Main exports., ./icons, ./chartsDefined in the package export map
Scriptsbuild, dev, lint, check-typesUse tsup, ESLint, and TypeScript validation
Button variantsprimary, secondary, outline, success, danger, danger-outlineDefined through buttonVariants
Button propstext, loading, icon, shortcut, right, disabledTooltipAdditional props layered on standard button attributes
Card-list APICardList, CardList.Card, CardList.Card.Context, CardList.ContextBuilt with Object.assign composition
Carousel familycarousel, nav-bar, thumbnailsRe-exported from the carousel index
Chart familyareas, bars, chart-context, funnel-chart, time-series-chart, tooltip-sync, x-axis, y-axisRe-exported from the charts index

Use this reference to choose the right level of import. For general interface elements, start with the root @dub/ui package. For chart-specific code, prefer the @dub/ui/charts subpath because the package metadata makes it a dedicated entry point. For icons, use @dub/ui/icons. When adding a new family, mirror the existing pattern: keep implementation modules close together, expose a concise index, and ensure the package build emits declarations that line up with the export map.

Sources: packages/ui/package.json, packages/ui/src/card-list/index.ts, packages/ui/src/carousel/index.ts, packages/ui/src/charts/index.ts

Relevant Source Files

  • packages/ui/README.md — Introduces @dub/ui as Dub's shared React component library and provides the installation command.
  • packages/ui/package.json — Defines the package name, version, public export map, build scripts, peer dependencies, dependencies, published files, and public publish configuration.
  • packages/ui/src/button.tsx — Shows a representative primitive component, including variant definitions, props, loading behavior, disabled tooltip behavior, and ref forwarding.
  • packages/ui/src/card-list/index.ts — Shows how a component family is composed into a namespaced CardList API with nested card and context members.
  • packages/ui/src/carousel/index.ts — Re-exports carousel modules for carousel, navigation bar, and thumbnails.
  • packages/ui/src/charts/index.ts — Re-exports chart modules for area and bar visuals, chart context, funnel and time-series charts, synchronized tooltips, and axes.

Next Steps

If you are consuming the package, install @dub/ui, verify compatible React and Next peer versions, and import from the root, icons, or charts entry point depending on the component family you need. If you are contributing to the package, run the package build, lint, and type-check scripts after changing components, and preserve the established pattern of small implementation modules with explicit index exports. For broader context, read the monorepo and publishing pages to understand how workspace packages are built and released together.