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.
Components
300+
↑ Carbon + extensions
3WCAG Compliance
AA
✓ Fully accessible
ABundle size
42kb
Tree-shaken
kGitHub 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.
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.
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.
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.
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.
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.
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
| 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
# 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
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> ) }
// 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 }, }
'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> }
'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> )}</> ) }
'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> ) }