tremorlabs/tremor

Copy & Paste React components to build modern web applications.

3,383 stars TypeScript 8 components

11 hidden assumptions · 4-stage pipeline · 8 components

Like any codebase, this library makes assumptions it never checks — most are routine. The ones worth your attention are below.

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.

Hidden Assumptions

Most of what this code assumes is routine. These 3 are the ones most likely to cause trouble here. The rest are minor; they're under "Show everything".

Worth your attention first

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

Worth your attention first

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

Worth your attention first

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

Show everything (8 more)
Shape

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
Contract

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
Environment

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
Domain

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
Scale

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
Resource

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
Contract

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
Temporal

Button component imports RiLoader2Fill icon but doesn't use it in the shown code, suggesting loading state functionality exists but isn't validated against icon availability

If this fails: If the Remix Icon library is missing or the specific icon is removed in future versions, loading states may render broken icons or crash during icon rendering

src/components/Button/Button.tsx:RiLoader2Fill

Open the standalone hidden-assumptions report for tremor →

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

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 .