tremorlabs/tremor

Copy & Paste React components to build modern web applications.

3,383 stars TypeScript 8 components

Component library that provides accessible React UI components for dashboard applications

Props flow from parent components through the component tree, where each Tremor component receives standard React props plus variant-specific props. The cx utility merges these classes with default styles, tailwind-variants generates conditional CSS based on variant props, and the final className is passed to either a native DOM element or a Radix UI primitive. Radix primitives handle accessibility features while Tremor adds consistent visual design.

Under the hood, the system uses 2 data pools, 3 control points to manage its runtime behavior.

A 8-component library. 139 files analyzed. Data flows through 4 distinct pipeline stages.

How Data Flows Through the System

Props flow from parent components through the component tree, where each Tremor component receives standard React props plus variant-specific props. The cx utility merges these classes with default styles, tailwind-variants generates conditional CSS based on variant props, and the final className is passed to either a native DOM element or a Radix UI primitive. Radix primitives handle accessibility features while Tremor adds consistent visual design.

  1. Props Reception — Component receives props including className overrides, variant selections (size, color, etc.), disabled state, and standard React props like children and event handlers through forwardRef [ComponentProps]
  2. Variant Processing — tailwind-variants tv() function receives variant prop values and generates base CSS classes plus variant-specific classes using conditional logic defined in the component's variant configuration [ComponentProps → VariantConfig]
  3. Style Composition — cx utility function merges generated variant classes with user-provided className prop using clsx for conditional application and tailwind-merge for CSS precedence resolution [VariantConfig → ClassValue]
  4. Component Rendering — Final merged className is applied to either a Radix UI primitive (for complex components like Switch, Accordion) or a native DOM element, with props forwarded through React.forwardRef for ref handling [ClassValue]

Data Models

The data structures that flow between stages — the contracts that hold the system together.

ComponentProps src/components/Button/Button.tsx
React.ComponentPropsWithoutRef<T> extended with variant props - includes className: string, disabled: boolean, size/variant discriminated unions, children: ReactNode, and forwarded refs
Props are passed from parent components, merged with default variants using tailwind-variants, and forwarded to the underlying DOM element or Radix primitive
VariantConfig src/components/Button/Button.tsx
tailwind-variants tv() configuration object with base: string[], variants: Record<string, Record<string, string[]>>, defaultVariants: Record<string, string>
Defined statically per component, receives variant prop values at runtime, generates final CSS class strings using conditional logic
ClassValue src/utils/cx.ts
Union type from clsx accepting string | object | array | undefined - represents any valid CSS class input that can be conditionally applied
Class values are collected from component variants and user overrides, merged using clsx for conditional logic, then deduplicated with tailwind-merge for CSS precedence

Hidden Assumptions

Things this code relies on but never validates. These are the things that cause silent failures when the system changes.

critical Domain unguarded

The cx function assumes all input ClassValue arguments are valid Tailwind CSS classes that tailwind-merge can understand and deduplicate correctly

If this fails: If non-Tailwind CSS classes or malformed class strings are passed, tailwind-merge may silently ignore them or produce unexpected class combinations, leading to broken styling without any error indication

src/utils/cx.ts:cx
critical Environment unguarded

Assumes Tailwind CSS is configured with the exact color palette and utilities referenced (blue-500, gray-300, etc.) and that dark mode is enabled via the 'dark:' prefix

If this fails: If Tailwind config is missing these colors or dark mode support, components render with broken styling - missing colors appear as plain text, dark mode styles are ignored, but no runtime errors occur

src/components/Button/Button.tsx:buttonVariants
critical Contract unguarded

The Switch component assumes Radix UI SwitchPrimitives.Root provides data-[state=checked] and data-[state=unchecked] attributes that CSS selectors depend on for visual state changes

If this fails: If Radix UI changes these data attribute names in future versions, the switch will render but state-dependent styling (colors, thumb position) will break completely, leaving a non-functional looking component

src/components/Switch/Switch.tsx:Switch
critical Shape unguarded

Assumes the returned domain tuple [minDomain, maxDomain] where values can be either 'auto' strings or numbers will be consumed by a charting library that understands this mixed-type format

If this fails: If the consuming chart library expects consistent types (all numbers or all strings), it may crash, render incorrectly, or ignore the domain values entirely, breaking chart scaling behavior

src/utils/getYAxisDomain.ts:getYAxisDomain
warning Contract unguarded

When asChild=true, assumes the children prop contains exactly one React element that Radix Slot can clone and merge props into

If this fails: If children contains multiple elements, text nodes, or null values when asChild=true, Radix Slot throws runtime errors or renders nothing, breaking the component completely

src/components/Card/Card.tsx:Card
warning Environment unguarded

