Giter Site home page Giter Site logo

nextui-org / tailwind-variants Goto Github PK

View Code? Open in Web Editor NEW
2.1K 11.0 63.0 305 KB

๐Ÿฆ„ Tailwindcss first-class variant API

Home Page: https://tailwind-variants.org

License: MIT License

JavaScript 24.51% Shell 0.17% TypeScript 75.32%
classnames css tailwindcss variants

tailwind-variants's People

Contributors

acald-creator avatar alex20180512 avatar ben-hapip avatar douglasduteil avatar gomah avatar handfish avatar hoangdevnull avatar jonathassardinha avatar jrgarciadev avatar lrholmes avatar marbemac avatar mskelton avatar patrykwalach avatar thefalked avatar tianenpang avatar timmlopk avatar yjose avatar zwgnr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tailwind-variants's Issues

declaration file not found

Describe the bug
Simply installed the package, and immediatly ts server tells me it cannot find the declaration file or the module. Using it in a NextJs project with the following tsconfig:

EDIT: installed tailwind-variant at version ^0.1.10

image

Here is the error:
image

NextJS Version is 13.4.9, but since its TS related i don't think thats the problem.

Expected behavior
Typings just working without research.

Desktop (please complete the following information):

  • OS: MacOS

Doesn't work when using Turbopack in Nextjs app dir

Describe the bug
Doesn't work when using Turbopack in Nextjs app dir

To Reproduce
Steps to reproduce the behavior:

  1. npx create-next-app@latest -e with-turbopack
  2. next dev --turbo
  3. tailwindcss config
/** @type {import('tailwindcss').Config} */
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { withTV } = require('tailwind-variants/transformer');

module.exports = withTV({
  darkMode: 'class',
  content: [
    './app/**/*.{js,ts,jsx,tsx}', // Note the addition of the `app` directory.
    './pages/**/*.{js,ts,jsx,tsx}'
  ],
  future: {
    hoverOnlyWhenSupported: true
  },
  theme: {
    extend: {}
  },
  plugins: []
});
  1. button
import { tv } from 'tailwind-variants';

const Button = () => {
  const button = tv({
    base: 'font-medium bg-blue-500 text-white rounded-full active:opacity-80',
    variants: {
      color: {
        primary: 'bg-blue-500 text-white',
        secondary: 'bg-purple-500 text-white'
      },
      size: {
        sm: 'text-sm',
        md: 'text-base',
        lg: 'px-4 py-3 text-lg'
      }
    },
    compoundVariants: [
      {
        size: ['sm', 'md'],
        class: 'px-3 py-1'
      }
    ],
    defaultVariants: {
      size: 'md',
      color: 'primary'
    }
  });

  return (
    <button className={button({ size: 'sm', color: 'secondary' })}>
      Click me
    </button>
  );
};

export default Button;
  1. in app/page import it

Expected behavior
It can work

Screenshots

Desktop (please complete the following information):

  • OS: [Mac]
  • Browser [chrome]
  • Version [0.1.0]

Smartphone (please complete the following information):

Additional context

Wrong typing for `twMergeConfig`

Describe the bug
why passing twMergeConfig to tv function I get this error

Type 'Partial<Config>' is not assignable to type 'Config'.
  Types of property 'cacheSize' are incompatible.
    Type 'number | undefined' is not assignable to type 'number'.
      Type 'undefined' is not assignable to type 'number'.

the Problem is in tv typing where twMergeConfig is type of TwMergeConfig

import type {Config as TwMergeConfig} from "tailwind-merge";

export type TWMConfig = {
  twMergeConfig?: TwMergeConfig;
};

however, inside tailwind-merge the config type is

import { Config } from './types';
type CreateConfigSubsequent = (config: Config) => Config;
export declare function extendTailwindMerge(configExtension: Partial<Config> | CreateConfigSubsequent, ...createConfig: CreateConfigSubsequent[]): (...classLists: import("./tw-join").ClassNameValue[]) => string;

To Reproduce
check vscode

Expected behavior
twMergeConfig has to correct typing

Responsive styles not applied to certain slots

Describe the bug

I'm working on a modal component that uses slots, and that also uses responsive styles to ensure that all of the fullscreen styles are applied until the sm breakpoint. One piece of this, is ensuring that the hide modal button is shown when fullscreen === true or when on mobile, even when hideCloseButton === true. My understanding is that the below style object should cover this. But sadly I'm having some trouble getting this working properly.

const styles = tv(
  {
    slots: {
      modal: "absolute",
      dialog: "max-h-screen overflow-y-auto bg-white",
      closeButton: "absolute right-8 top-8 cursor-pointer text-sm text-black"
    },
    variants: {
      fullscreen: {
        true: {
          modal: "h-full w-full",
          dialog: "h-full w-full",
          closeButton: "!block"
        },
        false: {
          modal: "h-max w-max",
          dialog: "h-max w-max rounded-lg"
        }
      },
      hideCloseButton: {
        true: {
          closeButton: "hidden"
        }
      }
    }
  },
  { responsiveVariants: ["sm"] }
);

To Reproduce

Link to minimal repro here: https://codesandbox.io/s/confident-http-rvdg8c?file=/src/index.tsx

Expected behavior

The close modal button should display in the following scenarios:

  1. { hideCloseButton: true, fullscreen: true }
  2. { hideCloseButton: true, size: 'initial' }
  3. { hideCloseButton: false | undefined, ...anyOtherProps }

The close modal button should NOT display in the following scenarios:

  1. { hideCloseButton: true, size: 'md' }
  2. { hideCloseButton: true, fullscreen: false | undefined }

Desktop (please complete the following information):

  • OS: macOS
  • Browser: Chrome, Safari
  • Version: N/A

typo on Comparison page

Describe the bug
Theres a typo at the bottom of the Comparison page.

To Reproduce
Steps to reproduce the behavior:

  1. Go to Comparison page
  2. "That beign said" should be "That being said"

Expected behavior

Screenshots
Screenshot 2023-05-11 at 08 08 39

Composing components while adding extra slots

Discussed in #21

Originally posted by lewebsimple March 10, 2023
As the title says, is it possible to add extra slots when extending a component ?

