
Research
/Security News
Weaponizing Discord for Command and Control Across npm, PyPI, and RubyGems.org
Socket researchers uncover how threat actors weaponize Discord across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.
@consensys/ds3-theme
Advanced tools
> π§ **Note**: This package is under active development. While we're working hard to make it production-ready, please be aware that APIs and features may change. We welcome your feedback and contributions as we continue to improve!
π§ Note: This package is under active development. While we're working hard to make it production-ready, please be aware that APIs and features may change. We welcome your feedback and contributions as we continue to improve!
π¨ Complex theming made simple
Build sophisticated, dynamic themes with a comprehensive design system that includes colors, spacing, typography, shadows, and animations. Our color system handles nested themes, mode switching, and semantic color mapping with ease.
π¨ Flexible Color System - Three ways to define colors:
π― Design Token System - Complete set of pre-configured tokens for colors, spacing, typography, shadows, and animations
π¨ Tailwind Classes - Use familiar Tailwind classes with our pre-configured design tokens
π Mode Switching - Toggle between light and dark modes with simple class changes
π Theme Switching - Switch between different themes (default, oceanBreeze, etc.) with class combinations
π Nested Themes - Create complex theme hierarchies with parent-child relationships and inheritance
π¨ Dynamic Inheritance - Child themes inherit from parent themes while maintaining their own overrides
β‘ Dynamic CSS Variables - Runtime theme customization with smooth transitions and real-time updates
pnpm add @consensys/ds3-theme
// tailwind.config.js
import { tailwindPreset } from '@consensys/ds3-theme';
export default {
presets: [tailwindPreset({
themes: {
// Choose colors from Radix UI color palettes
// See: https://www.radix-ui.com/colors
default: {
colors: {
neutral: 'gray',
primary: 'blue',
secondary: 'violet',
error: 'red',
warning: 'amber',
success: 'green',
info: 'blue',
}
}
}
})],
};
<!-- Recommended: Apply theme to the HTML element -->
<html class="light">
<body>
<button class="bg-primary hover:bg-primary-7 text-white px-4 py-2 rounded">
Click me
</button>
</body>
</html>
<!-- Alternative: Apply theme to any element -->
<div class="dark">
<button class="bg-primary hover:bg-primary-7 text-white px-4 py-2 rounded">
Click me
</button>
</div>
Before diving into the different ways to define colors, it's important to understand how colors are mapped to semantic roles in your UI:
Semantic colors help maintain consistency and meaning across your application. Instead of using colors directly (like blue
or red
), semantic colors describe the purpose of the color (like primary
or error
). This makes it easier to:
Here's how colors are mapped to semantic roles in your UI:
Semantic Color | Purpose | Default Mapping |
---|---|---|
neutral | Base UI elements, text, borders | gray |
primary | Main actions, brand identity | blue |
secondary | Alternative actions, accents | violet |
error | Error states, destructive actions | red |
warning | Warning states, cautionary actions | amber |
success | Success states, positive actions | green |
info | Information states, neutral actions | blue |
π‘ Tip: While these are the recommended semantic colors, you can use any semantic name that makes sense for your application. For example, you might use
brand
,accent
, orsurface
instead of or in addition to these defaults.
The theme system supports three ways to define colors:
Use pre-defined Radix UI Colors palettes for consistent, accessible colors:
// tailwind.config.js
import { tailwindPreset } from '@consensys/ds3-theme';
export default {
presets: [tailwindPreset({
themes: {
default: {
colors: {
neutral: 'gray',
primary: 'blue',
secondary: 'violet',
error: 'red',
warning: 'amber',
success: 'green',
info: 'blue',
}
}
}
})],
};
Generate custom color scales with semantic mapping using the Radix UI Colors Custom algorithm:
// tailwind.config.js
import { tailwindPreset } from '@consensys/ds3-theme';
export default {
presets: [tailwindPreset({
themes: {
default: {
colors: {
// Minimal configuration - just accent color
primary: {
accent: '#FF3366' // Required: Base accent color
},
// Light/dark mode accent colors
secondary: {
accent: { // Required: Base accent colors
light: '#0066FF',
dark: '#0033CC'
}
},
// Complete configuration
tertiary: {
accent: '#FF3366', // Required: Base accent color
gray: '#8B8D98', // Optional: Gray scale color
background: { // Optional: Background colors
light: '#FFFFFF',
dark: '#000000'
}
}
}
}
}
})],
};
Create fully customizable color scales with any valid CSS color:
// tailwind.config.js
import { tailwindPreset } from '@consensys/ds3-theme';
export default {
presets: [tailwindPreset({
themes: {
default: {
colors: {
primary: {
light: {
// Any valid CSS color string is supported
'cardBg': '#FF3366',
'overlay': 'rgba(0, 0, 0, 0.5)',
'gradient': 'linear-gradient(to right, #FF3366, #0066FF)',
// Numeric keys are supported
1: '#E6F7FF',
2: '#BAE7FF',
// Alpha variants with any key
a1: 'rgba(24, 144, 255, 0.05)',
a13: 'rgba(24, 144, 255, 0.13)',
a100: 'rgba(24, 144, 255, 0.1)'
},
dark: {
// Dark mode is optional
'primary': '#001A4D',
// ...
}
}
}
}
}
})],
};
π‘ Tip: If you don't specify dark mode colors, the system will automatically use the light mode colors for dark mode. This is useful when you want to maintain the same color scheme across both modes or when you're just getting started with theming.
π‘ Tip: You can mix and match all three color configuration types within a single theme to create the perfect color system for your needs.
Create custom themes by mapping semantic colors to different Radix colors:
// tailwind.config.js
import { tailwindPreset } from '@consensys/ds3-theme';
export default {
presets: [tailwindPreset({
themes: {
// Default theme
default: {
colors: {
neutral: 'gray',
primary: 'blue',
secondary: 'violet',
error: 'red',
warning: 'amber',
success: 'green',
info: 'blue',
}
},
// Custom theme
oceanBreeze: {
colors: {
neutral: 'slate', // Cooler neutral tone
primary: 'cyan', // Ocean-inspired primary
secondary: 'blue', // Complementary blue
error: 'red', // Keep error consistent
warning: 'amber', // Keep warning consistent
success: 'grass', // Natural success color
info: 'blue', // Match secondary
}
}
}
})],
};
Then use your custom theme with the appropriate mode class:
<!-- Ocean Breeze theme in light mode -->
<html class="oceanBreeze light">
<body>
<button class="bg-primary hover:bg-primary-7 text-white">
Ocean Breeze Button
</button>
<p class="text-primary-11">Text using primary color</p>
<div class="bg-primary-a5">Semi-transparent background</div>
</body>
</html>
Create different theme zones within your application:
<!-- Root theme (default) -->
<html class="light">
<body>
<!-- Main content with default theme -->
<main>
<button class="bg-primary">Default Theme Button</button>
</main>
<!-- Force this button to dark mode -->
<div class="dark">
<button class="bg-primary">Ocean Breeze Dark Button</button>
</div>
<!-- Nested Ocean Breeze theme -->
<div class="oceanBreeze dark">
<button class="bg-primary">Sunset Theme Light Button</button>
</div>
</body>
</html>
π‘ Note: You can specify just the theme name (e.g.,
oceanBreeze
) and it will inherit the parent's mode, or you can override the mode by specifying both theme and mode (e.g.,oceanBreeze dark
).
The theme package provides a complete set of design tokens through the Tailwind preset. These tokens are carefully crafted to work together and maintain consistency across your application:
// tailwind.config.js
import { tailwindPreset } from '@consensys/ds3-theme';
export default {
presets: [tailwindPreset({
themes: {
// Your theme configuration
}
})],
};
The preset includes:
For detailed configuration options, see the Tailwind preset source.
The theme system processes your configuration in three simple steps:
Read Configuration
Generate CSS Variables The system processes your theme configuration in three steps:
addBase
pluginThis process enables Tailwind to generate utility classes that reference these CSS variables, making them available throughout your application. For example:
bg-primary-1
β Sets background to the lightest primary colortext-neutral-11
β Sets text to a dark neutral colorborder-error-6
β Sets border to a medium error colorbg-primary-a5
β Sets background to a semi-transparent primary colorThe CSS variables below are what makes this possible - they're injected into the runtime environment and automatically update when switching themes or modes. This means your Tailwind utility classes will automatically adapt to the current theme and mode:
/* Light mode (default theme) */
.light {
--color-neutral-1: var(--radix-gray-1);
--color-neutral-a1: var(--radix-gray-a1); /* Alpha variant for transparency */
--color-primary-1: var(--radix-blue-1);
--color-primary-a1: var(--radix-blue-a1); /* Alpha variant for transparency */
/* ... */
}
/* Dark mode (default theme) */
.dark {
--color-neutral-1: var(--radix-gray-dark-1);
--color-neutral-a1: var(--radix-gray-dark-a1); /* Alpha variant for transparency */
--color-primary-1: var(--radix-blue-dark-1);
--color-primary-a1: var(--radix-blue-dark-a1); /* Alpha variant for transparency */
/* ... */
}
/* Light mode (ocean breeze theme) */
.oceanBreeze.light {
--color-neutral-1: var(--radix-slate-1);
--color-neutral-a1: var(--radix-slate-a1); /* Alpha variant for transparency */
--color-primary-1: var(--radix-cyan-1);
--color-primary-a1: var(--radix-cyan-a1); /* Alpha variant for transparency */
/* ... */
}
/* Dark mode (ocean breeze theme) */
.oceanBreeze.dark {
--color-neutral-1: var(--radix-slate-dark-1);
--color-neutral-a1: var(--radix-slate-dark-a1); /* Alpha variant for transparency */
--color-primary-1: var(--radix-cyan-dark-1);
--color-primary-a1: var(--radix-cyan-dark-a1); /* Alpha variant for transparency */
/* ... */
}
<!-- Default theme in light mode -->
<div class="light">
<!-- Using base colors -->
<div class="bg-primary-1">Lightest primary color</div>
<div class="text-neutral-1">Lightest neutral color</div>
<!-- Using alpha variants -->
<div class="bg-primary-a1">Semi-transparent primary color</div>
<div class="text-neutral-a1">Semi-transparent neutral color</div>
</div>
<!-- Ocean Breeze theme in light mode -->
<div class="oceanBreeze light">
<div class="bg-primary-1">Ocean Breeze lightest primary</div>
<div class="bg-primary-a1">Ocean Breeze transparent primary</div>
</div>
<!-- Nested themes example -->
<div class="light">
<div class="bg-primary-1">Default theme</div>
<!-- Ocean Breeze theme in dark mode -->
<div class="oceanBreeze dark">
<div class="bg-primary-1">Nested Ocean Breeze theme</div>
</div>
</div>
When switching themes or modes, the system updates CSS variables in real-time:
// Example of theme switching
document.documentElement.classList.remove('light');
document.documentElement.classList.add('dark');
// Or switching to a custom theme
document.documentElement.classList.remove('default');
document.documentElement.classList.add('oceanBreeze');
The CSS variables update automatically, maintaining all color relationships and semantic mappings.
You can customize theme variables at runtime:
// Example of runtime color adjustment
document.documentElement.style.setProperty('--color-primary-6', '#custom-color');
// Or adjusting alpha values
document.documentElement.style.setProperty('--color-primary-a6', 'rgba(0, 0, 0, 0.5)');
To enable smooth transitions between theme changes, add transition properties to your CSS:
/* Add to your global CSS */
:root {
--theme-transition-duration: 200ms;
}
* {
transition: background-color var(--theme-transition-duration) ease,
color var(--theme-transition-duration) ease,
border-color var(--theme-transition-duration) ease;
}
This creates a smooth experience when switching between themes or modes.
The theme package provides several utility functions that you can use directly in your code:
import { generateRadixColors, getColorScaleObject } from '@consensys/ds3-theme';
// Generate a complete color scale from a base color
const colors = generateRadixColors({
appearance: 'light', // or 'dark'
accent: '#3D63DD', // Your brand color
gray: '#8B8D98', // Your neutral color
background: '#FFFFFF' // Your background color
});
// Convert the generated colors into a usable color scale object
const colorScale = getColorScaleObject({
isDarkMode: false,
name: 'blue',
contrast: colors.accentContrast,
scale: colors.accentScale,
scaleWideGamut: colors.accentScaleWideGamut,
scaleAlpha: colors.accentScaleAlpha,
scaleAlphaWideGamut: colors.accentScaleAlphaWideGamut,
surface: colors.accentSurface,
surfaceWideGamut: colors.accentSurfaceWideGamut,
});
The generated color scale includes:
Contributions welcome!
MIT License - Copyright (c) 2025 ConsenSys Inc
FAQs
> π§ **Note**: This package is under active development. While we're working hard to make it production-ready, please be aware that APIs and features may change. We welcome your feedback and contributions as we continue to improve!
The npm package @consensys/ds3-theme receives a total of 0 weekly downloads. As such, @consensys/ds3-theme popularity was classified as not popular.
We found that @consensys/ds3-theme demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Β It has 17 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
/Security News
Socket researchers uncover how threat actors weaponize Discord across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.
Security News
Socket now integrates with Bun 1.3βs Security Scanner API to block risky packages at install time and enforce your organizationβs policies in local dev and CI.
Research
The Socket Threat Research Team is tracking weekly intrusions into the npm registry that follow a repeatable adversarial playbook used by North Korean state-sponsored actors.