Assumes the consuming environment supports CSS outline-offset and focus-visible pseudo-class, which are relatively modern CSS features

If this fails: In older browsers or environments without focus-visible support, focus indicators may not appear at all, creating accessibility violations for keyboard navigation

src/utils/focusRing.ts:focusRing
warning Domain unguarded

The disabled prop on Label assumes consumers will coordinate this state with associated form controls, but Label itself has no mechanism to enforce or validate this relationship

If this fails: Labels can appear disabled while their associated inputs remain enabled (or vice versa), creating confusing UX where visual state doesn't match functional state

src/components/Label/Label.tsx:Label
warning Scale unguarded

Switch size variants hardcode specific pixel values for width/height (h-5 w-9, h-4 w-7) and translation distances (translate-x-4, translate-x-3) assuming standard Tailwind spacing scale

If this fails: If Tailwind spacing is customized or components need different sizing, the thumb translation may not align properly with the track, creating visual misalignment where the thumb doesn't reach track edges

src/components/Switch/Switch.tsx:switchVariants
info Resource weakly guarded

Assumes tailwind-merge's internal cache can handle the volume of className combinations without memory issues or significant performance degradation

If this fails: In applications with many dynamic class combinations or long-running sessions, the cache could grow large enough to cause memory pressure or GC overhead, degrading UI responsiveness

src/utils/cx.ts:cx
info Contract unguarded

Storybook configuration assumes all component stories follow the naming pattern *.stories.@(js|jsx|mjs|ts|tsx) and are located under src/**/ directories

If this fails: Stories placed in other locations or using different naming conventions won't be discovered by Storybook, making components appear missing from the development environment without clear error messages

.storybook/main.ts:config

System Behavior

How the system operates at runtime — where data accumulates, what loops, what waits, and what controls what.

Data Pools

Variant Registry (registry)
Each component defines its variant configurations using tailwind-variants tv() - maps variant prop combinations to CSS class arrays
Utility Cache (in-memory)
tailwind-merge maintains internal cache of CSS class precedence rules to avoid recomputing class merging logic

Delays

Control Points

Technology Stack

Radix UI (library)
Provides unstyled, accessible component primitives that Tremor wraps with its design system
Tailwind CSS (framework)
CSS utility framework used for all component styling through class composition
tailwind-variants (library)
Generates conditional CSS classes based on component props - handles variant logic and type safety
tailwind-merge (library)
Deduplicates and resolves precedence conflicts between Tailwind CSS classes
clsx (library)
Conditionally applies CSS classes based on boolean logic and object notation
Storybook (framework)
Development environment for building and documenting components in isolation
Playwright (testing)
End-to-end testing of component behavior and interactions in Storybook
Vite (build)
Build tool for development server and production bundling

Key Components

Explore the interactive analysis

See the full architecture map, data flow, and code patterns visualization.

Analyze on CodeSea

Related Library Repositories

Frequently Asked Questions

What is tremor used for?

Component library that provides accessible React UI components for dashboard applications tremorlabs/tremor is a 8-component library written in TypeScript. Data flows through 4 distinct pipeline stages. The codebase contains 139 files.

How is tremor architected?

tremor is organized into 3 architecture layers: Core Utilities, Component Layer, Development Tooling. Data flows through 4 distinct pipeline stages. This layered structure keeps concerns separated and modules independent.

How does data flow through tremor?

Data moves through 4 stages: Props Reception → Variant Processing → Style Composition → Component Rendering. Props flow from parent components through the component tree, where each Tremor component receives standard React props plus variant-specific props. The cx utility merges these classes with default styles, tailwind-variants generates conditional CSS based on variant props, and the final className is passed to either a native DOM element or a Radix UI primitive. Radix primitives handle accessibility features while Tremor adds consistent visual design. This pipeline design keeps the data transformation process straightforward.

What technologies does tremor use?

The core stack includes Radix UI (Provides unstyled, accessible component primitives that Tremor wraps with its design system), Tailwind CSS (CSS utility framework used for all component styling through class composition), tailwind-variants (Generates conditional CSS classes based on component props - handles variant logic and type safety), tailwind-merge (Deduplicates and resolves precedence conflicts between Tailwind CSS classes), clsx (Conditionally applies CSS classes based on boolean logic and object notation), Storybook (Development environment for building and documenting components in isolation), and 2 more. A focused set of dependencies that keeps the build manageable.

What system dynamics does tremor have?

tremor exhibits 2 data pools (Variant Registry, Utility Cache), 3 control points, 2 delays. These runtime behaviors shape how the system responds to load, failures, and configuration changes.

What design patterns does tremor use?

4 design patterns detected: Radix Primitive Wrapping, Variant-Driven Styling, Forward Ref Pattern, Slot Composition.

Analyzed on April 20, 2026 by CodeSea. Written by .