Klass

Class variant utility library

README


hiiiits

klass


Introduction


Class variant utility

Features


- Base and variants
- Compound variants
- Conditional variants
- Framework-agnostic
- TypeScript support
- Styled-component-like API (React, Preact & Solid)
- Polymorphic components (React, Preact & Solid)

Roadmap


- [x] Variants
- [x] Compound variants
- [x] Conditional variants
- [x] Group
- [x] Slots

Examples


Core


  1. ```tsx
  2. import { klass, reklass } from "@klass/core";

  3. const button = klass({
  4.   base: "inline-flex items-center justify-center rounded-md outline-none",
  5.   variants: {
  6.     color: {
  7.       default: "bg-neutral-700 text-white",
  8.       primary: "bg-indigo-700 text-white",
  9.       secondary: "bg-orange-700 text-white",
  10.     },
  11.     size: {
  12.       sm: "px-3 py-0.5 h-7 text-sm font-medium",
  13.       md: "px-4 py-1 h-8 text-base font-medium",
  14.       lg: "px-5 py-1.5 h-9 text-lg font-semibold",
  15.     },
  16.     block: {
  17.       true: "w-full",
  18.     },
  19.     // "class" variant are not allowed
  20.   },
  21.   defaultVariants: {
  22.     color: "default",
  23.     size: "md",
  24.   },
  25. });

  26. const box = reklass({
  27.   conditions: {
  28.     base: "",
  29.     sm: "sm:",
  30.     md: "md:",
  31.     lg: "lg:",
  32.     xl: "xl:",
  33.     "2xl": "2xl:",
  34.   },
  35.   defaultCondition: "base",
  36.   variants: {
  37.     m: {
  38.       "0": "m-0",
  39.       "1": "m-1",
  40.       "2": "m-2",
  41.       "3": "m-3",
  42.       "4": "m-4",
  43.       "5": "m-5",
  44.       "6": "m-6",
  45.       "7": "m-7",
  46.       "8": "m-8",
  47.     },
  48.     p: {
  49.       "0": "p-0",
  50.       "1": "p-1",
  51.       "2": "p-2",
  52.       "3": "p-3",
  53.       "4": "p-4",
  54.       "5": "p-5",
  55.       "6": "p-6",
  56.       "7": "p-7",
  57.       "8": "p-8",
  58.     },
  59.   },
  60. });

  61. button({ color: "primary", block: true }); // "inline-flex items-center justify-center rounded-md outline-none bg-indigo-700 text-white px-4 py-1 h-8 text-base font-medium w-full"
  62. // access variant
  63. button.v.color("primary"); // "bg-indigo-700 text-white"

  64. box({ m: "1", p: "2" }); // "m-1 p-1"
  65. box({ m: { base: "1", md: "2" }, p: { base: "1", md: "2" } }); // "m-1 md:m-2 p-1 md:p-2"
  66. // access revariant
  67. box.rv.m("1"); // "m-1";
  68. box.rv.p({ base: "1", md: "2" }); // "p-1 md:p-2"
  69. ```

Preact / React / Solid


  1. ```tsx
  2. import { klassed, reklassed } from "@klass/{preact,react,solid}";

  3. const Button = klassed(
  4.   "button",
  5.   {
  6.     base: "inline-flex items-center justify-center rounded-md outline-none",
  7.     variants: {
  8.       color: {
  9.         default: "bg-neutral-700 text-white",
  10.         primary: "bg-indigo-700 text-white",
  11.         secondary: "bg-orange-700 text-white",
  12.       },
  13.       size: {
  14.         sm: "px-3 py-0.5 h-7 text-sm font-medium",
  15.         md: "px-4 py-1 h-8 text-base font-medium",
  16.         lg: "px-5 py-1.5 h-9 text-lg font-semibold",
  17.       },
  18.       block: {
  19.         true: "w-full",
  20.       },
  21.     },
  22.     defaultVariants: {
  23.       color: "default",
  24.       size: "md",
  25.     },
  26.   },
  27.   {
  28.     // default props
  29.     dp: {
  30.       type: "button",
  31.     },
  32.   }
  33. );

  34. const Box = reklassed("div", {
  35.   conditions: {
  36.     base: "",
  37.     sm: "sm:",
  38.     md: "md:",
  39.     lg: "lg:",
  40.     xl: "xl:",
  41.     "2xl": "2xl:",
  42.   },
  43.   defaultCondition: "base",
  44.   variants: {
  45.     m: {
  46.       "0": "m-0",
  47.       "1": "m-1",
  48.       "2": "m-2",
  49.       "3": "m-3",
  50.       "4": "m-4",
  51.       "5": "m-5",
  52.       "6": "m-6",
  53.       "7": "m-7",
  54.       "8": "m-8",
  55.     },
  56.     p: {
  57.       "0": "p-0",
  58.       "1": "p-1",
  59.       "2": "p-2",
  60.       "3": "p-3",
  61.       "4": "p-4",
  62.       "5": "p-5",
  63.       "6": "p-6",
  64.       "7": "p-7",
  65.       "8": "p-8",
  66.     },
  67.   },
  68. });

  69. const App = () => {
  70.   return (
  71.     <Box m={{ base: "1", md: "2" }} p="2">
  72.       <Box as="section">
  73.         <Button color="primary" block>
  74.           Primary Block Button
  75.         </Button>
  76.       </Box>

  77.       <Box as="section">
  78.         <Button as="a" color="secondary">
  79.           Secondary Anchor Button
  80.         </Button>
  81.       </Box>
  82.     </Box>
  83.   );
  84. };

  85. export default App;
  86. ```

Inspiration


Some of the core concepts and designs are inspired by

- cva