Consider the following:

import { tv } from "tailwind-variants";

const section = tv({
  slots: {
    wrapper: '',
    inner: '',
  },
});

const extended = tv({
  extend: section,
  slots: {
    inner: 'py-12',
    extraSlot: '',
  }
});

// This doesn't work as extended().extraSlot is undefined, but commenting out `extend: section` makes it work
console.log(extended().extraSlot())

Of course adding the missing slots in the parent component with empty values would fix the problem, but this means we have to know every possible slot name in advance ... which is not very convenient DX or downright impossible for packaged libraries.

Am I missing something ?

VariantProps are of type `any`

Describe the bug
When using the VariantProps generic all of the returned types are any instead of being literals.

To Reproduce

  1. Create a basic tv function in Typescript that includes variants.
const circle = tv({
  variants: {
    size: {
      md: ["w-[580px] h-[580px]"],
      lg: ["w-[1280px] h-[1280px]"],
    },
    contrast: {
      low: ["bg-gray-100", "dark:bg-purple-900"],
      high: ["bg-gray-200", "dark:bg-purple-800"],
    },
  },
  defaultVariants: {
    size: "md",
    contrast: "high",
  },
})
  1. Import and use the VariantProps generic
type CircleType = VariantProps<typeof circle> 
  1. Check intellisense on either type, or component, and see any
    Screen Shot 2023-06-06 at 9 16 56 AM
    Screen Shot 2023-06-06 at 9 16 26 AM

Expected behavior
variant props to be literals. ie: size: 'md' | 'lg'

Screenshots
Screenshots are added above in description

Desktop (please complete the following information):

  • OS: Mac 12.6.6
  • Browser: Not applicable
  • Typescript Version: 5.1

Smartphone (please complete the following information):

  • Device: n/a
  • OS: n/a
  • Browser: n/a
  • Version: n/a

Additional context
The actual tv function isn't strongly typed either. I can add whatever I want to defaultVariants whether its a variant or not.

Feedback for โ€œAcknowledgementsโ€

Hello. I implement my own variants function and look for the lib that could do this the best. There is a lack of custom props for tuning variants that depends on some prop or state. It's loading for example.
image
Best regards, Ruslan.

Specific responsive variants are not working

