2024May

“cn” utility function in shadcn-ui/ui:

When I saw the cn function being imported from @/lib/utils in shadcn-ui/ui source code, I assumed that this function’s name is derived from “shadcn” since it contains “cn’’and that it handles some core logic but turns out, it is a wrapper on top of clsx and twMerge. I questioned, Why? Why would you need such a wrapper?

To understand the reason behind this cn wrapper, you must first understand clsx and tailwind-merge.

Clsx

Clsx official docs definition is that it is a tiny (239B) utility for constructing className strings conditionally.

Also serves as a faster & smaller drop-in replacement for the classnames module.

Build shadcn-ui/ui from scratch.

Examples:

import clsx from 'clsx';
// or
import { clsx } from 'clsx';
 
// Strings (variadic)
clsx('foo', true && 'bar', 'baz');
//=> 'foo bar baz'
 
// Objects
clsx({ foo:true, bar:false, baz:isTrue() });
//=> 'foo baz'
 
// Objects (variadic)
clsx({ foo:true }, { bar:false }, null, { '--foobar':'hello' });

We all are familiar with the clsx package, it is used to render the classnames conditionally.

Tailwind-merge:

To be honest, I have never used the tailwind-merge package before. So I visited the official docs and learnt that it is a utility function to efficiently merge Tailwind CSS classes in JS without style conflicts.

Example:

import { twMerge } from 'tailwind-merge'
 
twMerge('px-2 py-1 bg-red hover:bg-dark-red', 'p-3 bg-[#B91C1C]')
// → 'hover:bg-dark-red p-3 bg-[#B91C1C]'

Connecting the dots:

It was at this point, it occurred to me that in shadcn-ui, clsx conditionally renders tailwind class names as strings and doing so could result in tailwind class name conflicts

Cn usage in shadcn-ui/ui:

I found the following files using cn function

https://github.com/search?q=repo%3Ashadcn-ui%2Fui+cn&type=code

About me:

Hey, my name is Ramu Narasinga. I study large open-source projects and create content about their codebase architecture and best practices, sharing it through articles, videos.

I am open to work on interesting projects. Send me an email at ramu.narasinga@gmail.com

My Github —  https://github.com/ramu-narasinga

My website —  https://ramunarasinga.com

My Youtube channel —  https://www.youtube.com/@ramu-narasinga

Learning platform —  https://thinkthroo.com

Codebase Architecture —  https://app.thinkthroo.com/architecture

Best practices —  https://app.thinkthroo.com/best-practices

Production-grade projects —  https://app.thinkthroo.com/production-grade-projects

References:

  1. https://github.com/shadcn-ui/ui/blob/main/apps/www/app/layout.tsx

  2. https://github.com/shadcn-ui/ui/blob/main/apps/www/lib/utils.ts

  3. https://www.npmjs.com/package/tailwind-merge

  4. https://github.com/dcastil/tailwind-merge/blob/main/src/lib/create-tailwind-merge.ts

  5. https://github.com/dcastil/tailwind-merge/blob/main/src/lib/merge-classlist.ts#L6

We use cookies
We use cookies to ensure you get the best experience on our website. For more information on how we use cookies, please see our cookie policy.

By clicking "Accept", you agree to our use of cookies.

Learn more