Theme provider, CSS customization, and utility hooks for adapting Carbon components to your brand and design requirements.
Global theme management with support for Carbon's built-in themes and custom theme creation.
/**
* Global theme provider for Carbon components
*/
interface ThemeProps {
/** Theme variant to apply */
theme?: "white" | "g10" | "g90" | "g100" | string;
/** Components to theme */
children: React.ReactNode;
/** CSS class name */
className?: string;
}
/**
* Global theme provider with extended options
*/
interface GlobalThemeProps {
/** Theme variant */
theme?: "white" | "g10" | "g90" | "g100" | string;
/** Global theme children */
children: React.ReactNode;
}Usage Examples:
import { Theme, GlobalTheme } from "@carbon/react";
// Basic theme provider
<Theme theme="g90">
<App />
</Theme>
// Global theme (affects entire document)
<GlobalTheme theme="g10">
<App />
</GlobalTheme>
// Theme switching
function ThemeSwitcher() {
const [currentTheme, setCurrentTheme] = useState("white");
return (
<Theme theme={currentTheme}>
<div>
<select
value={currentTheme}
onChange={(e) => setCurrentTheme(e.target.value)}
>
<option value="white">White (Light)</option>
<option value="g10">Gray 10 (Light)</option>
<option value="g90">Gray 90 (Dark)</option>
<option value="g100">Gray 100 (Dark)</option>
</select>
<MyApplication />
</div>
</Theme>
);
}
// Custom theme integration
<Theme theme="custom-brand-theme">
<App />
</Theme>Layer context system for proper nested component styling and visual hierarchy.
/**
* Layer context provider for nested styling
*/
interface LayerProps {
/** Layer children */
children: React.ReactNode;
/** Layer level (0-2) for visual hierarchy */
level?: 0 | 1 | 2;
/** CSS class name */
className?: string;
}Usage Examples:
import { Layer, Tile, Button } from "@carbon/react";
// Layer hierarchy for visual depth
<div>
{/* Base layer (level 0) */}
<Tile>
<h2>Main Content</h2>
<p>This is the base layer content.</p>
<Layer level={1}>
{/* First nested layer */}
<Tile>
<h3>Nested Panel</h3>
<p>This content is on layer 1.</p>
<Layer level={2}>
{/* Second nested layer */}
<Tile>
<h4>Deep Nested Content</h4>
<p>This is the deepest nested layer (level 2).</p>
<Button>Action</Button>
</Tile>
</Layer>
</Tile>
</Layer>
</Tile>
</div>
// Modal with proper layering
<Modal open={isOpen}>
<Layer>
<h2>Modal Title</h2>
<p>Modal content on proper layer.</p>
<Layer level={1}>
<Tile>Nested content in modal</Tile>
</Layer>
</Layer>
</Modal>Utility hooks and components for managing CSS class prefixes and unique IDs.
/**
* CSS class prefix hook
* @returns Current CSS class prefix
*/
function usePrefix(): string;
/**
* ID prefix hook for unique identifier generation
* @returns Current ID prefix
*/
function useIdPrefix(): string;
/**
* Class prefix provider
*/
interface ClassPrefixProps {
/** CSS class prefix */
prefix: string;
/** Children to apply prefix to */
children: React.ReactNode;
}
/**
* ID prefix provider
*/
interface IdPrefixProps {
/** ID prefix */
prefix: string;
/** Children to apply prefix to */
children: React.ReactNode;
}Usage Examples:
import {
usePrefix,
useIdPrefix,
ClassPrefix,
IdPrefix
} from "@carbon/react";
// Using prefix hooks in custom components
function MyCustomComponent() {
const prefix = usePrefix();
const idPrefix = useIdPrefix();
return (
<div className={`${prefix}--my-component`}>
<input id={`${idPrefix}--my-input`} />
<label htmlFor={`${idPrefix}--my-input`}>Custom Input</label>
</div>
);
}
// Custom prefix providers
<ClassPrefix prefix="my-brand">
<IdPrefix prefix="my-app">
<App />
</IdPrefix>
</ClassPrefix>
// Using hooks to maintain consistency
function CustomCard({ title, children }) {
const prefix = usePrefix();
const idPrefix = useIdPrefix();
const titleId = `${idPrefix}--card-title-${Math.random()}`;
return (
<div
className={`${prefix}--card`}
aria-labelledby={titleId}
>
<h3 id={titleId} className={`${prefix}--card__title`}>
{title}
</h3>
<div className={`${prefix}--card__content`}>
{children}
</div>
</div>
);
}Sass/SCSS integration patterns and CSS variable usage for advanced styling.
/**
* SCSS import pattern for Carbon styles
*/
interface CarbonSCSSImports {
/** Import all Carbon styles */
all: "@carbon/react/scss/index.scss";
/** Import specific component styles */
component: "@carbon/react/scss/components/[component]/index.scss";
/** Import theme tokens */
tokens: "@carbon/styles/scss/theme";
/** Import layout utilities */
layout: "@carbon/styles/scss/layout";
/** Import motion tokens */
motion: "@carbon/styles/scss/motion";
/** Import spacing tokens */
spacing: "@carbon/styles/scss/spacing";
/** Import type utilities */
type: "@carbon/styles/scss/type";
}SCSS Usage Examples:
// Import all Carbon styles
@use "@carbon/react/scss/index.scss";
// Import specific components
@use "@carbon/react/scss/components/button";
@use "@carbon/react/scss/components/text-input";
// Import design tokens
@use "@carbon/styles/scss/theme" as *;
@use "@carbon/styles/scss/spacing" as *;
@use "@carbon/styles/scss/type" as *;
// Custom component with Carbon tokens
.my-custom-component {
background: $background;
color: $text-primary;
padding: $spacing-05;
border-radius: $spacing-02;
// Use Carbon type styles
@include type-style('body-02');
&:hover {
background: $background-hover;
}
}
// Theme-aware custom styles
.my-themed-component {
// Light theme styles
@include theme($theme: $white) {
border: 1px solid $border-subtle-01;
}
// Dark theme styles
@include theme($theme: $g90) {
border: 1px solid $border-subtle-01;
}
}
// Responsive design with Carbon breakpoints
@use "@carbon/styles/scss/breakpoint" as *;
.responsive-component {
padding: $spacing-03;
@include breakpoint(md) {
padding: $spacing-05;
}
@include breakpoint(lg) {
padding: $spacing-07;
}
}CSS custom property usage for runtime theme customization.
/* CSS Custom Properties for theming */
.custom-theme {
/* Override Carbon color tokens */
--cds-background: #f8f9fa;
--cds-text-primary: #1a1a1a;
--cds-interactive-01: #0066cc;
--cds-interactive-02: #6c757d;
/* Override spacing tokens */
--cds-spacing-05: 1rem;
--cds-spacing-06: 1.5rem;
/* Override typography tokens */
--cds-productive-heading-03-font-size: 1.25rem;
--cds-productive-heading-03-line-height: 1.4;
}
/* Component-specific theming */
.custom-button-theme {
--cds-button-primary: #ff6b35;
--cds-button-primary-hover: #e55a2b;
--cds-button-primary-active: #cc4e24;
}CSS Custom Property Usage:
import { Button, TextInput } from "@carbon/react";
// Apply custom theme via CSS classes
<div className="custom-theme">
<Button kind="primary">Custom themed button</Button>
<TextInput labelText="Custom themed input" />
</div>
// Inline CSS custom properties
<div
style={{
'--cds-interactive-01': '#ff6b35',
'--cds-interactive-02': '#6c757d'
}}
>
<Button kind="primary">Inline themed button</Button>
</div>Accessing Carbon design tokens programmatically for custom styling.
/**
* Carbon theme tokens (available as CSS custom properties)
*/
interface CarbonTokens {
// Color tokens
background: string;
"text-primary": string;
"text-secondary": string;
"interactive-01": string;
"interactive-02": string;
"interactive-03": string;
"interactive-04": string;
// Spacing tokens
"spacing-01": string; // 0.125rem
"spacing-02": string; // 0.25rem
"spacing-03": string; // 0.5rem
"spacing-04": string; // 0.75rem
"spacing-05": string; // 1rem
"spacing-06": string; // 1.5rem
"spacing-07": string; // 2rem
"spacing-08": string; // 2.5rem
"spacing-09": string; // 3rem
"spacing-10": string; // 4rem
"spacing-11": string; // 5rem
"spacing-12": string; // 6rem
// Layout tokens
"layout-01": string; // 1rem
"layout-02": string; // 1.5rem
"layout-03": string; // 2rem
"layout-04": string; // 3rem
"layout-05": string; // 4rem
"layout-06": string; // 6rem
"layout-07": string; // 10rem
}Accessing tokens in React:
// Using CSS custom properties in inline styles
function CustomComponent() {
return (
<div
style={{
backgroundColor: 'var(--cds-background)',
color: 'var(--cds-text-primary)',
padding: 'var(--cds-spacing-05)',
borderRadius: 'var(--cds-spacing-02)',
border: '1px solid var(--cds-border-subtle-01)'
}}
>
Custom styled component using Carbon tokens
</div>
);
}
// Using getComputedStyle to access tokens
function useThemeToken(tokenName: string) {
const [value, setValue] = useState('');
useEffect(() => {
const root = document.documentElement;
const computedValue = getComputedStyle(root)
.getPropertyValue(`--cds-${tokenName}`)
.trim();
setValue(computedValue);
}, [tokenName]);
return value;
}
// Using the hook
function ThemedComponent() {
const primaryColor = useThemeToken('interactive-01');
const spacing = useThemeToken('spacing-05');
return (
<div style={{ color: primaryColor, padding: spacing }}>
Dynamically themed content
</div>
);
}Responsive design utilities and breakpoint management.
/**
* Carbon breakpoints
*/
interface CarbonBreakpoints {
sm: "320px"; // Small
md: "672px"; // Medium
lg: "1056px"; // Large
xlg: "1312px"; // Extra large
max: "1584px"; // Maximum
}
/**
* Media query hook for responsive behavior
*/
function useMatchMedia(query: string): boolean;Breakpoint Usage:
import { useMatchMedia } from "@carbon/react";
// Responsive component behavior
function ResponsiveComponent() {
const isMobile = useMatchMedia('(max-width: 671px)');
const isTablet = useMatchMedia('(min-width: 672px) and (max-width: 1055px)');
const isDesktop = useMatchMedia('(min-width: 1056px)');
return (
<div>
{isMobile && <MobileLayout />}
{isTablet && <TabletLayout />}
{isDesktop && <DesktopLayout />}
</div>
);
}
// Responsive grid
function ResponsiveGrid() {
const isMobile = useMatchMedia('(max-width: 671px)');
return (
<Grid>
<Row>
<Column sm={4} md={8} lg={12}>
<h1>Responsive Content</h1>
</Column>
</Row>
<Row>
{isMobile ? (
// Mobile: Stack vertically
<>
<Column sm={4}><Card>Card 1</Card></Column>
<Column sm={4}><Card>Card 2</Card></Column>
<Column sm={4}><Card>Card 3</Card></Column>
</>
) : (
// Desktop: Side by side
<>
<Column md={2} lg={4}><Card>Card 1</Card></Column>
<Column md={3} lg={4}><Card>Card 2</Card></Column>
<Column md={3} lg={4}><Card>Card 3</Card></Column>
</>
)}
</Row>
</Grid>
);
}Motion token integration for consistent animations and transitions.
/**
* Carbon motion tokens
*/
interface CarbonMotion {
"duration-fast-01": "70ms";
"duration-fast-02": "110ms";
"duration-moderate-01": "150ms";
"duration-moderate-02": "240ms";
"duration-slow-01": "400ms";
"duration-slow-02": "700ms";
"easing-standard": "cubic-bezier(0.2, 0, 0.38, 0.9)";
"easing-entrance": "cubic-bezier(0, 0, 0.38, 0.9)";
"easing-exit": "cubic-bezier(0.2, 0, 1, 0.9)";
}Motion Usage:
/* Using motion tokens in CSS */
.custom-animation {
transition:
opacity var(--cds-duration-moderate-01) var(--cds-easing-standard),
transform var(--cds-duration-moderate-01) var(--cds-easing-standard);
}
.fade-in {
animation: fadeIn var(--cds-duration-moderate-02) var(--cds-easing-entrance);
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(1rem); }
to { opacity: 1; transform: translateY(0); }
}// Using motion tokens in React
function AnimatedComponent({ isVisible }) {
return (
<div
style={{
opacity: isVisible ? 1 : 0,
transform: isVisible ? 'translateY(0)' : 'translateY(1rem)',
transition: `
opacity var(--cds-duration-moderate-01) var(--cds-easing-standard),
transform var(--cds-duration-moderate-01) var(--cds-easing-standard)
`
}}
>
Animated content
</div>
);
}/**
* Carbon type styles available via SCSS mixins
*/
interface CarbonTypeStyles {
// Productive styles
"productive-heading-01": { fontSize: "14px", lineHeight: "18px" };
"productive-heading-02": { fontSize: "16px", lineHeight: "22px" };
"productive-heading-03": { fontSize: "20px", lineHeight: "26px" };
"productive-heading-04": { fontSize: "28px", lineHeight: "36px" };
"productive-heading-05": { fontSize: "32px", lineHeight: "40px" };
"productive-heading-06": { fontSize: "42px", lineHeight: "50px" };
"productive-heading-07": { fontSize: "54px", lineHeight: "64px" };
// Body styles
"body-01": { fontSize: "14px", lineHeight: "18px" };
"body-02": { fontSize: "16px", lineHeight: "22px" };
// Code styles
"code-01": { fontSize: "12px", lineHeight: "16px" };
"code-02": { fontSize: "14px", lineHeight: "20px" };
// Helper styles
"helper-text-01": { fontSize: "12px", lineHeight: "16px" };
"helper-text-02": { fontSize: "14px", lineHeight: "18px" };
// Label styles
"label-01": { fontSize: "12px", lineHeight: "16px" };
"label-02": { fontSize: "14px", lineHeight: "18px" };
}