Describe the bug
Defining a responsive variant for specific variants using the object syntax (described on #24) isn't returning the correct types nor is it returning the expected classes.

To Reproduce
Steps to reproduce the behavior:

  1. Go to https://codesandbox.io/p/sandbox/competent-ben-i7mvx9
  2. Open components/button.styles.ts file where the responsive variants are configured for the size variant only
  3. Open pages/index.tsx file to see usage of component and the types of the variants (extracted using VariantProps on components/button.tsx file)
  4. See that the "Responsive button" has type errors on the size prop and that the classes have not been injected into the <button> element.

Expected behavior
The types should be correctly asserted based on the configuration the developer has instructed for each variant and the classes should be extracted according to the same configuration.

Additional context
It seems that the transformer has this feature working (according to the PR mentioned above), but the tv API does not seem to have this feature implemented just yet.

extended tailwind classes not added to final classList.

Describe the bug
I have extended my tailwind theme with new a new class for a smaller fontSize:

fontSize: {
        mini: ['0.65rem', '0.75rem'],
      },

But when trying to use it in a tailwind-variants function. It never gets added to the final classes:

e.g.

export const itemDescription = tv({
  base: 'm-0 overflow-hidden whitespace-nowrap text-mini text-neutral-400',
})

The only workaround I have found is to override the class like tv({ class: 'text-mini '}) (this makes it work).

Expected behavior
extended tailwind theme options should work in the tv() base classes.

Desktop (please complete the following information):

  • OS: macOS
  • Browser: Chromium
  • Version "tailwind-variants": "0.1.8",

Improve performance

Hey there ๐Ÿ‘‹,

First, thank you for making this lib possible, it has great features and coming from cva, it feels nice to use slots and the extend prop.

However, as I was refactoring the project to use tailwind-variants, I noticed some performance issue...

Here's a repro:
https://github.com/Sliov/cva-tailwind-variants-benchmark

Do you know if that's normal or if there's space for improvement here?

Thank you

`VariantProps` with extended component only works when `variants` is defined

Describe the bug
When extending a component with extend and using it with VariantProps, it only works when the variants property is defined in the extending component.

To Reproduce
Take this (solidJS) code:

const base = tv({
  base: "...",
  variants: {
    hasError: {
      true: "border-red-800 outline-red-800",
    },
  },
});

const extended = tv({
  extend: base
});

export interface ExtendedProps extends JSX.SelectHTMLAttributes<HTMLSelectElement>, VariantProps<typeof extended> {}

export const Extended: Component<ExtendedProps> = (props) => {
  // Split select element props
  const [local, other] = splitProps(props, ["class", "hasError"]);

  return (
    <select
      class={extended({ hasError: local.hasError, class: local.class })}
      {...other}
    />
  );
};

It throws the following error:

Type 'string | number | boolean | TVScreenPropsValue<{ hasError: { true: string; }; } & TVVariantsDefault<undefined, undefined>, string> | TVScreenPropsValue<...> | undefined' is not assignable to type 'boolean | TVScreenPropsValue<{ hasError: { true: string; }; } & { hasError?: { true?: ClassValue | SlotsClassValue<undefined, undefined>; } | undefined; }, "hasError"> | undefined'.
  Type 'string' is not assignable to type 'boolean | TVScreenPropsValue<{ hasError: { true: string; }; } & { hasError?: { true?: ClassValue | SlotsClassValue<undefined, undefined>; } | undefined; }, "hasError"> | undefined'.

Replacing extended with the following code fixes the issue:

const extended = tv({
  extend: base,
  variants: {}
});

Expected behavior
I expect it to don't throw on the first variant.

Desktop (please complete the following information):

  • OS: no response
  • Browser no response
  • Version no response

Smartphone (please complete the following information):

  • Device: no response
  • OS: no response
  • Browser no response
  • Version no response

Additional context
no response

Type error when TailwindVariant style contains boolean

Describe the bug
Receive type error when TailwindVariant style contains boolean.

To Reproduce
Steps to reproduce the behavior:

  1. Have boolean in the tv style
  2. Use tv style in .tsx file
  3. See type error saying Type boolean is not assignable to string | number | undefined

Expected behavior
There should not be any errors. The boolean should be converted to string under the hood. Or the type should accept boolean.

Screenshots

The setting on tv containing booleans:
image

The type error received when using the tv style:
image

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • macOS 13.5.2
  • Chrome
  • Version [e.g. 22]
  • Typescript 4.9.4
  • tailwind-variants: 0.1.13
  • typescript-eslint/eslint-plugin: 5.60.1,
  • typescript-eslint/parser: 5.47.0,

Additional context
Please let me know if there is any questions. Thank you.

Feature: edit default configuration

Would like the ability to edit the default config:

type TvConfig = {
  twMerge?: boolean,
  twMergeConfig?:TwMergeConfig,
  responsiveVariants?: string[] | boolean
}

Mostly just want to turn off twMerge by default

You could do it one of two ways:

import { globalConfig } from 'tailwind-variants'

globalConfig({
  twMerge: false
})

...

or

import { createTV } from 'tailwind-variants'

const tv = createTV({
  twMerge: false
})

const button = tv({
  ...
})

...

Incorrect types inheritance when extending

Describe the bug
When using "extend" prop to compose class names, the prop-types produced in extended TVReturnType aren't correct. Without "boolean" variant, typescript happy, but the type of "props.variant" in the BuyButton component is "string | number | undefined" which looks incorrect too.

To Reproduce

const baseButton = tv({
  base: "",
  variants: {
    variant: {
      primary: "",
    },
    disabled: {
      true: "",
    },
  },
});

const buyButton = tv({
  extend: baseButton,
});

const Button = (props: VariantProps<typeof baseButton>) => {
  const className = baseButton(props);

  return (
    <div className="flex gap-3">
      <button className={className}>Buy button</button>
    </div>
  );
};

const BuyButton = (props: VariantProps<typeof buyButton>) => {
  const className = buyButton(props);

  return (
    <div className="flex gap-3">
      <button className={className}>Buy button</button>
    </div>
  );
};

Expected behavior
Props for the "buyButton" inherited properly to let typescript pass without errors and suggest correct variants in autocomplete.

Screenshots
Screenshot 2023-05-03 at 17 58 15
Screenshot 2023-05-03 at 17 58 26

Desktop (please complete the following information):

  • OS: MacOS Ventura 13.3.1

Additional context

  • Typescript: 5.0.2
  • tailwind-variants: 0.1.5

Compound Slots not working with variants

Given the following configuration

const grid = tv({
  variants: {
    documents: {
      true: {},
    }
  },
  defaultVariants: {
    documents: true
  },
  slots: {
    general: 'col-span-7 row-span-4 card',
    chart: 'card !px-0 col-span-5 relative row-span-4',
    documents: 'row-span-6 col-span-5 card',
    flow: 'relative row-span-6 card'
  },
  compoundSlots: [
    // {
    //   slots: ['documents', 'chart', 'general', 'flow'],
    //   className: 'bg-violet-10',
    //   documents: false
    // },
    {
      documents: false,
      slots: ['documents'],
      className: 'hidden'
    }, {
      documents: false,
      slots: ['flow'],
      className: 'col-span-12'
    }, {
      documents: true,
      slots: ['flow'],
      className: 'col-span-7'
    }
  ]
})

// usage later
const { general, flow, documents, chart } = grid({ documents: true })

// i'd expect to have `col-span-12` applied below
// jsx
<div className={flow()} />

The variants are never applied ๐Ÿคทโ€โ™‚๏ธ (version 0.1.10).
Maybe I misunderstood how to use them?

Leading classes not added to output

Describe the bug
I'm currently evaluating tv for a project, and have been doing some testing by refactoring an existing typography component. I've noticed that some classes (in this case, leading-x ones) aren't being added.

To Reproduce
Here is a codesandbox with a minimal repro, showing that the leading classes are not added by tv, but are added by cva

Expected behavior
All classes listed in the variant's config are added to the output.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: MacOS
  • Browser: Chrome, Safari
  • Version: 0.1.5

Incorrect Types

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Steps to reproduce the behavior:
Copy paste example code

tv({
  base: 'font-bold',
  variants: {
    size: {
      xs: '',
      sm: ''
    },
    flat: {
      true: ''
    }
  },
  defaultVariants: {
    flat: true,

  },
  compoundVariants: []
})

Expected behavior
No errors

Screenshots
CleanShot 2023-06-09 at 02 33 43@2x

Desktop (please complete the following information):

  • OS: MacOS
  • Browser not relevant
  • Version 0.1.6

Additional context
Add any other context about the problem here.

[ docs ] - mistake in code snippet

hello there... while exploring ur website. i saw this code error at this page in last snippet

=> bug

const { base, tab } = tab({ color: "primary" });

=> correct

const { base, tab } = card({ color: "primary" });

yarn berry PnP build Error

Describe the bug

  • yarn berry PnP build Error

To Reproduce
Steps to reproduce the behavior:

  1. Set up Next.js starter.
  2. Run "yarn set version 3.2.3".
  3. Run "yarn install".
  4. Encounter an error when running "yarn build".

Expected behavior

  • Expect the "yarn build" command to run successfully and confirm the build.

Screenshots
If applicable, add screenshots to help explain your problem.

image

Desktop (please complete the following information):

  • OS: Windows 11
  • Browse: Chrome
  • Version: recent

Additional context
Add any other context about the problem here.

  • Is there any other way to apply in a Yarn Berry PnP environment? If so, can you guide me through it?

Export className with VariantProps

Hi,

This is not a bug, may be a feature request.

I find myself keep adding ClassName in each component like this

import { ClassValue } from 'tailwind-variants'

export type HeadingProps = HeadingVariants & {
  className?: ClassValue
}

I even played with VariantProps types locally to un omit the className but the type was messed up, would you consider exporting something like WithClassName?

type WithClassName<P = unknown> = P & { className?: ClassValue };

Putting "text-{color}" class in the same variant as "text-{size}" class removes the color class

Describe the bug
Putting "text-{color}" class in the same variant as "text-{size}" class removes the color class

To Reproduce
Steps to reproduce the behavior:

  1. Add tokens to tailwind config
const config = {
  theme: {
    colors: {
      ...
      white: '#FFFFFF'
    },
    fontSize: {
      ...
      '14': '0.875rem'
    }
  }
}
  1. Create variant
export const button = tv({
  variants: {
    intent: {
      primary: 'text-white text-14',
    },
  },
  defaultVariants: {
    intent: 'primary',
  },
})
  1. Add to component
function Component() {
  return <button className={button()}>Button</button>
}
  1. Check DOM and notice missing classes

Expected behavior
No tailwind classes should be removed

Screenshots
Notice "text-emerald" has been removed
Screenshot 2023-08-20 at 8 38 27 PM
Screenshot 2023-08-20 at 8 38 59 PM

Desktop (please complete the following information):

  • OS: Mac
  • Browser: chrome
  • Version: 115.0.5790.170

Additional context
Add any other context about the problem here.

Custom boxShadow not working with shadow color class

Describe the bug
Custom shadows get stripped from the classList when used with a color class.

To Reproduce
Steps to reproduce the behavior:

  1. Create a custom boxShadow in tailwind config: {circle: "0 0px 30px -10px rgba(0, 0, 0, 0.3)"}
  2. Create a tv with variant: shadow-circle shadow-violet-600
  3. Results in: hover:shadow-violet-600, with shadow-circle stripped
  4. If I remove shadow-violet-600, then shadow-circle remains

Expected behavior
Custom shadows should be usable with shadow color utility classes

Great work on this btw!

TailwindCSS arbitrary values don't work

Is there any way to configure it?
I want margin-top: 65px,
so I wrote mt-[65px] but it's not working.
Code:
<main className="container mx-auto max-w-7xl px-6 flex-grow mt-[65px]">

extend does not work as expected

Extend does not work as expected. I've created a simple example below.

Once "inputBox" is extended, the "slot" is modified and not immutable. It appears that this pull request (PR) is causing this change.

const inputBox = tv({
  slots: {
    base: "flex",
  },
});
console.log("inputBox", inputBox().base()); // flex

const extendedInput = tv({
  extend: inputBox,
  slots: {
    base: "flex1",
  },
});

// expected: flex flex1, actual: flex flex1
console.log("extendedInput", extendedInput().base()); 
// expected: flex, actual: flex flex1
console.log("inputBox", inputBox().base());

I'm curious as to why the implementation of "joinObjects" was changed to a version with side effects.

In monorepo, `writeFileSync()` is called on the client side

Describe the bug

In monorepo using Turborepo, when withTV() was called in a child package to hide settings related to tailwind, writeFileSync() was called on the client side and compilation failed.

To Reproduce

Steps to reproduce the behavior:

  1. Clone a minimally configured repository to reproduce this problem: https://github.com/dino3616/tv-bug (alternative: you can use Codespaces)
  2. Install dependencies with the pnpm install command
  3. Start the development server with the pnpm website dev command
  4. Check the errors output to the browser and terminal

Expected behavior

Can compile even if withTV() is called in a child package.

Screenshots

Below is a screenshot of the error output to the browser:

image

and terminal:

pnpm website dev

> [email protected] website /Users/shio/Projects/shio3616/tv-bug
> pnpm --filter @tv-bug/website "dev"


> @tv-bug/[email protected] dev /Users/shio/Projects/shio3616/tv-bug/apps/website
> next dev

- ready started server on 0.0.0.0:3000, url: http://localhost:3000
- event compiled client and server successfully in 318 ms (20 modules)
- wait compiling...
- event compiled client and server successfully in 100 ms (20 modules)
- wait compiling /page (client and server)...
- error ../../node_modules/.pnpm/[email protected][email protected]/node_modules/tailwind-variants/dist/chunk-FUBUDMV2.js:1:0
Module not found: Can't resolve 'fs'

https://nextjs.org/docs/messages/module-not-found

Import trace for requested module:
../../node_modules/.pnpm/[email protected][email protected]/node_modules/tailwind-variants/dist/transformer.js
../../packages/tailwind/src/config.ts
../../packages/tailwind/src/index.ts
./src/component/client-button.tsx
- wait compiling /_error (client and server)...
- error ../../node_modules/.pnpm/[email protected][email protected]/node_modules/tailwind-variants/dist/chunk-FUBUDMV2.js:1:0
Module not found: Can't resolve 'fs'

https://nextjs.org/docs/messages/module-not-found

Import trace for requested module:
../../node_modules/.pnpm/[email protected][email protected]/node_modules/tailwind-variants/dist/transformer.js
../../packages/tailwind/src/config.ts
../../packages/tailwind/src/index.ts
./src/component/client-button.tsx
<w> [webpack.cache.PackFileCacheStrategy] Caching failed for pack: Error: ENOENT: no such file or directory, rename '/Users/shio/Projects/shio3616/tv-bug/apps/website/.next/cache/webpack/client-development-fallback/1.pack.gz_' -> '/Users/shio/Projects/shio3616/tv-bug/apps/website/.next/cache/webpack/client-development-fallback/1.pack.gz

Desktop (please complete the following information):

  • OS: macOS
  • Browser: chrome
  • Version: N/A

Additional context

This problem is only specific to monorepo and does not occur with polyrepo.
In fact, a modification like this PR completely eliminates the problem.

Landing page styling bug

Describe the bug
Doesn't look right

To Reproduce
Steps to reproduce the behavior:

  1. Go to "tailwind-variants.org
  2. Mobile view
  3. Scroll-x

Expected behavior
...

Screenshots
image

Additional context
<svg fill="none" height="1018" viewBox="0 0 1210 1018" width="1210" xmlns="http://www.w3.org/2000/svg" class="absolute -z-10 -translate-y-[40%] animate-[appear_1s_ease]">
is not responsive

Typescript: basic example of compound variants from documentation generates type errors "Type 'string' is not assignable to type 'never'"

Describe the bug
Following the documentation on compound variants generates a TypeScript error when attempting to target multiple variants.

To Reproduce

  1. Setup a basic project with tailwind-variants
  2. Copy the code from the documentation on compound variants
  3. See that the size key of compoundVariants cannot target ['sm', 'md'] or else it generates

Type 'string' is not assignable to type 'never'.ts(2322)

Expected behavior
I expect no TypeScript errors for basic usage of the compound variants feature.

Desktop (please complete the following information):

  • OS: Windows Version 22H2 OS Build 19045.2965
  • Browser: N/A (TypeScript error throws without accessing via Browser, but using VSCode)
  • Version: "tailwind-variants": "^0.1.5"

typecheck fails

Describe the bug
Running command typecheck failed due to no providing declaration file of utils.js

To Reproduce

  1. Go to root of the project
  2. run typecheck script
  3. Scroll down to '....'
  4. See error

Expected behavior
Type check must be finished without no errors.

Screenshots

image

Additional context
You maybe considering allowJS: true or converting utils.js to TS version.

Feature Request: Support for other types of Tailwind variants, not only the responsive ones

Dynamic Variants

Before using Tailwind Variants, I created components with Tailwind plugin utility to use on my company's design system.

module.exports = plugin({ addComponents })({
  addComponents({
    '.btn': {
       padding: '...',
       margin: '...',
       fontSize: '...'
    },
    '.btn-light': {...},
    '.btn-dark': {...},
  })
})

And the beauty was that once Tailwind creates the component classes (i.e. .btn) I could use them with Tailwind variants:

<button class="btn btn-light dark:btn-dark">Button</button>

The idea here is to use the current responsiveVariants and transform it to accept all sorts of Tailwind variants like dark and others, not only the responsive ones.

Current behavior

import { tv } from "tailwind-variants";
 
const button = tv({
  base: "font-semibold text-white py-1 px-3 rounded-full active:opacity-80",
  variants: {
    color: {
      primary: "bg-blue-500 hover:bg-blue-700",
      secondary: "bg-purple-500 hover:bg-purple-700",
      success: "bg-green-500 hover:bg-green-700",
    },
    size: {
      small: "py-0 px-2 text-xs",
      medium: "py-1 px-2 text-sm",
      large: "py-1.5 px-3 text-md",
    },
  }
},
{
  responsiveVariants: ['sm', 'md'] // `true` to apply to all screen sizes
});
 
button({
  color: {
    initial: "primary",
    sm: "success",
    md: "secondary",
  },
  size: {
    initial: "small",
    sm: "medium",
    md: "large",
  },
});

Request

responsiveVariants becomes dynamicVariants

import { tv } from "tailwind-variants";
 
const button = tv({
  base: "font-semibold text-white py-1 px-3 rounded-full active:opacity-80",
  variants: {
    color: {
      primary: "bg-blue-500 hover:bg-blue-700",
      secondary: "bg-purple-500 hover:bg-purple-700",
      success: "bg-green-500 hover:bg-green-700",
    },
    size: {
      small: "py-0 px-2 text-xs",
      medium: "py-1 px-2 text-sm",
      large: "py-1.5 px-3 text-md",
    },
  }
},
{
  dynamicVariants: ['sm, 'md', 'dark']  // enables the usage of `dark`
});
 
button({
  color: {
    initial: "primary",
    dark: "success", 
  }, 
  size: {...},
});
// results in "bg-blue-500 hover:bg-blue-700 dark:bg-green-500 dark:hover:bg-green-700 ..."

// Usage in JSX

const Button = ({ color, size, className, children }) => (
  <button className={button({ color, size, className })}>{children}</button>
)

export default () => (
  <Button color={{ initial: 'primary', dark: 'success' }} size={{ ... }}>
    ...
  </Button>
)

`TWMConfig["twMergeConfig"]` does not allow partial configurations

Describe the bug

Since the use of TWMConfig["twMergeConfig"] is to be passed to extendTailwindMerge that takes configs partially, the type of TWMConfig["twMergeConfig"] should be also partial.

const twMerge = !isEmptyObject(config.twMergeConfig)
      ? extendTailwindMerge(config.twMergeConfig)
      : twMergeBase;

https://github.com/nextui-org/tailwind-variants/blob/main/src/index.js#LL29C24-L29C24

export function extendTailwindMerge(
    configExtension: Partial<Config> | CreateConfigSubsequent,
    ...createConfig: CreateConfigSubsequent[]
) {
    return typeof configExtension === 'function'
        ? createTailwindMerge(getDefaultConfig, configExtension, ...createConfig)
        : createTailwindMerge(
              () => mergeConfigs(getDefaultConfig(), configExtension),
              ...createConfig,
          )
}

https://github.com/dcastil/tailwind-merge/blob/main/src/lib/extend-tailwind-merge.ts#LL8C1-L18C2

export type TWMConfig = {
  /**
   * Whether to merge the class names with `tailwind-merge` library.
   * It's avoid to have duplicate tailwind classes. (Recommended)
   * @see https://github.com/dcastil/tailwind-merge/blob/v1.8.1/README.md
   * @default true
   */
  twMerge?: boolean;
  /**
   * The config object for `tailwind-merge` library.
   * @see https://github.com/dcastil/tailwind-merge/blob/v1.8.1/docs/configuration.md
   */
  twMergeConfig?: TwMergeConfig;
};

https://github.com/nextui-org/tailwind-variants/blob/main/src/config.d.ts#L20

To Reproduce
Steps to reproduce the behavior:

  1. Install the package
  2. Pass tv an empty configuration object as shown below:
tv(options, {
    ...config,
    twMerge: true,
    twMergeConfig: {},
  });
  1. Now you reproduced the type error.

Expected behavior

TWMConfig["twMergeConfig"] should be typed partially.

export type TWMConfig = {
  /**
   * Whether to merge the class names with `tailwind-merge` library.
   * It's avoid to have duplicate tailwind classes. (Recommended)
   * @see https://github.com/dcastil/tailwind-merge/blob/v1.8.1/README.md
   * @default true
   */
  twMerge?: boolean;
  /**
   * The config object for `tailwind-merge` library.
   * @see https://github.com/dcastil/tailwind-merge/blob/v1.8.1/docs/configuration.md
   */
  twMergeConfig?: Partial<TwMergeConfig>;
};

Screenshots
If applicable, add screenshots to help explain your problem.
image

Desktop (please complete the following information):

All desktop environments

Smartphone (please complete the following information):

All smartphone environments

Additional context
None

text size and text color overwrites each other

Describe the bug
text size and text color overwrites each other

const button = tv({
  base: 'rounded-sm',
  variants: {
    variant: {
      primary: 'bg-primary text-neutral-white',
      secondary: '',
      tertiary: ''
    },
    size: {
      small: 'py-2 px-6 text-button-small',
      medium: 'py-3.5 px-8 text-button-medium',
      normal: 'py-4 px-8 text-button-normal'
    }
  },
  defaultVariants: {
    variant: 'primary',
    size: 'medium'
  }
})

Expected Result
"rounded-sm bg-primary py-3.5 px-8 text-neutral-white text-button-medium"

Result
"rounded-sm bg-primary py-3.5 px-8 text-button-medium"

Link not found in Documentation

Describe the bug

The link on the Slots Documentation https://www.tailwind-variants.org/docs/slots#slots-with-responsive-variants is throwing 404. Please update the link, it is currently referencing to https://www.tailwind-variants.org/docs/responsive-variants.

To Reproduce
Steps to reproduce the behavior:

  1. Go to 'https://www.tailwind-variants.org/docs/slots#slots-with-responsive-variants`'
  2. Click on 'here' link
  3. It will throw the 404 page error

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.
Screenshot 2023-07-23 at 5 24 10 PM

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

slow down prettier formating in vscode

i created a button component using tailwind variants like this:
const button = tv(
{
base: "py-2 px-5 ",
variants: {
variant: {
contained: "rounded-[10px] ",
outlined: "rounded-[10px]",
inlined: "bg-transparent ",
},
},
},
{
responsiveVariants: ["lg"],
}
);

type ButtonVariants = VariantProps;

export type IButtonProps = {
children: React.ReactNode;
} & ButtonVariants;

but when i use this component ,the prettier extenstion formatting on vscode takes to long ... !
and when i remove tailwind variants from this component,prettier formatting working stable and fast !

Screenshot (111)

Expected behavior
dont break another tools and extenstion like prettier !

  • OS: Windows
  • Browser Chrome
  • Version 113

Tailwind Variants Transform Failed: Widths is not defined

Describe the bug

First of all, thank you for the library โ€“ enjoying using it so far, it's helped a lot in structuring Tailwind-based projects.

Using Next.js 13 โ€“ย I have a file that looks like this:

import { tv } from "tailwind-variants";

type WidthScale = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;

export const Widths: { [key in WidthScale]: string } = {
  0: "w-0",
  1: "w-1",
  2: "w-2",
  3: "w-3",
  4: "w-4",
  5: "w-5",
  6: "w-6",
  7: "w-7",
  8: "w-8",
  9: "w-9",
  10: "w-10",
};

export const useWidth = tv(
  {
    variants: {
      width: {
        full: "w-full",
        ...Widths,
      },
    },
  },
  { responsiveVariants: true }
);

When I start the app, I get the following message:

Tailwind Variants Transform Failed: Widths is not defined
If you think this is an issue, please submit it at https://github.com/nextui-org/tailwind-variants/issues/new/choose

If I move the widths directly into the function, the problem goes away โ€“ i.e:

export const useWidth = tv(
  {
    variants: {
      width: {
        full: "w-full",
        0: "w-0",
        1: "w-1",
        2: "w-2",
        3: "w-3",
        4: "w-4",
        5: "w-5",
        6: "w-6",
        7: "w-7",
        8: "w-8",
        9: "w-9",
        10: "w-10",
      },
    },
  },
  { responsiveVariants: true }
);

To Reproduce
Create a file with the above, and reference it inside a component.

Desktop (please complete the following information):

  • Next version: 13.4.2
  • Tailwind Variants version: 0.1.6
  • Tailwind version: 3.3.1

Idea, add polymorphic components & tsx export

import { tv } from 'tailwind-variants'

const button = tv({
  base: "font-medium inline-flex items-center",
  variants: {
    variant: {
      default: "bg-white border hover:bg-gray-50",
      filled: "bg-light-primary hover:bg-light-hover-primary text-white",
      light: "bg-light-primary/10 hover:bg-light-hover-primary/[0.12] text-light-primary",
      outline: "bg-white hover:bg-light-primary/5 border border-light-primary text-light-primary",
      subtle: "bg-white hover:bg-light-hover-primary/[0.12] text-light-primary",
      transparent: "bg-white text-light-primary",
      white: "bg-white hover:bg-gray-50 text-light-primary",
    },
    size: {
      xs: "px-3 h-7 text-xs",
      sm: "px-4 h-8 text-sm",
      md: "px-5 h-9 text-base",
      lg: "px-6 h-10 text-lg",
      xl: "px-7 h-11 text-xl",
      '2xl': "px-8 h-12 text-xl",
    },
    radius: {
      xs: "rounded-sm",
      sm: "rounded",
      md: "rounded-md",
      lg: "rounded-lg",
      xl: "rounded-xl",
      '2xl': "rounded-2xl",
      full: "rounded-full",
    },
    fullWidth: {
      true: "w-full"
    },
  },
  defaultVariants: {
    variant: "filled",
    size: "sm",
    radius: "sm",
  },
});

export default function Button({as, ...props}:any) {
  const Component = as || "button";
  
  return (
    <>
      <Component className={button(props)} {...props}>
        {props.children}
      </Component>
    </>
  )
};

typecheck fails

Describe the bug
Running command typecheck failed due to no providing declaration file of utils.js

To Reproduce

  1. Go to root of the project
  2. run typecheck script
  3. Scroll down to '....'
  4. See error

Expected behavior
Type check must be finished without no errors.

Screenshots

image

Additional context
You maybe considering allowJS: true or converting utils.js to TS version.

Responsive variants do not work with ๏ปฟ`theme()`

Describe the bug
Using an arbitrary value that references the theme() function appears to break the withTV transformer's ability to generate classes for responsive variants. Example: w-[theme(spacing.32)].

To Reproduce
Steps to reproduce the behavior:

  1. Go to https://codesandbox.io/p/sandbox/zqqlg2?file=%2Fsrc%2FApp.tsx%3A1%2C1
  2. View App.tsx on :L23 the large variant that uses the (valid) arbitrary value syntax
  3. See classes being appropriately applied (md:w-[theme(spacing.32)]) but the CSS is never generated.

Expected behavior
CSS is successfully generated for the following classes: md:w-[theme(spacing.32)] md:h-[theme(spacing.32)].

Additional context

  • This syntax is useful for when you'd like to calculate a value relative to another theme value like so: w-[calc(theme(spacing.32)_/_2)]
  • Using arbitrary values syntax that doesn't reference the theme() function as defined and commented out on :L22 appears to work as expected.

Typescript errors with `compoundVariants` and boolean values

Describe the bug

This issue appears when I updated typescript from v5.0.4 to v5.1.3.
now when I run the typecehck tsc --noEmit I got this error

src/Button.tsx:19:7 - error TS2322: Type 'true' is not assignable to type 'string | number | symbol | never[] | undefined'.

19       disabled: true,
         ~~~~~~~~


Found 1 error in src/Button.tsx:19

this button component is exactly the live example on the documentation here

To Reproduce
Steps to reproduce the behavior:

  1. Go to this sandbox
  2. open a new terminal and run pnpm typecheck

Expected behavior
error should not happen

Additional context
Add any other context about the problem here.

Typescript type V TVVariantsDefault errors.

Describe the bug
Typescript shows a number of errors

node_modules/tailwind-variants/dist/index.d.ts:216:35 - error TS2344: Type 'V' does not satisfy the constraint 'TVVariantsDefault<S, undefined>'.
  Type 'TVVariants<S, B, EV, undefined>' is not assignable to type 'TVVariantsDefault<S, undefined>'.
    Type 'TVVariantsDefault<S, B> | { [K in keyof EV]?: { [K2 in keyof EV[K]]?: (S extends TVSlots ? ClassValue | SlotsClassValue<S, B> : ClassValue) | undefined; } | undefined; }' is not assignable to type 'TVVariantsDefault<S, undefined>'.
      Type '{ [K in keyof EV]?: { [K2 in keyof EV[K]]?: (S extends TVSlots ? ClassValue | SlotsClassValue<S, B> : ClassValue) | undefined; } | undefined; }' is not assignable to type 'TVVariantsDefault<S, undefined>'.
        Type '{ [K2 in keyof EV[K]]?: (S extends TVSlots ? ClassValue | SlotsClassValue<S, B> : ClassValue) | undefined; } | undefined' is not assignable to type '{ [key: string]: S extends TVSlots ? ClassValue | SlotsClassValue<S, undefined> : ClassValue; }'.
          Type 'undefined' is not assignable to type '{ [key: string]: S extends TVSlots ? ClassValue | SlotsClassValue<S, undefined> : ClassValue; }'.
            Type 'TVVariants<S, B, TVVariants<ES, B, E["variants"], ES>, undefined>' is not assignable to type 'TVVariantsDefault<S, undefined>'.
              Type 'TVVariantsDefault<S, B> | { [K in keyof TVVariants<ES, B, E["variants"], ES>]?: { [K2 in keyof TVVariants<ES, B, E["variants"], ES>[K]]?: (S extends TVSlots ? ClassValue | SlotsClassValue<...> : ClassValue) | undefined; } | undefined; }' is not assignable to type 'TVVariantsDefault<S, undefined>'.
                Type '{ [K in keyof TVVariants<ES, B, E["variants"], ES>]?: { [K2 in keyof TVVariants<ES, B, E["variants"], ES>[K]]?: (S extends TVSlots ? ClassValue | SlotsClassValue<...> : ClassValue) | undefined; } | undefined; }' is not assignable to type 'TVVariantsDefault<S, undefined>'.
                  Type '{ [K2 in keyof TVVariants<ES, B, E["variants"], ES>[K]]?: (S extends TVSlots ? ClassValue | SlotsClassValue<S, B> : ClassValue) | undefined; } | undefined' is not assignable to type '{ [key: string]: S extends TVSlots ? ClassValue | SlotsClassValue<S, undefined> : ClassValue; }'.
                    Type 'undefined' is not assignable to type '{ [key: string]: S extends TVSlots ? ClassValue | SlotsClassValue<S, undefined> : ClassValue; }'.
                      Type 'TVVariantsDefault<S, B> | { [x: string]: { [x: string]: (S extends TVSlots ? ClassValue | SlotsClassValue<S, B> : ClassValue) | undefined; } | undefined; }' is not assignable to type 'TVVariantsDefault<S, undefined>'.
                        Type '{ [x: string]: { [x: string]: (S extends TVSlots ? ClassValue | SlotsClassValue<S, B> : ClassValue) | undefined; } | undefined; }' is not assignable to type 'TVVariantsDefault<S, undefined>'.
                          'string' index signatures are incompatible.
                            Type '{ [x: string]: (S extends TVSlots ? ClassValue | SlotsClassValue<S, B> : ClassValue) | undefined; } | undefined' is not assignable to type '{ [key: string]: S extends TVSlots ? ClassValue | SlotsClassValue<S, undefined> : ClassValue; }'.
                              Type 'undefined' is not assignable to type '{ [key: string]: S extends TVSlots ? ClassValue | SlotsClassValue<S, undefined> : ClassValue; }'.

216     CV extends TVCompoundVariants<V, S, B, EV, ES>,
                                      ~

node_modules/tailwind-variants/dist/index.d.ts:217:34 - error TS2344: Type 'V' does not satisfy the constraint 'TVVariantsDefault<S, undefined>'.

217     DV extends TVDefaultVariants<V, S, EV, ES>,
                                     ~

node_modules/tailwind-variants/dist/index.d.ts:223:7 - error TS2344: Type 'V' does not satisfy the constraint 'TVVariantsDefault<S, undefined>'.

223       V,
          ~

node_modules/tailwind-variants/dist/index.d.ts:263:39 - error TS2344: Type 'V' does not satisfy the constraint 'TVVariantsDefault<S, undefined>'.

263       compoundSlots?: TVCompoundSlots<V, S, B>;
                                          ~

node_modules/tailwind-variants/dist/index.d.ts:275:19 - error TS2344: Type 'V' does not satisfy the constraint 'TVVariantsDefault<S, undefined>'.

275   ): TVReturnType<V, S, B, C, EV, ES, E>;
                      ~


Found 7 errors in 2 files.

To Reproduce
Typescript 4.8.4 use react-aria and tsc

tsconfig:

"compilerOptions": {
    "esModuleInterop": true,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "jsx": "react-jsx",
    "target": "ES2019",
    "module": "ES2022",
    "strict": true,
    "allowJs": true,
}

Expected behavior
Not have typescript errors

Additional context
Add any other context about the problem here.

The compoundSlots does not accept an array in the property

Describe the bug

I am try to pass an array of string inside of property on compoundSlots similar with happen with compoundVariants

To Reproduce

const foo = tv({
      slots: {
        base: "flex flex-wrap",
        cursor: ["absolute", "flex", "overflow-visible"],
      },
      variants: {
        size: {
          xs: {},
          sm: {},
          md: {},
          lg: {},
          xl: {},
        },
      },
      compoundSlots: [
        {
          slots: ["base"],
          size: ["xs", "lg"],
          class: "w-7 h-7 text-xs",
        }
      ],
    })
 []);

