diff --git a/pages/docs/api-reference.mdx b/pages/docs/api-reference.mdx index fad6600..671b16a 100644 --- a/pages/docs/api-reference.mdx +++ b/pages/docs/api-reference.mdx @@ -151,6 +151,7 @@ type TVOptions = { slots?: Record; variants?: Record>; defaultVariants?: Record; + requiredVariants?: string[]; compoundVariants?: Array & ClassProp>; compoundSlots?: Array & ClassProp>; }; @@ -205,6 +206,16 @@ To learn more about variants and how to use them, check out the [Variants](/docs To learn more about default variants and how to use them, check out the [Default Variants](/docs/variants#default-variants) page. +#### `requiredVariants` + +**description:** This property allows you to define which variants must be provided at both runtime and TypeScript level. + +**type:** `string[]` | `undefined` + +**default**: `undefined` + +To learn more about required variants and how to use them, check out the [Required Variants](/docs/variants#required-variants) page. + #### `compoundVariants` **description:** This property allows you to define the compound variants for the component. diff --git a/pages/docs/typescript.mdx b/pages/docs/typescript.mdx index a5d5175..bc65508 100644 --- a/pages/docs/typescript.mdx +++ b/pages/docs/typescript.mdx @@ -55,58 +55,3 @@ export const Button = (props: ButtonProps) => { return ; }; ``` - -### Required variants - -**Tailwind Variants** doesn't offer a way to make variants required yet, but you can use TypeScript's [Utility Types](https://www.typescriptlang.org/docs/handbook/utility-types.html) to achieve this. - -```tsx copy /VariantProps/ -import { tv, type VariantProps } from 'tailwind-variants' - -const buttonStyles = tv({ - base: "px-4 py-1.5 rounded-full hover:opacity-80", - variants: { - color: { - primary: "bg-blue-500 text-white", - neutral: "bg-zinc-500 text-black dark:text-white", - }, - requiredFlat: { - true: "bg-transparent", - false: "bg-white", - }, - }, - defaultVariants: { - color: "primary", - }, - compoundVariants: [...], -}); - -/** - * Result: - * color?: "primary" | "neutral" - * flat?: boolean - */ -type ButtonVariants = VariantProps - -export interface ButtonProps - extends Omit, - Required> {} - -export const button = (props: ButtonProps) => buttonStyles(props); - -// ❌ TypeScript Error: -// Argument of type "{}": is not assignable to parameter of type "ButtonProps". -// Property "requiredFlat" is missing in type "{}" but required in type "ButtonProps". -button({}); - -// ✅ -button({ requiredFlat: true }); -``` - - -
- This sample is taken from the "Required Variants" section of the - [CVA](https://github.com/joe-bell/cva) project on Github, which was - developed by [Joe Bell](https://github.com/joe-bell). -
-
diff --git a/pages/docs/variants.mdx b/pages/docs/variants.mdx index 5d9881c..2b493a0 100644 --- a/pages/docs/variants.mdx +++ b/pages/docs/variants.mdx @@ -143,6 +143,53 @@ button({ color: 'success', size: 'lg' }); */ ``` +### Required variants + +You can enforce that certain variants must be provided at both runtime and TypeScript level by using the `requiredVariants` property. This helps prevent missing critical variant configurations. + +```js copy /requiredVariants/ +import { tv } from 'tailwind-variants'; + +const button = tv({ + base: 'font-semibold text-white py-2 px-4 rounded-full active:opacity-80', + variants: { + intent: { + primary: 'bg-blue-500 hover:bg-blue-700', + secondary: 'bg-gray-500 hover:bg-gray-700', + danger: 'bg-red-500 hover:bg-red-700' + }, + size: { + sm: 'text-sm py-1 px-3', + md: 'text-md py-2 px-4', + lg: 'text-lg py-3 px-6' + } + }, + requiredVariants: ['intent'] +}); + +// ✅ Valid - intent is provided +button({ intent: 'primary', size: 'md' }); +/** + * Result: + * font-semibold text-white py-2 px-4 rounded-full active:opacity-80 bg-blue-500 hover:bg-blue-700 + */ + +// ❌ TypeScript Error & Runtime Error - intent is missing +button({ size: 'md' }); +/** + * Runtime Error: + * Tailwind Variants: Missing required variant(s): intent + */ +``` + + +
+ Required variants provide both TypeScript type checking and runtime + validation. If a required variant is not provided, an error will be thrown + at runtime. +
+
+ ### Boolean variants You can also add boolean variants to a component. This is useful when you want to add a state variant e.g. `disabled`.