# Tailwind ## Introduction [Tailwind CSS](https://tailwindcss.com/docs/installation) is a "utility-first CSS framework".Tailwind provides hundreds of built-in classes that eliminate the need to start from scratch when creating designs. Tailwind also uses [PurgeCSS](https://v2.tailwindcss.com/docs/optimizing-for-production) to remove unused classes in production, resulting in a smaller bundle size. If you've used Bootstrap before, you'll find Tailwind easy to pick up since a lot of the classes used are similiar. ## Basic Example CSS ```typescript <div style={{ width: '12px', height: '12px', backgroundColor: '#fe1b1b' }}></div> ``` Tailwind ```typescript <div className='w-3 h-3 bg-red-500'>...</div> ``` ## Breakpoints Tailwind is utilizes a [mobile-first design](https://tailwindcss.com/docs/responsive-design). ```typescript <p className="pt-3 text-sm md:text-base xl:text-lg">...</p> ``` ## Hover, Focus, and Other States Every utility class in Tailwind can be applied conditionally by adding a [modifier](https://tailwindcss.com/docs/hover-focus-and-other-states). ```typescript <p className="bg-sky-500 hover:bg-sky-700 ">...</p> ``` These modifiers can even be stacked to target more specific situations. ```typescript <p className="bg-sky-500 md:hover:bg-sky-700 ">...</p> ``` ## Arbitrary Values What if you want to use a style that's not in the default Tailwind classes? And it's only seldom used, so you don't want to add it to our custom Tailwind config? This is where Tailwind's [arbitrary values](https://tailwindcss.com/docs/adding-custom-styles#using-arbitrary-values) come into play. ```typescript <p className="text-[28px] bg-[#6aa700]">...</p> ``` **Note:** - Before you use an arbitray value, **please make sure that the value you need isn't in the Tailwind default classes or our custom Tailwind Config first**. - If you find that the arbitrary values **will need to be used a lot** in the future, **please add it in our custom Tailwind Config**. ## Important Modifier You can make any utility **important** by adding a `!` character to the beginning: ```typescript <p className="font-bold !font-medium">...</p> ``` This is useful when we need to override old Bootstrap classes. ## Grid Example ![](https://hackmd.io/_uploads/BygIPZD2h.png) ```typescript <div className="h-[800px] flex items-center justify-center"> <div className="grid grid-cols-3 gap-4 p-4 bg-green-500 w-[300px] h-[500px]"> <div className="row-span-2 bg-green-300">1</div> <div className="bg-green-300">2</div> <div className="row-span-2 bg-green-300">3</div> <div className="bg-green-300">4</div> <div className="col-span-3 bg-green-300">5</div> </div> </div> ``` ## Grid example with Breakpoints ![](https://hackmd.io/_uploads/SyPjvZPnh.png) ```typescript <div className="h-[800px] flex items-center justify-center"> <div className="md:grid grid-cols-3 gap-4 p-4 bg-green-500 w-[300px] h-[500px]"> <div className="row-span-2 bg-green-300">1</div> <div className="bg-green-300">2</div> <div className="row-span-2 bg-green-300">3</div> <div className="bg-green-300">4</div> <div className="col-span-3 bg-green-300">5</div> </div> </div> ``` ## Config By default, Tailwind will look for an optional [tailwind.config.js](https://tailwindcss.com/docs/configuration) file at the root of your project where you can define any customizations. ### Content Because we currently use Bootstrap as well as Tailwind in our USA project (we are planning to phase-out Bootstrap but it takes time), if we enable Tailwind globally it will mess up the formatting in some places. Thus, if we add a new new page/component that needs Tailwind, we have to add it to the **Content** section: ![](https://hackmd.io/_uploads/HkYsXNj3n.png) **Glob Basic Syntax** Tailwind uses [fast-glob](https://github.com/mrmlnc/fast-glob) for pattern matching. - An asterisk (`*`) — matches everything except slashes (path separators), hidden files (names starting with `.`). - A double star or globstar (`**`) — matches zero or more directories. **Examples** Say your file structure looks like this: ``` 🗀 components 🗀 blog 🗀 categories 🞍 categories-list.tsx 🞍 categories-link.tsx 🞍 container.tsx 🞍 metadata.tsx 🗀 faq 🞍 search-result.tsx 🞍 search.tsx 🞍 footer.tsx 🞍 modal.tsx 🗀 pages 🞍 tailwind.config.js ``` - `./components/blog/**/*.{tsx,jsx,js}` — matches all files in the **components/blog** directory (any level of nesting) that have the extension **tsx**, **jsx**, or **js**. - If you want to specify just one file for example, you can write `./components/blog/categories/categories-link.tsx` ### Screens In **theme** > **screens**, we can customize our breakpoints: ![](https://hackmd.io/_uploads/rkVh5-v33.png) ### Colors In **theme** > **extend** > **colors**, we can customize our colors: ![](https://hackmd.io/_uploads/r15boZv22.png) ### Important Note - Notice how **colors** is placed within **extend**. Any config that is under **extend** means that **it is extended from the default config**. - If it's not under **extend**, it will **override the default config** and we usually don't want that. - So please make sure to add **any new config options under extend**. ![](https://hackmd.io/_uploads/rkJXa-D2h.png) ## Homework In our **iBuypower.NextJS** project, go to branch **playground**. Write the code for Homework 1 and 2 here: - pages\playground\hw-1.tsx - pages\playground\hw-2.tsx Work task: IUW-369 ### Homework 1 - Tailwind Grid Layout (no RWD required) ![](https://hackmd.io/_uploads/SkTzfzvhh.png) ### Homework 2 - Tailwind Grid Layout (with RWD) Mobile view ![](https://hackmd.io/_uploads/S1MdHzDh3.png) Tablet view ![](https://hackmd.io/_uploads/B1HXIzDhh.png) Desktop view ![](https://hackmd.io/_uploads/SJQ38Mw3h.png) ## Official Docs - https://tailwindcss.com/docs/installation --- # Classnames ## Introduction [Classnames](https://www.npmjs.com/package/classnames) is a simple JavaScript utility for conditionally joining classNames together. ## Usage Basic examples of different usage: ```typescript! classNames('foo', 'bar'); // => 'foo bar' classNames('foo', { bar: true }); // => 'foo bar' classNames({ 'foo-bar': true }); // => 'foo-bar' classNames({ 'foo-bar': false }); // => '' classNames({ foo: true }, { bar: true }); // => 'foo bar' classNames({ foo: true, bar: true }); // => 'foo bar' // lots of arguments of various types classNames('foo', { bar: true, duck: false }, 'baz', { quux: true }); // => 'foo bar baz quux' // other falsy values are just ignored classNames(null, false, 'bar', undefined, 0, 1, { baz: null }, ''); // => 'bar 1 ``` Usage with React, Tailwind, and TypeScript: ```typescript! import cn from 'classnames'; export default function ItemCard({ text, isShown = true, variant = Variant.THIN }: IItemCardProps) { return ( <div className={cn('mx-auto bg-lime-400', { 'w-80 text-sm': variant === Variant.THIN, 'text-md w-96 font-bold': variant === Variant.FAT, 'hidden': isShown === false, })} > <p>{text}</p> </div> ); } export enum Variant { THIN = 'THIN', FAT = 'FAT', } interface IItemCardProps { text: string; isShown?: boolean; variant?: Variant; } ``` # Other - $projects and config - eslint and prettierr - file naming - const - API proxy, endpoints, services - redis - preventXSS - assgined jira work tasks => explain work task specs, create new branch, git commit message, how to mark progress, QA, deploying, - answer questions