JSS integration with React providing CSS-in-JS styling solutions with theming support
—
The Higher-Order Component (HOC) API provides the classic React pattern for injecting styles into components as a classes prop. This approach is ideal for class components and when following traditional HOC patterns.
Creates a higher-order component that injects styles as a classes prop into the wrapped component.
/**
* Creates a higher-order component that injects styles as classes prop
* @param styles - JSS styles object or function that returns styles
* @param options - Configuration options for the HOC
* @returns HOC function that wraps components with injected styles
*/
function withStyles<ClassNames extends string | number | symbol, Props, Theme>(
styles: Styles<ClassNames, Props, Theme> | ((theme: Theme) => Styles<ClassNames, Props, undefined>),
options?: WithStylesOptions
): <C>(component: C) => ComponentType<
JSX.LibraryManagedAttributes<
C,
Omit<GetProps<C>, 'classes'> & {
classes?: Partial<ClassesForStyles<typeof styles>>;
innerRef?: RefObject<any> | ((instance: any) => void);
}
>
>;
interface WithStylesOptions extends BaseOptions {
/** Whether to inject theme as a prop to the wrapped component */
injectTheme?: boolean;
/** Custom JSS instance to use for this component */
jss?: Jss;
}Usage Examples:
import React from 'react';
import { withStyles } from 'react-jss';
// Static styles
const styles = {
button: {
padding: '10px 20px',
backgroundColor: '#007bff',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
'&:hover': {
backgroundColor: '#0056b3'
}
}
};
// Class component usage
class MyButton extends React.Component {
render() {
const { classes, children, ...props } = this.props;
return (
<button className={classes.button} {...props}>
{children}
</button>
);
}
}
const StyledButton = withStyles(styles)(MyButton);
// Functional component usage
const MyFunctionalButton = ({ classes, children, ...props }) => (
<button className={classes.button} {...props}>
{children}
</button>
);
const StyledFunctionalButton = withStyles(styles)(MyFunctionalButton);Using function-based styles that respond to theme and props:
import React from 'react';
import { withStyles, ThemeProvider } from 'react-jss';
const dynamicStyles = (theme) => ({
container: {
padding: '20px',
backgroundColor: theme.backgroundColor,
color: theme.textColor,
borderRadius: theme.borderRadius
},
title: {
fontSize: (props) => props.large ? '24px' : '18px',
fontWeight: theme.fontWeight.bold,
marginBottom: '16px'
}
});
const MyComponent = ({ classes, title, children }) => (
<div className={classes.container}>
<h2 className={classes.title}>{title}</h2>
{children}
</div>
);
const StyledComponent = withStyles(dynamicStyles)(MyComponent);
// Usage with theme
const theme = {
backgroundColor: '#f5f5f5',
textColor: '#333',
borderRadius: '8px',
fontWeight: {
bold: 600
}
};
function App() {
return (
<ThemeProvider theme={theme}>
<StyledComponent title="Hello" large>
Content here
</StyledComponent>
</ThemeProvider>
);
}Automatically inject theme as a prop to the wrapped component:
const styles = {
card: {
padding: '16px',
borderRadius: '8px',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
}
};
const Card = ({ classes, theme, children }) => (
<div
className={classes.card}
style={{ backgroundColor: theme.cardBackground }}
>
{children}
</div>
);
const StyledCard = withStyles(styles, { injectTheme: true })(Card);Components wrapped with withStyles accept a classes prop to override specific style classes:
const Button = withStyles({
root: {
padding: '10px',
backgroundColor: 'blue'
}
})(({ classes, children }) => (
<button className={classes.root}>{children}</button>
));
// Override specific classes
<Button classes={{ root: 'my-custom-button-class' }}>
Click me
</Button>Access the ref of the wrapped component using innerRef:
const Input = withStyles({
input: {
padding: '8px',
border: '1px solid #ccc'
}
})(React.forwardRef(({ classes, ...props }, ref) => (
<input className={classes.input} ref={ref} {...props} />
)));
function App() {
const inputRef = React.useRef();
const focusInput = () => {
inputRef.current?.focus();
};
return (
<div>
<Input innerRef={inputRef} />
<button onClick={focusInput}>Focus Input</button>
</div>
);
}interface WithStylesProps<S extends Styles<any, any, any> | ((theme: any) => Styles<any, any, undefined>)> {
/** Generated CSS class names object */
classes: ClassesForStyles<S>;
}
/** @deprecated Please use WithStylesProps instead */
type WithStyles<S extends Styles<any, any, any> | ((theme: any) => Styles<any, any, undefined>)> = WithStylesProps<S>;
type GetProps<C> = C extends ComponentType<infer P> ? P : never;Install with Tessl CLI
npx tessl i tessl/npm-react-jss