const { base } = foo({size: 'xs'});

**HTML**
  <div class={base()}>
  </div>

Expected behavior

**HTML**
    <div class="flex flex-wrap w-7 h-7 text-xs">
    </div>

The properties inside of compoundSlots are hoping 2 differences types string and string[], but when put array of string stop to working. This example, i am using size. When size is 'xs' or 'lg' it need to add the classes. Like compoundVariants working.

Example:

  compoundSlots: [
        {
          slots: ["base"],
          size: ["xs", "lg"],
          class: "w-7 h-7 text-xs",
        }
      ]

Now, i don't know if above quote is a bug or feature, but i hope some answers

  • Browser [e.g. chrome, safari]

feature suggestions

Hey all! some time ago I started an open-source project called Nullwind, it's a components system that uses Tailwind. We're willing to use Tailwind Variants but miss some features described below.

1. ability to apply compound variants based on a boolean

in our case, we have a button with different colors, and this same button has a prop called outline which applies outline styles following the chosen color. for example:

<Button color="secondary" outline />

to achieve it, we needed to create something like the following:

const button = tv({
  variants: {
    color: {
      primary:
        "text-white bg-primary-500 border border-transparent hover:bg-primary-800 disabled:hover:bg-primary-500",
    },
    outline: {
      primary:
        "text-primary-500 bg-white border border-primary-500 hover:bg-primary-50 disabled:hover:bg-white",
    },
  }
})

