A set of tools to manage inline styles on React elements with support for pseudo-classes, media queries, and keyframe animations.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Extensible plugin architecture that allows customization of Radium's style processing behavior through a modular system of processing functions.
Plugins are functions that process style objects and return modifications to component props, styles, or global state.
/**
* Plugin function interface
* @param config - Plugin configuration object with utilities and current state
* @returns Plugin result with optional modifications to component
*/
interface Plugin {
(config: PluginConfig): PluginResult | void;
}
interface PluginConfig {
/** Component name (may not be available if minified) */
componentName: string;
/** Current Radium configuration */
config: RadiumConfig;
/** Current element props (can be modified by previous plugins) */
props: object;
/** Current element style (can be modified by previous plugins) */
style: object;
// Utility functions
/** Add CSS to global stylesheet */
addCSS: (css: string) => { remove: () => void };
/** Add !important to all values in style object */
appendImportantToEachValue: (style: object) => object;
/** Convert CSS rules object to string */
cssRuleSetToString: (selector: string, rules: object, userAgent?: string) => string;
/** Get component field value */
getComponentField: (key: string) => any;
/** Get global state value */
getGlobalState: (key: string) => any;
/** Get element state (hover, focus, active) */
getState: (stateKey: string, elementKey?: string) => any;
/** Generate hash from string */
hash: (data: string) => string;
/** Check if value is nested style object */
isNestedStyle: (value: any) => boolean;
/** Merge array of style objects */
mergeStyles: (styles: object[]) => object;
/** Set component state */
setState: (stateKey: string, value: any, elementKey?: string) => void;
/** Environment detection utilities */
ExecutionEnvironment: {
canUseEventListeners: boolean;
canUseDOM: boolean;
};
}
interface PluginResult {
/** Fields to merge into component instance */
componentFields?: object;
/** Values to merge into global state */
globalState?: object;
/** Props to merge into element */
props?: object;
/** Style object to replace current style */
style?: object;
}Radium includes a comprehensive set of built-in plugins that handle core functionality.
interface BuiltinPlugins {
/** Validates style properties and detects common issues */
checkProps: Plugin;
/** Processes keyframe animation objects */
keyframes: Plugin;
/** Merges arrays of style objects intelligently */
mergeStyleArray: Plugin;
/** Adds vendor prefixes to CSS properties */
prefix: Plugin;
/** Extracts nested style objects for processing */
removeNestedStyles: Plugin;
/** Handles :hover, :focus, :active pseudo-classes */
resolveInteractionStyles: Plugin;
/** Processes @media query styles */
resolveMediaQueries: Plugin;
/** Handles :visited pseudo-class styles */
visited: Plugin;
}Usage Examples:
import Radium from 'radium';
// Access built-in plugins
const { Plugins } = Radium;
// Default plugin order
const defaultPlugins = [
Plugins.mergeStyleArray,
Plugins.checkProps,
Plugins.resolveMediaQueries,
Plugins.resolveInteractionStyles,
Plugins.keyframes,
Plugins.visited,
Plugins.removeNestedStyles,
Plugins.prefix,
Plugins.checkProps // Run again after processing
];Create custom plugins to extend Radium's functionality.
Usage Examples:
// Simple logging plugin
function loggingPlugin({ componentName, style }) {
console.log(`Styling component: ${componentName}`, style);
// Return nothing - no modifications
}
// Style transformation plugin
function uppercaseTextPlugin({ style }) {
if (style.textTransform === 'uppercase-all') {
return {
style: {
...style,
textTransform: 'uppercase',
fontWeight: 'bold',
letterSpacing: '1px'
}
};
}
}
// Plugin that adds CSS to global stylesheet
function globalStylesPlugin({ addCSS, hash }) {
const css = `
.custom-utility {
display: flex;
align-items: center;
justify-content: center;
}
`;
const id = hash(css);
if (!document.getElementById(id)) {
const { remove } = addCSS(css);
// Store remove function if needed later
}
}
// Use custom plugins
const MyComponent = Radium({
plugins: [
Plugins.mergeStyleArray,
loggingPlugin,
uppercaseTextPlugin,
Plugins.checkProps,
Plugins.resolveMediaQueries,
Plugins.resolveInteractionStyles,
globalStylesPlugin,
Plugins.prefix,
Plugins.checkProps
]
})(BaseComponent);Plugins are executed in the order they appear in the configuration array. Each plugin receives the result of previous plugins.
Usage Examples:
// Plugin execution order matters
const orderedPlugins = [
// 1. First, merge style arrays
Plugins.mergeStyleArray,
// 2. Validate initial styles
Plugins.checkProps,
// 3. Process special style objects that create new styles
Plugins.resolveMediaQueries,
Plugins.resolveInteractionStyles,
Plugins.keyframes,
Plugins.visited,
// 4. Extract nested styles
Plugins.removeNestedStyles,
// 5. Add vendor prefixes
Plugins.prefix,
// 6. Final validation
Plugins.checkProps
];Guidelines for developing custom plugins.
/**
* Plugin development template
*/
function customPlugin({
componentName,
config,
props,
style,
addCSS,
getState,
setState,
isNestedStyle,
mergeStyles
}) {
// 1. Check if plugin should run
if (!shouldProcessStyle(style)) {
return; // No modifications
}
// 2. Process style object
const processedStyle = processStyle(style);
// 3. Add any necessary CSS
if (needsGlobalCSS(processedStyle)) {
addCSS(generateCSS(processedStyle));
}
// 4. Return modifications
return {
style: processedStyle,
props: {
...props,
'data-processed': true
}
};
}Usage Examples:
// Responsive utilities plugin
function responsiveUtilitiesPlugin({ style, addCSS, hash }) {
const responsiveProps = ['responsiveWidth', 'responsiveHeight'];
const hasResponsiveProps = responsiveProps.some(prop => style[prop]);
if (!hasResponsiveProps) return;
const newStyle = { ...style };
if (style.responsiveWidth) {
const breakpoints = style.responsiveWidth;
Object.keys(breakpoints).forEach(breakpoint => {
const css = `
@media (min-width: ${breakpoint}) {
.responsive-width-${hash(breakpoint)} {
width: ${breakpoints[breakpoint]};
}
}
`;
addCSS(css);
});
newStyle.className = `responsive-width-${hash(JSON.stringify(breakpoints))}`;
delete newStyle.responsiveWidth;
}
return { style: newStyle };
}Plugins can be configured globally or per-component.
Usage Examples:
// Global plugin configuration
const GlobalRadium = Radium({
plugins: [
...Radium.Plugins,
customPlugin
]
});
// Per-component configuration
const SpecialComponent = Radium({
plugins: [
Plugins.mergeStyleArray,
specialComponentPlugin,
Plugins.prefix
]
})(BaseComponent);
// Runtime configuration via props
<MyComponent
radiumConfig={{
plugins: [...customPlugins]
}}
/>Intelligently merges arrays of style objects with deep merging for nested styles.
interface MergeStyleArrayPlugin {
/** Processes style arrays into single style object */
(config: PluginConfig): PluginResult;
}Validates style properties and usage patterns, warning about common issues.
interface CheckPropsPlugin {
/** Validates style objects and usage patterns */
(config: PluginConfig): void;
}Processes @media query styles and applies them based on current media conditions.
interface ResolveMediaQueriesPlugin {
/** Processes @media query styles */
(config: PluginConfig): PluginResult;
}Handles :hover, :focus, and :active pseudo-class styles by setting up event listeners.
interface ResolveInteractionStylesPlugin {
/** Handles pseudo-class styles */
(config: PluginConfig): PluginResult;
}Adds vendor prefixes to CSS properties and values based on browser detection.
interface PrefixPlugin {
/** Adds vendor prefixes to styles */
(config: PluginConfig): PluginResult;
}interface Plugin {
(config: PluginConfig): PluginResult | void;
}
interface PluginConfig {
componentName: string;
config: RadiumConfig;
props: object;
style: object;
addCSS: (css: string) => { remove: () => void };
appendImportantToEachValue: (style: object) => object;
cssRuleSetToString: (selector: string, rules: object, userAgent?: string) => string;
getComponentField: (key: string) => any;
getGlobalState: (key: string) => any;
getState: (stateKey: string, elementKey?: string) => any;
hash: (data: string) => string;
isNestedStyle: (value: any) => boolean;
mergeStyles: (styles: object[]) => object;
setState: (stateKey: string, value: any, elementKey?: string) => void;
ExecutionEnvironment: {
canUseEventListeners: boolean;
canUseDOM: boolean;
};
}
interface PluginResult {
componentFields?: object;
globalState?: object;
props?: object;
style?: object;
}Install with Tessl CLI
npx tessl i tessl/npm-radium