{"id":15471001,"url":"https://github.com/jackardios/react-tailwind-variants","last_synced_at":"2025-07-29T15:40:09.983Z","repository":{"id":143350603,"uuid":"613886098","full_name":"Jackardios/react-tailwind-variants","owner":"Jackardios","description":"React Stitches-like variants API for tailwindcss classes","archived":false,"fork":false,"pushed_at":"2025-07-23T16:02:25.000Z","size":164,"stargazers_count":17,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-23T16:16:19.484Z","etag":null,"topics":["classnames","react","stitches","tailwind","tailwindcss","variants"],"latest_commit_sha":null,"homepage":"","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/Jackardios.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-14T13:20:17.000Z","updated_at":"2025-07-23T16:02:02.000Z","dependencies_parsed_at":null,"dependency_job_id":"a44a4efa-025d-4f65-940d-39d59b57458d","html_url":"https://github.com/Jackardios/react-tailwind-variants","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/Jackardios/react-tailwind-variants","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jackardios%2Freact-tailwind-variants","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jackardios%2Freact-tailwind-variants/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jackardios%2Freact-tailwind-variants/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jackardios%2Freact-tailwind-variants/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Jackardios","download_url":"https://codeload.github.com/Jackardios/react-tailwind-variants/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jackardios%2Freact-tailwind-variants/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267710031,"owners_count":24131933,"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","status":"online","status_checked_at":"2025-07-29T02:00:12.549Z","response_time":2574,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["classnames","react","stitches","tailwind","tailwindcss","variants"],"created_at":"2024-10-02T02:08:21.293Z","updated_at":"2025-07-29T15:40:09.952Z","avatar_url":"https://github.com/Jackardios.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React Tailwind Variants\n\n[![npm package][npm-img]][npm-url]\n[![npm bundle size][bundle-size-img]][bundle-size-url]\n[![Downloads][downloads-img]][downloads-url]\n\n`Stitches.js`-like API for creating composable components. You can define a single variant, multiple variants, and even compound variants which allow you to define classes based on a combination of variants.\n\nThis is a modified version of the [`classname-variants`](https://github.com/fgnass/classname-variants/)\n\n## Features\n\n- 📦 Lightweight\n- 📜 Fully type-safe\n- 💅🏼 Elegant [Stitches-like](https://github.com/stitchesjs/stitches) variants API\n- 🗑️ Automatic tailwindcss classes conflict resolution via [tailwind-merge](https://github.com/dcastil/tailwind-merge)\n- ♻️ Polymorphic components via [@radix-ui/slot](https://www.radix-ui.com/docs/primitives/utilities/slot)\n\n## Installation\n\n```bash\nnpm install tailwind-merge react-tailwind-variants\n```\n\n## Usage\n\n- [Basics](#basics)\n- [Boolean variants](#boolean-variants)\n- [Compound variants](#compound-variants)\n- [Default variants](#default-variants)\n- [Polymorphic components](#polymorphic-components)\n- [Composing components](#composing-components)\n- [Utilities](#utilities)\n  - [variants(config)](#variantsconfig)\n  - [variantProps(config)](#variantpropsconfig)\n  - [extractVariantsConfig(component)](#extractvariantsconfigcomponent)\n- [Typescript utilities](#typescript-utilities)\n  - [VariantsConfigOf\\\u003cComponent\\\u003e](#variantsconfigofcomponent)\n  - [VariantPropsOf\\\u003cComponent\\\u003e](#variantpropsofcomponent)\n- [Tailwind CSS IntelliSense](#tailwind-css-intellisense)\n\n### Basics\n\nLet's assume we want to build a button component with Tailwind CSS that comes in different sizes and colors.\n\nIt consists of some _base classes_ that are always present as well as some optional classes that need to be added depending on the desired _variants_.\n\n```tsx\nimport { styled } from 'react-tailwind-variants';\n\nconst Button = styled('button', {\n  base: 'rounded text-white',\n  variants: {\n    color: {\n      brand: 'bg-sky-500',\n      accent: 'bg-teal-500',\n    },\n    size: {\n      small: 'px-5 py-3 text-xs',\n      large: 'px-6 py-4 text-base',\n    },\n  },\n});\n```\n\nThe result is a react component:\n\n```tsx\n\u003cButton type=\"submit\" color=\"brand\" size=\"large\" className=\"px-8\"\u003e\n  Click me!\n\u003c/Button\u003e\n```\n\nComponent will be rendered as:\n\n```html\n\u003cbutton\n  type=\"submit\"\n  className=\"rounded text-white bg-sky-500 py-4 text-base px-8\"\n\u003e\n  Click me!\n\u003c/button\u003e\n```\n\nAs a value for classes, you can use a `\"string\"`, an `\"array\"` of strings, or `\"null\"`:\n\n```tsx\nimport { styled } from 'react-tailwind-variants';\n\nconst Button = styled('button', {\n  base: ['rounded', 'text-white'],\n  variants: {\n    color: {\n      none: null,\n      brand: 'bg-sky-500',\n      accent: 'bg-teal-500',\n    },\n  },\n});\n```\n\n---\n\n### Boolean variants\n\nVariants can be of type `boolean` by using `\"true\"` or/and `\"false\"` as the key:\n\n```tsx\nimport { styled } from 'react-tailwind-variants';\n\nconst Button = styled('button', {\n  base: 'text-white',\n  variants: {\n    rounded: {\n      true: 'rounded-full',\n    },\n  },\n});\n```\n\n---\n\n### Compound variants\n\nThe `compoundVariants` option can be used to apply class names based on a combination of other variants.\n\n```tsx\nimport { styled } from 'react-tailwind-variants';\n\nconst Button = styled('button', {\n  base: 'text-base'\n  variants: {\n    variant: {\n      none: null,\n      filled: 'bg-blue-500 text-white',\n      outlined: 'border border-blue-500 text-blue-500',\n      plain: 'bg-transparent text-blue-500',\n    },\n    size: {\n      sm: 'px-3 py-1.5'\n      md: 'px-4 py-2'\n      lg: 'px-6 py-3'\n    },\n  },\n  compoundVariants: [\n    {\n      variants: {\n        variant: ['filled', 'outlined'],\n        size: 'sm'\n      },\n      className: 'text-sm'\n    },\n    {\n      // `compoundVariants` className takes\n      // precedence over `variants`,\n      // so in this case the class `p-0`\n      // will override `padding` classes\n      variants: {\n        variant: 'none'\n      },\n      className: 'p-0'\n    },\n  ],\n});\n```\n\n```tsx\n\u003cButton variant=\"outlined\" size=\"sm\"\u003eOutlined button\u003c/Button\u003e\n\u003cButton variant=\"none\" size=\"sm\"\u003eUnstyled button\u003c/Button\u003e\n```\n\nwill be rendered as:\n\n```html\n\u003cbutton\n  class=\"text-base border border-blue-500 text-blue-500 px-3 py-1.5 text-sm\"\n\u003e\n  Outlined button\n\u003c/button\u003e\n\u003cbutton class=\"text-base p-0\"\u003eUnstyled button\u003c/button\u003e\n```\n\n---\n\n### Default variants\n\nThe `defaultVariants` option can be used to select a variant by default.\nAll non-boolean variants for which no default values are specified are required.\nIf no default value is specified for boolean options, it evaluates to \"false\"\n\nBelow is an example with a component that has a required `size` and an optional `color` variants\n\n```tsx\nimport { styled } from 'react-tailwind-variants';\n\nconst Button = styled('button', {\n  variants: {\n    color: {\n      brand: 'bg-sky-500',\n      accent: 'bg-teal-500',\n    },\n    size: {\n      small: 'px-5 py-3 text-xs',\n      large: 'px-6 py-4 text-base',\n    },\n    elevated: {\n      true: 'shadow',\n    },\n  },\n  defaultVariants: {\n    color: 'neutral',\n  },\n});\n```\n\n---\n\n### Polymorphic components\n\nIf you want to keep all the variants you have defined for a component but want to render a different HTML tag or a different custom component, you can use the `\"asChild\"` prop to do so:\n\n```tsx\nimport { styled } from 'react-tailwind-variants';\n\nconst Button = styled('button', {\n  base: 'rounded text-white',\n  variants: {\n    color: {\n      brand: 'bg-sky-500',\n      accent: 'bg-teal-500',\n    },\n    size: {\n      small: 'px-5 py-3 text-xs',\n      large: 'px-6 py-4 text-base',\n    },\n  },\n});\n```\n\n```tsx\n\u003cButton asChild color=\"brand\" size=\"large\"\u003e\n  \u003ca href=\"/test\" className=\"mt-4 mb-2\"\u003e\n    Button as link\n  \u003c/a\u003e\n\u003c/Button\u003e\n```\n\nwill be rendered as:\n\n```html\n\u003ca\n  href=\"/test\"\n  className=\"rounded text-white bg-sky-500 px-6 py-4 text-base mt-4 mb-2\"\n\u003e\n  Button as link\n\u003c/a\u003e\n```\n\n---\n\n### Composing components\n\nComposing one styled component into another.\n\n1. Components can be composed via the `styled` function.\n\n```tsx\nimport { styled } from 'react-tailwind-variants';\n\nconst BaseButton = styled('button', {\n  base: 'text-center bg-blue-500 text-white',\n  variants: {\n    size: {\n      small: 'px-5 py-3 text-xs',\n      large: 'px-6 py-4 text-base',\n    },\n  },\n});\n\nconst Button = styled(BaseButton, {\n  base: 'rounded text-white',\n  variants: {\n    color: {\n      brand: 'bg-sky-500',\n      accent: 'bg-teal-500',\n    },\n  },\n});\n```\n\n```tsx\n\u003cButton type=\"submit\" color=\"brand\" size=\"large\"\u003e\n  Click me!\n\u003c/Button\u003e\n```\n\nwill be rendered as:\n\n```html\n\u003cbutton\n  type=\"submit\"\n  className=\"text-center text-white px-6 py-4 text-base rounded text-white bg-sky-500\"\n\u003e\n  Click me!\n\u003c/button\u003e\n```\n\n2. You can also achieve the same result using `\"asChild\"` prop:\n\n```tsx\nimport { styled } from 'react-tailwind-variants';\n\nconst BaseButton = styled('button', {\n  base: 'text-center bg-blue-500 text-white',\n  variants: {\n    size: {\n      small: 'px-5 py-3 text-xs',\n      large: 'px-6 py-4 text-base',\n    },\n  },\n});\n\nconst Button = styled('button', {\n  base: 'rounded text-white',\n  variants: {\n    color: {\n      brand: 'bg-sky-500',\n      accent: 'bg-teal-500',\n    },\n  },\n});\n```\n\n```tsx\n\u003cBaseButton asChild size=\"large\"\u003e\n  \u003cButton type=\"submit\" color=\"brand\"\u003e\n    Click me!\n  \u003c/Button\u003e\n\u003c/Button\u003e\n```\n\nwill be rendered as:\n\n```html\n\u003cbutton\n  type=\"submit\"\n  className=\"text-center text-white px-6 py-4 text-base rounded text-white bg-sky-500\"\n\u003e\n  Click me!\n\u003c/button\u003e\n```\n\n---\n\n### Utilities\n\n#### `variants(config)`\n\nThe function accepts variants config as argument and returns a `className` builder function\n\n```ts\nimport { variants } from 'react-tailwind-variants';\n\nconst buttonVariants = variants({\n  base: 'rounded text-white',\n  variants: {\n    color: {\n      brand: 'bg-sky-500',\n      accent: 'bg-teal-500',\n    },\n    size: {\n      small: 'px-5 py-3 text-xs',\n      large: 'px-6 py-4 text-base',\n    },\n  },\n});\n\nconsole.log(\n  buttonVariants({\n    color: 'brand',\n    size: 'small',\n    className: 'text-sky-900 px-8',\n  })\n);\n// Console output:\n// 'rounded bg-sky-500 py-3 text-xs text-sky-900 px-8'\n```\n\n#### `variantProps(config)`\n\nThe function accepts variants config as argument and returns props builder function\n\n```ts\nimport { variantProps } from 'react-tailwind-variants';\n\nconst buttonVariantProps = variantProps({\n  base: 'rounded text-white',\n  variants: {\n    color: {\n      brand: 'bg-sky-500',\n      accent: 'bg-teal-500',\n    },\n    size: {\n      small: 'px-5 py-3 text-xs',\n      large: 'px-6 py-4 text-base',\n    },\n  },\n});\n\nconsole.log(\n  buttonVariantProps({\n    color: 'brand',\n    size: 'small',\n    className: 'text-sky-900 px-8',\n    type: 'button',\n    onClick: e =\u003e {\n      // ...\n    },\n  })\n);\n// Console output:\n// {\n//   className: 'rounded bg-sky-500 py-3 text-xs text-sky-900 px-8'\n//   type: \"button\",\n//   onClick: ...\n// }\n```\n\n#### `extractVariantsConfig(component)`\n\nThe function accepts a component from which it extracts the configuration of variants\n\n```ts\nimport { styled, extractVariantsConfig } from 'react-tailwind-variants';\n\nconst Button = styled('button', {\n  base: ['rounded', 'text-white'],\n  variants: {\n    color: {\n      none: null,\n      brand: 'bg-sky-500',\n      accent: 'bg-teal-500',\n    },\n  },\n});\n\nconsole.log(extractVariantsConfig(Button));\n// Console output:\n// {\n//   base: ['rounded', 'text-white'],\n//   variants: {\n//     color: {\n//       none: null,\n//       brand: 'bg-sky-500',\n//       accent: 'bg-teal-500',\n//     },\n//   },\n// }\n```\n\n### Typescript utilities\n\n#### `VariantsConfigOf\u003cComponent\u003e`\n\nA utility that allows you to extract the configuration type from the component type\n\n```ts\nimport { type VariantsConfigOf, styled } from 'react-tailwind-variants';\n\nconst Button = styled('button', {\n  base: ['rounded', 'text-white'],\n  variants: {\n    color: {\n      none: null,\n      brand: 'bg-sky-500',\n      accent: 'bg-teal-500',\n    },\n  },\n});\n\ntype ButtonVariantsConfig = VariantsConfigOf\u003ctypeof Button\u003e;\n```\n\n#### `VariantPropsOf\u003cComponent\u003e`\n\nA utility that allows you to extract the variant props type from the component type\n\n```ts\nimport { type VariantPropsOf, styled } from 'react-tailwind-variants';\n\nconst Button = styled('button', {\n  base: ['rounded', 'text-white'],\n  variants: {\n    color: {\n      none: null,\n      brand: 'bg-sky-500',\n      accent: 'bg-teal-500',\n    },\n  },\n});\n\ntype ButtonVariantProps = VariantPropsOf\u003ctypeof Button\u003e;\n```\n\n### Tailwind CSS IntelliSense\n\nIn order to get auto-completion for the CSS classes themselves, you can use the [Tailwind CSS IntelliSense](https://github.com/tailwindlabs/tailwindcss-intellisense) plugin for VS Code. In order to make it recognize the strings inside your variants-config, you have to somehow mark them and configure the plugin accordingly.\n\nOne way of doing so is by using tagged template literals:\n\n```ts\nimport { styled, tw } from 'react-tailwind-variants';\n\nconst Button = styled('button', {\n  base: tw`px-5 py-2 text-white`,\n  variants: {\n    color: {\n      neutral: tw`bg-slate-500 hover:bg-slate-400`,\n      accent: tw`bg-teal-500 hover:bg-teal-400`,\n    },\n  },\n});\n```\n\nYou can then add the following line to your `settings.json`:\n\n```\n\"tailwindCSS.experimental.classRegex\": [\"tw`(\\\\`|[^`]+?)`\"]\n```\n\n\u003e **Note**\n\u003e The `tw` helper function is just an alias for [`String.raw`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/raw).\n\n[npm-img]: https://img.shields.io/npm/v/react-tailwind-variants\n[npm-url]: https://www.npmjs.com/package/react-tailwind-variants\n[bundle-size-img]: https://img.shields.io/bundlephobia/minzip/react-tailwind-variants\n[bundle-size-url]: https://bundlephobia.com/package/react-tailwind-variants\n[downloads-img]: https://img.shields.io/npm/dt/react-tailwind-variants\n[downloads-url]: https://www.npmtrends.com/react-tailwind-variants\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjackardios%2Freact-tailwind-variants","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjackardios%2Freact-tailwind-variants","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjackardios%2Freact-tailwind-variants/lists"}