const Button = ({ color, outline, class: klass }) => {
  <button
    class={button({
      color,
      ...(outline && { outline: color }),
      class: klass,
    })}
  >Click here!</button>
}

after doing that, I noticed the outline type is being mistyped. is there any other way to achieve what we're looking for?

2. ability to extend more than one theme

In our framework, the user is able to style the components globally, locally, or via class. check here

[baseTheme, globalTheme, localTheme, class]

we were able to achieve it but needed to create a complex logic that merges these objects. it'd be cool if we had any way to extend multiple themes, so we can use the TV engine to replace all the necessary properties correctly.

our workaround:

const button = tv({ extend: buttonTheme, ...mergeThemes(context.theme, props.theme)?.button });
button({ ...props, class: props.class })

suggestion:

const button = tv({ extend: [buttonTheme, tv(context.theme.button), tv(props.theme.button)] });
button({ ...props, class: props.class })

I'd love to discuss more about these requested features ๐Ÿ˜„

Slot level variant overrides

We are using react-aria-components in our component library and one thing we find that tailwind-variants doesn't support very well is the ability to override variants at the slot level. For example, with react-aria-components, some variables used for variants are passed to the class name prop like shown below.

const tooltipStyles = tv({ ... })
const styles = tooltipStyles()

<BaseTooltip className={({ placement }) => styles.base({ placement })}>
  <OverlayArrow className={({ placement }) => styles.arrow({ placement })}>
    <svg />
  </OverlayArrow>
  
  {content}
