@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/uiThe 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 path | Types | ESM | CommonJS | Purpose |
|---|---|---|---|---|
@dub/ui | ./dist/index.d.ts | ./dist/index.mjs | ./dist/index.js | Main UI component surface |
@dub/ui/icons | ./dist/icons/index.d.ts | ./dist/icons/index.mjs | ./dist/icons/index.js | Icon component surface |
@dub/ui/charts | ./dist/charts/index.d.ts | ./dist/charts/index.mjs | ./dist/charts/index.js | Chart 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
| Area | Concrete names visible in source | Notes |
|---|---|---|
| Package name | @dub/ui | Public package for Dub UI components |
| Install command | pnpm i @dub/ui | Documented in the package README |
| Build output | dist/** | Only compiled output is included in the published package files |
| Main exports | ., ./icons, ./charts | Defined in the package export map |
| Scripts | build, dev, lint, check-types | Use tsup, ESLint, and TypeScript validation |
| Button variants | primary, secondary, outline, success, danger, danger-outline | Defined through buttonVariants |
| Button props | text, loading, icon, shortcut, right, disabledTooltip | Additional props layered on standard button attributes |
| Card-list API | CardList, CardList.Card, CardList.Card.Context, CardList.Context | Built with Object.assign composition |
| Carousel family | carousel, nav-bar, thumbnails | Re-exported from the carousel index |
| Chart family | areas, bars, chart-context, funnel-chart, time-series-chart, tooltip-sync, x-axis, y-axis | Re-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/uias 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 namespacedCardListAPI 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.