Ultimate Carbon Stack

IBM Carbon · Ultimate Stack · White Theme · React Spring · v11

Production-ready
design system stack

A complete, enterprise-grade frontend architecture built on IBM Carbon — now with React Spring physics animations. Four animation packages: @react-spring/web, useTransition, useChain, and @use-gesture/react.

Foundation
Components
3
Animations
4
Data Layer
5
Deploy

Components

300+

↑ Carbon + extensions

3

WCAG Compliance

AA

✓ Fully accessible

A

Bundle size

42kb

Tree-shaken

k

GitHub stars

7.7k

↑ Active community

Stack layers

Layer 01 · Core

IBM Carbon

Base design system

300+ accessible, production-ready components. Design tokens, theming, WCAG AA, full Figma kit. The non-negotiable foundation.

@carbon/react @carbon/tokens @carbon/icons

Layer 02 · Styling

SASS + CSS Tokens

Theming engine

Carbon's SASS system with design tokens for all colors, spacing, motion, and type. White/Gray 10/Dark themes out of the box.

sass css custom properties theming

Layer 03 · Animation

React Spring

Physics motion layer

Physics-based spring animations for Carbon. No durations — springs settle naturally, mirroring Carbon's "lightweight material" motion philosophy. Four packages cover every animation need.

@react-spring/web useTransition useChain @use-gesture/react

Layer 04 · Data Viz

Carbon Charts

Visualization

IBM's own charting library, fully Carbon-themed. Bar, line, scatter, donut, geo maps. Accessible, responsive, framework-ready.

@carbon/charts-react D3 recharts alt

Layer 05 · State

Zustand

State management

Lightweight global state. Pairs perfectly with Carbon's controlled components. No boilerplate, or use Redux Toolkit for enterprise scale.

zustand immer redux-toolkit (alt)

Layer 06 · Framework

Next.js 14+

App framework

App Router, RSC, server actions. Carbon components work seamlessly with Next.js client components. ISR and edge-ready.

next.js app router RSC

Notification patterns

carbon · inline notifications

Stack configured

All Carbon layers installed and ready. Run npm run dev to start.

Accessibility passed

WCAG 2.1 AA compliance verified across all components.

Peer dependency warning

React 18 required for Carbon v11. Update if on React 17.

Build failed

SASS compilation error in _overrides.scss — check line 42.

carbon · form inputs

carbon · toggles & settings

Light mode

White theme active

Animations

React Spring enabled

Analytics

Event tracking

Accessibility audit

axe-core in dev mode

Data table

Packages — Carbon Stack
Package Version Layer Status Weekly DLs
@carbon/react v1.73 Core Active
@react-spring/web v9.x Animation Active
useTransition built-in Animation Active
useChain built-in Animation Active
@use-gesture/react v10.x Gesture Optional
@carbon/charts-react v1.x Data Viz Active
zustand v4.x State Pending
next v14.x Framework Active

Setup code

bash · install all layers
# 1. Create Next.js app
npx create-next-app@latest my-carbon-app --typescript --tailwind=false

# 2. Install Carbon core + icons + tokens
npm install @carbon/react @carbon/icons-react @carbon/tokens sass

# 3. Install React Spring animation layer (all four packages)
npm install @react-spring/web
npm install @use-gesture/react     # optional: drag/scroll gestures

# 4. Install Carbon charts for data viz
npm install @carbon/charts-react @carbon/charts d3

# 5. Install state management
npm install zustand immer
tsx · app/layout.tsx
import '@carbon/react/scss/globals/scss/styles.scss'  // Carbon base
import '@carbon/charts/styles.css'                // Carbon charts
import { Theme } from '@carbon/react'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {/* Carbon white = light theme */}
        <Theme theme="white">
          {children}
        </Theme>
      </body>
    </html>
  )
}
ts · lib/springs.ts — shared spring configs
// Map Carbon's two motion modes to React Spring physics
export const carbonSprings = {
  // Productive — fast, task-focused, no bounce
  productive: { tension: 300, friction: 30, mass: 0.8 },
  // Expressive — noticeable, smooth, for page moments
  expressive: { tension: 180, friction: 26, mass: 1 },
  // Micro — instant, tight, button/icon feedback
  micro:      { tension: 500, friction: 40, mass: 0.5 },
}
tsx · useSpring — animated Carbon modal
'use client'
import { animated, useSpring } from '@react-spring/web'
import { carbonSprings } from '@/lib/springs'

export function AnimatedPanel({ open }: { open: boolean }) {
  const spring = useSpring({
    opacity:   open ? 1 : 0,
    transform: open ? 'translateX(0px)' : 'translateX(32px)',
    config: carbonSprings.expressive,
  })
  return <animated.div style={spring}>{/* Carbon panel content */}</animated.div>
}
tsx · useTransition — notification stack enter/leave
'use client'
import { animated, useTransition } from '@react-spring/web'
import { InlineNotification } from '@carbon/react'
import { carbonSprings } from '@/lib/springs'

export function NotificationStack({ items }: { items: string[] }) {
  const transitions = useTransition(items, {
    from:  { opacity: 0, height: 0, transform: 'translateY(-8px)' },
    enter: { opacity: 1, height: 48, transform: 'translateY(0px)' },
    leave: { opacity: 0, height: 0, transform: 'translateY(-8px)' },
    config: carbonSprings.productive,
  })
  return (
    <>{transitions((style, item) =>
      <animated.div style={style}>
        <InlineNotification kind="info" title={item} />
      </animated.div>
    )}</>
  )
}
tsx · useChain + useGesture — stagger + drag
'use client'
import { animated, useTrail, useChain, useSpringRef } from '@react-spring/web'
import { useDrag } from '@use-gesture/react'
import { Tile } from '@carbon/react'

const tiles = ['Revenue', 'Users', 'Uptime', 'Errors']

export function DashboardTiles() {
  const trailRef = useSpringRef()
  const trail = useTrail(tiles.length, {
    ref: trailRef,
    from: { opacity: 0, y: 16 },
    to:   { opacity: 1, y: 0  },
  })
  // useChain sequences: trail starts at t=0, next anim at t=0.5
  useChain([trailRef], [0])

  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: 1 }}>
      {trail.map((style, i) => (
        <animated.div key={tiles[i]} style={style}>
          <Tile>{tiles[i]}</Tile>
        </animated.div>
      ))}
    </div>
  )
}