</BaseTooltip>

While this is more of a niche use case, and defining the variants at the top level is definitely the more likely case, having the ability to at least override variants at the slot level to support this use case would be nice.

Thoughts?

rounded classes did not get merged when using custom className

Describe the bug
I am using TV to style my button component
and I have a rounded variant, rounded variant by default is md in defaultVariants when I tried to add a class name rounded-0 to override the base class, the classes did not get merged and both of the classes are on the component when I tried to add a class name to override the color variant by adding new class, the classes got merged and the background color on the component is what I passed from className

<Button
      variant="solid"
      color="danger"
      className="rounded-0 bg-secondary text-danger hover:bg-secondary-700"
>
 Custom
</Button>

Expected behavior
it should override the base class with the given class in className

Screenshots
Screenshot 2023-05-03 at 7 51 04 PM

  • OS: macOS
  • Browser: chrome
  • Version ^0.1.3

Can I use "Arbitrary values" for variants and slots?

I would like to use the Tailwind CSS "Arbitrary values" in variants and slots, but I couldn't figure out how to write it. Is there any documents or reference code?

const styles = tv({
  variants: {
    focusable: {
      true: 'some-classes',
    },
    tabbable: {
      true: 'some-classes',
    },
  },
  compoundVariants: [
    {
      focusable: true,
      tabbable: true,
      className: `max-h-[${someArbitaryValue}]`,
    },
  ],
})

// Can you pass `someArbitaryValue` to styled?
<SomeComponent className={styles({ focusable, tabbable })} />

I couldn't figure it out from the documents so I surpassed it by writing the following.

const styles = tv({...})
const maxHeightStyle = focusable && tabbable ? `max-h-[${someArbitaryValue}]` : ''

<div className={`${styles(...)} ${maxHeightStyle}`} />

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.