npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@slicknode/stylemapper

v0.1.5

Published

Flexible utility to create styled and type-safe React components

Downloads

2,182

Readme

Slicknode Stylemapper

npm version Build passing Test Coverage License Dependency Count Types included

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 components

Works especially great with utility based CSS frameworks like Tailwind CSS.

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 utility classes.

Basic Example

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 (
    <Menu>
      <MenuItem>Home</MenuItem>
      <MenuItem>Product</MenuItem>
      <MenuItem>Signup Now</MenuItem>
    </Menu>
  );
};

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:

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 (
    <Button intent={'danger'} size={'large'}>
      Delete Account
    </Button>
  );
};

Compound Variants

If you only want to add class names to a component if multiple props have particular values, you can configure compountVariants:

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 (
    <Button intent={'danger'} outline>
      Delete Account
    </Button>
  );
};

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, Radix UI and Reach UI. Just pass in the component as a first argument:

const CustomComponent = ({ className }) => {
  return (
    // Make sure you add the className from the props to the DOM node
    <div className={className}>My custom react component</div>
  );
};

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 (
    <SizedComponent intent="danger" size="large">
      Large error message
    </SizedComponent>
  );
};

Variant Type Casting

You can define boolean and numeric variant values. The type definition for the resulting prop is automatically inferred:

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
  <StyledComponent selected={true} size={2}/>
);

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:

const CustomComponent = ({ open, className }) => {
  return (
    <div className={className}>Component is {open ? 'open' : 'closed'}</div>
  );
};

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:

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, you can enable intellisense for style mapper by updating your settings:

{
  "tailwindCSS.experimental.classRegex": [
    ["styled\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"]
  ]
}

Credits

This library is heavily inspired by Stitches, a great CSS in Javascript library. Stylemapper brings a similar API to utility based CSS frameworks without requiring a specific library.