{"id":13990795,"url":"https://github.com/slicknode/stylemapper","last_synced_at":"2025-04-09T08:08:46.338Z","repository":{"id":57818897,"uuid":"521942147","full_name":"slicknode/stylemapper","owner":"slicknode","description":"Flexible utility to create styled and type-safe React components","archived":false,"fork":false,"pushed_at":"2022-10-25T12:36:28.000Z","size":432,"stargazers_count":141,"open_issues_count":1,"forks_count":1,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-04-02T07:09:52.412Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/slicknode.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-08-06T12:35:21.000Z","updated_at":"2024-12-13T06:07:30.000Z","dependencies_parsed_at":"2023-01-20T12:06:06.334Z","dependency_job_id":null,"html_url":"https://github.com/slicknode/stylemapper","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slicknode%2Fstylemapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slicknode%2Fstylemapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slicknode%2Fstylemapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slicknode%2Fstylemapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/slicknode","download_url":"https://codeload.github.com/slicknode/stylemapper/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247999860,"owners_count":21031046,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-09T13:03:15.584Z","updated_at":"2025-04-09T08:08:46.315Z","avatar_url":"https://github.com/slicknode.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# Slicknode Stylemapper\n\n[![npm version](https://badge.fury.io/js/@slicknode%2Fstylemapper.svg)](https://www.npmjs.com/package/@slicknode/stylemapper)\n[![Build passing](https://github.com/slicknode/stylemapper/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/slicknode/stylemapper/actions/workflows/main.yml)\n[![Test Coverage](https://badgen.net/codecov/c/github/slicknode/stylemapper)](https://app.codecov.io/github/slicknode/stylemapper)\n[![License](https://badgen.net/github/license/slicknode/stylemapper)](https://github.com/slicknode/stylemapper/blob/main/LICENSE)\n[![Dependency Count](https://badgen.net/bundlephobia/dependency-count/@slicknode/stylemapper)](https://www.npmjs.com/package/@slicknode/stylemapper)\n[![Types included](https://badgen.net/npm/types/@slicknode/stylemapper)](https://www.npmjs.com/package/@slicknode/stylemapper)\n\nEasily create styled, strictly typed React components and simplify your component code.\n\nStylemapper 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:\n\n- Get **strictly typed components** without writing Typescript prop type definitions (Stylemapper infers types automatically)\n- Automatically create **variant props** without complicating your component code (success/error, large/medium etc.)\n- **Add styles to 3rd party libraries** without manually creating wrapper components, type definitions, etc.\n- Have a **single source of truth for your styles** instead of spreading classnames all over your React components\n\nWorks especially great with utility based CSS frameworks like [Tailwind CSS](https://tailwindcss.com/).\n\n## Installation\n\nAdd Slicknode Stylemapper as a dependency to your project:\n\n    npm install --save @slicknode/stylemapper\n\n## Usage\n\nImport the `styled` utility function and create styled components. Examples are using [Tailwind CSS](https://tailwindcss.com/) utility classes.\n\n### Basic Example\n\n```ts\nimport { styled } from '@slicknode/stylemapper';\n\n// Create styled components with CSS classes\nconst Menu = styled('ul', 'space-x-2 flex');\nconst MenuItem = styled('li', 'w-9 h-9 flex items-center justify-center');\n\n// Then use the components in your app\nconst App = () =\u003e {\n  return (\n    \u003cMenu\u003e\n      \u003cMenuItem\u003eHome\u003c/MenuItem\u003e\n      \u003cMenuItem\u003eProduct\u003c/MenuItem\u003e\n      \u003cMenuItem\u003eSignup Now\u003c/MenuItem\u003e\n    \u003c/Menu\u003e\n  );\n};\n```\n\n### Variants\n\nCreate variants by passing a configuration object. Stylemapper automatically infers the correct prop type definitions and passes the resulting `className` prop to the component:\n\n```ts\nconst Button = styled('button', {\n  variants: {\n    intent: {\n      neutral: 'bg-slate-300 border border-slate-500',\n      danger: 'bg-red-300 border border-red-500',\n      success: 'bg-green-300 border border-green-500',\n    },\n    size: {\n      small: 'p-2',\n      medium: 'p-4',\n      large: 'p-8',\n    },\n    // Add any number of variants...\n  },\n  // Optionally set default variant values\n  defaultVariants: {\n    intent: 'neutral',\n    size: 'medium',\n  },\n});\n\nconst App = () =\u003e {\n  return (\n    \u003cButton intent={'danger'} size={'large'}\u003e\n      Delete Account\n    \u003c/Button\u003e\n  );\n};\n```\n\n### Compound Variants\n\nIf you only want to add class names to a component if multiple props have particular values, you can configure `compountVariants`:\n\n```ts\nconst Button = styled('button', {\n  variants: {\n    intent: {\n      danger: 'bg-red-300',\n      success: 'bg-green-300',\n    },\n    outline: {\n      true: 'border',\n      false: '',\n    },\n    // Add any number of variants...\n  },\n  compoundVariants: [\n    {\n      intent: 'success',\n      outline: true,\n      className: 'border-green-500',\n    },\n    {\n      intent: 'danger',\n      outline: true,\n      className: 'border-red-500',\n    },\n  ],\n});\n\nconst App = () =\u003e {\n  return (\n    \u003cButton intent={'danger'} outline\u003e\n      Delete Account\n    \u003c/Button\u003e\n  );\n};\n```\n\n### Custom Components\n\nStylemapper 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:\n\n```ts\nconst CustomComponent = ({ className }) =\u003e {\n  return (\n    // Make sure you add the className from the props to the DOM node\n    \u003cdiv className={className}\u003eMy custom react component\u003c/div\u003e\n  );\n};\n\nconst StyledCustomComponent = styled(CustomComponent, {\n  variants: {\n    intent: {\n      danger: 'bg-red-300 border border-red-500',\n      success: 'bg-green-300 border border-green-500',\n    },\n  },\n});\n\n// Extending styled components\nconst SizedComponent = styled(StyledCustomComponent, {\n  variants: {\n    size: {\n      small: 'p-2',\n      medium: 'p-4',\n      large: 'p-8',\n    },\n  },\n});\n\nconst App = () =\u003e {\n  return (\n    \u003cSizedComponent intent=\"danger\" size=\"large\"\u003e\n      Large error message\n    \u003c/SizedComponent\u003e\n  );\n};\n```\n\n### Variant Type Casting\n\nYou can define `boolean` and `numeric` variant values. The type definition for the resulting prop is automatically inferred:\n\n```ts\nconst StyledComponent = styled('div', {\n  variants: {\n    selected: {\n      true: 'bg-red-300 border border-red-500',\n      false: 'bg-green-300 border border-green-500',\n    },\n    size: {\n      1: 'p-2'\n      2: 'p-4'\n      3: 'p-8'\n    }\n  },\n});\n\nconst App = () =\u003e (\n  // This component now expects a boolean and a number value as props\n  \u003cStyledComponent selected={true} size={2}/\u003e\n);\n```\n\n### Prop Forwarding\n\nBy 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:\n\n```ts\nconst CustomComponent = ({ open, className }) =\u003e {\n  return (\n    \u003cdiv className={className}\u003eComponent is {open ? 'open' : 'closed'}\u003c/div\u003e\n  );\n};\n\nconst StyledComponent = styled('div', {\n  variants: {\n    selected: {\n      true: 'bg-red-300 border border-red-500',\n      false: 'bg-green-300 border border-green-500',\n    },\n  },\n  forwardProps: ['selected'],\n});\n```\n\n### Composing Configurations\n\nYou 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:\n\n```ts\nimport { intentVariants, sizeVariants } from './shared';\nconst StyledComponent = styled(\n  'div',\n\n  // Add some base styles that are added every time\n  'p-2 flex gap-2',\n\n  // Add imported variants\n  intentVariants,\n  sizeVariants,\n\n  // Add other custom variants\n  {\n    selected: {\n      true: 'border border-green-500',\n      false: 'border border-green-100',\n    },\n  }\n);\n```\n\n### IntelliSense for Tailwind CSS\n\nIf 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):\n\n```json\n{\n  \"tailwindCSS.experimental.classRegex\": [\n    [\"styled\\\\(([^)]*)\\\\)\", \"[\\\"'`]([^\\\"'`]*).*?[\\\"'`]\"]\n  ]\n}\n```\n\n## Credits\n\nThis 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.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslicknode%2Fstylemapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fslicknode%2Fstylemapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslicknode%2Fstylemapper/lists"}