https://github.com/slicknode/stylemapper
Flexible utility to create styled and type-safe React components
https://github.com/slicknode/stylemapper
Last synced: 3 months ago
JSON representation
Flexible utility to create styled and type-safe React components
- Host: GitHub
- URL: https://github.com/slicknode/stylemapper
- Owner: slicknode
- License: mit
- Created: 2022-08-06T12:35:21.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2022-10-25T12:36:28.000Z (over 2 years ago)
- Last Synced: 2025-04-02T07:09:52.412Z (3 months ago)
- Language: TypeScript
- Size: 422 KB
- Stars: 141
- Watchers: 5
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Slicknode Stylemapper
[](https://www.npmjs.com/package/@slicknode/stylemapper)
[](https://github.com/slicknode/stylemapper/actions/workflows/main.yml)
[](https://app.codecov.io/github/slicknode/stylemapper)
[](https://github.com/slicknode/stylemapper/blob/main/LICENSE)
[](https://www.npmjs.com/package/@slicknode/stylemapper)
[](https://www.npmjs.com/package/@slicknode/stylemapper)Easily create styled, strictly typed React components and simplify your component code.
Stylemapper is a small, flexible and zero-dependency utility to **add CSS classes to React components**. It eliminates the boilerplate you usually need for changing styles based on state, define typescript definitions, etc. This simplifies the creation and maintenance of your style and design system:
- Get **strictly typed components** without writing Typescript prop type definitions (Stylemapper infers types automatically)
- Automatically create **variant props** without complicating your component code (success/error, large/medium etc.)
- **Add styles to 3rd party libraries** without manually creating wrapper components, type definitions, etc.
- Have a **single source of truth for your styles** instead of spreading classnames all over your React componentsWorks especially great with utility based CSS frameworks like [Tailwind CSS](https://tailwindcss.com/).
## Installation
Add Slicknode Stylemapper as a dependency to your project:
npm install --save @slicknode/stylemapper
## Usage
Import the `styled` utility function and create styled components. Examples are using [Tailwind CSS](https://tailwindcss.com/) utility classes.
### Basic Example
```ts
import { styled } from '@slicknode/stylemapper';// Create styled components with CSS classes
const Menu = styled('ul', 'space-x-2 flex');
const MenuItem = styled('li', 'w-9 h-9 flex items-center justify-center');// Then use the components in your app
const App = () => {
return (
Home
Product
Signup Now
);
};
```### Variants
Create variants by passing a configuration object. Stylemapper automatically infers the correct prop type definitions and passes the resulting `className` prop to the component:
```ts
const Button = styled('button', {
variants: {
intent: {
neutral: 'bg-slate-300 border border-slate-500',
danger: 'bg-red-300 border border-red-500',
success: 'bg-green-300 border border-green-500',
},
size: {
small: 'p-2',
medium: 'p-4',
large: 'p-8',
},
// Add any number of variants...
},
// Optionally set default variant values
defaultVariants: {
intent: 'neutral',
size: 'medium',
},
});const App = () => {
return (
Delete Account
);
};
```### Compound Variants
If you only want to add class names to a component if multiple props have particular values, you can configure `compountVariants`:
```ts
const Button = styled('button', {
variants: {
intent: {
danger: 'bg-red-300',
success: 'bg-green-300',
},
outline: {
true: 'border',
false: '',
},
// Add any number of variants...
},
compoundVariants: [
{
intent: 'success',
outline: true,
className: 'border-green-500',
},
{
intent: 'danger',
outline: true,
className: 'border-red-500',
},
],
});const App = () => {
return (
Delete Account
);
};
```### Custom Components
Stylemapper works with any React component, as long as the component has a `className` prop. This makes it easy to add styles to your own components or to UI libraries like [Headless UI](https://headlessui.com/), [Radix UI](https://www.radix-ui.com/) and [Reach UI](https://reach.tech/). Just pass in the component as a first argument:
```ts
const CustomComponent = ({ className }) => {
return (
// Make sure you add the className from the props to the DOM node
My custom react component
);
};const StyledCustomComponent = styled(CustomComponent, {
variants: {
intent: {
danger: 'bg-red-300 border border-red-500',
success: 'bg-green-300 border border-green-500',
},
},
});// Extending styled components
const SizedComponent = styled(StyledCustomComponent, {
variants: {
size: {
small: 'p-2',
medium: 'p-4',
large: 'p-8',
},
},
});const App = () => {
return (
Large error message
);
};
```### Variant Type Casting
You can define `boolean` and `numeric` variant values. The type definition for the resulting prop is automatically inferred:
```ts
const StyledComponent = styled('div', {
variants: {
selected: {
true: 'bg-red-300 border border-red-500',
false: 'bg-green-300 border border-green-500',
},
size: {
1: 'p-2'
2: 'p-4'
3: 'p-8'
}
},
});const App = () => (
// This component now expects a boolean and a number value as props
);
```### Prop Forwarding
By default, variant props are **not** passed to the wrapped component to prevent invalid props to be attached to DOM nodes. If you need the values of variants inside of your custom components, specify them in the configuration:
```ts
const CustomComponent = ({ open, className }) => {
return (
Component is {open ? 'open' : 'closed'}
);
};const StyledComponent = styled('div', {
variants: {
selected: {
true: 'bg-red-300 border border-red-500',
false: 'bg-green-300 border border-green-500',
},
},
forwardProps: ['selected'],
});
```### Composing Configurations
You can pass any number of configurations to the `styled` function. This allows you to reuse styles and variants across components. Pass either a string with class names or a configuration object as input values:
```ts
import { intentVariants, sizeVariants } from './shared';
const StyledComponent = styled(
'div',// Add some base styles that are added every time
'p-2 flex gap-2',// Add imported variants
intentVariants,
sizeVariants,// Add other custom variants
{
selected: {
true: 'border border-green-500',
false: 'border border-green-100',
},
}
);
```### IntelliSense for Tailwind CSS
If you are using the offical [TailwindCSS extension for VSCode](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss), you can enable intellisense for style mapper by updating your [settings](https://code.visualstudio.com/docs/getstarted/settings):
```json
{
"tailwindCSS.experimental.classRegex": [
["styled\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"]
]
}
```## Credits
This library is heavily inspired by [Stitches](https://stitches.dev/), a great CSS in Javascript library. Stylemapper brings a similar API to utility based CSS frameworks without requiring a specific library.