React+TailwindCSS template
Author : JaNakh Pon , August 09, 2021
Tags
Intro
We are going to set up TailwindCSS in create-react-app with TypeScript and build a simple responsive todo template with pagination🔥.
Step 1 (Installation)
Let's get started by generating a react app using create-react-app:
> npx create-react-app tailwindreacttodo --template typescript
> cd tailwindreacttodo
Now we have a react app with typescript, so let's install dependencies for TailwindCSS:
> npm install -D tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9
And now let's install craco(Create React App Configuration Override):
> npm install @craco/craco
Now, it's time to make some changes in package.json because we want to use craco instead of react-scripts,
"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test",
"eject": "react-scripts eject"
},
Next, create a craco.config.js at the root of our project and add the tailwindcss and autoprefixer as PostCSS plugins:
// craco.config.js
module.exports = {
style: {
postcss: {
plugins: [
require('tailwindcss'),
require('autoprefixer'),
],
},
},
}
Next, generate your tailwind.config.js file:
> npx tailwindcss-cli@latest init
and configure the purge[] for Tailwind to remove unused styles in production,
// tailwind.config.js
module.exports = {
purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [],
}
And now, let's include tailwind to our main css file(index.css):
/* ./src/index.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
Step 2 (Design Thinking)
Now, if we think about a simple single page todo app interface, we can imagine it in three parts:
- Interactive Form
- List of tasks/ Container of tasks
- Pagination
Since using TailwindCSS is unlike using components based UI libraries(bootstrap, material-ui, semantic-ui, ...etc) and more like writing vanilla CSS: we are going to use grid and flex even though it's just a simple single page todo ui.
Step 3 (Implementation)
For more informations about css class read tailwind documentation here. First, let's create a main container to wrap the three components. we want to use a simple container and set margin left right to auto but we want to keep a certain distance for margin top and bottom:
const App = () => {
return (
<div className="container mx-auto lg:my-32 md:my-30 sm:my-15 ">
{/* 3 components go here */}
</div>
);
}
export default App;
Interactive form/ Interactive Component
For Interactive form/component we might need:
- Input field for creating/saving new task/todo
- Input field for searching task/todo
- select boxes for sorting by properties in ascending or descending order
So, we might want to use display:flex for that:
const InteractiveComponent = () => {
return (
<>
<div className="flex justify-center m-5">
<section className="w-10/12 sm:w-10/11 lg:w-1/2 max-w-2xl flex flex-col items-center">
<form className="flex justify-between w-full">
<input type="text" placeholder={`write things down here ...`} />
</form>
</section>
</div>
<div className="flex justify-center m-5">
<section className="w-10/12 sm:w-10/11 lg:w-1/2 max-w-2xl flex flex-col items-center">
<form className="flex justify-between w-full">
<div className=" w-full relative text-gray-700">
<input className="w-full h-10 pl-8 pr-3" type="text" placeholder="search here .." />
<div className="absolute inset-y-0 left-0 flex items-center px-2 pointer-events-none">
<svg className="w-4 h-4 fill-current" viewBox="0 0 20 20">
<path d="M18.125,15.804l-4.038-4.037c0.675-1.079,1.012-2.308,1.01-3.534C15.089,4.62,12.199,1.75,8.584,1.75C4.815,1.75,1.982,4.726,2,8.286c0.021,3.577,2.908,6.549,6.578,6.549c1.241,0,2.417-0.347,3.44-0.985l4.032,4.026c0.167,0.166,0.43,0.166,0.596,0l1.479-1.478C18.292,16.234,18.292,15.968,18.125,15.804 M8.578,13.99c-3.198,0-5.716-2.593-5.733-5.71c-0.017-3.084,2.438-5.686,5.74-5.686c3.197,0,5.625,2.493,5.64,5.624C14.242,11.548,11.621,13.99,8.578,13.99 M16.349,16.981l-3.637-3.635c0.131-0.11,0.721-0.695,0.876-0.884l3.642,3.639L16.349,16.981z"></path>
</svg>
</div>
</div>
<select>
<option className="p-1">updated_at</option>
<option className="p-1">created_at</option>
<option className="p-1">id</option>
<option className="p-1">title</option>
</select>
<select>
<option className="p-1">ASC</option>
<option className="p-1">DESC</option>
</select>
</form>
</section>
</div>
</>
)
}
export default InteractiveComponent;
List of tasks
For displaying list of tasks, might want to use a combination for grid and flex, Grid will be using as a wrapping container and Flex will be used in each Item of the list. Btw, my combination is not a good looking one!😂:
const TasksComponent = () => {
return (
<>
<div className="grid grid-flow-row auto-rows-max lg:mt-5 sm:mt-2">
<div className="flex justify-center mx-8">
<section className="w-10/12 sm:w-10/11 lg:w-1/2 max-w-2xl">
<p className="text-sm font-medium">Found 4 tasks!</p>
</section>
</div>
<div className="flex justify-center mt-10 mx-8">
<section className="w-10/12 sm:w-10/11 lg:w-1/2 max-w-2xl">
<h2 className="font-bold ml-2">Lorem Ipsum, <span className="font-light text-sm">2 days ago</span></h2>
<input type="checkbox" />
<span className="text-left text-sm leading-3 tracking-wider px-1">
Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts and visual mockups
| <span className="cursor-pointer hover:uppercase hover:font-bolder hover:text-red-500" > remove?</span></span>
</section>
</div>
<div className="flex justify-center mt-10 mx-8">
<section className="w-10/12 sm:w-10/11 lg:w-1/2 max-w-2xl">
<h2 className="font-bold ml-2">Lorem Ipsum, <span className="font-light text-sm">2 days ago</span></h2>
<input type="checkbox" />
<span className="text-left text-sm leading-3 tracking-wider px-1">
Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts and visual mockups
| <span className="cursor-pointer hover:uppercase hover:font-bolder hover:text-red-500" > remove?</span></span>
</section>
</div>
<div className="flex justify-center mt-10 mx-8">
<section className="w-10/12 sm:w-10/11 lg:w-1/2 max-w-2xl">
<h2 className="font-bold ml-2">Lorem Ipsum, <span className="font-light text-sm">2 days ago</span></h2>
<input type="checkbox" />
<span className="text-left text-sm leading-3 tracking-wider px-1">
Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts and visual mockups
| <span className="cursor-pointer hover:uppercase hover:font-bolder hover:text-red-500" > remove?</span></span>
</section>
</div>
<div className="flex justify-center mt-10 mx-8">
<section className="w-10/12 sm:w-10/11 lg:w-1/2 max-w-2xl">
<h2 className="font-bold ml-2">Lorem Ipsum, <span className="font-light text-sm">2 days ago</span></h2>
<input type="checkbox" />
<span className="text-left text-sm leading-3 tracking-wider px-1">
Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts and visual mockups
| <span className="cursor-pointer hover:uppercase hover:font-bolder hover:text-red-500" > remove?</span></span>
</section>
</div>
</div>
</>
)
}
export default TasksComponent;
Pagination
For Pagination, we want to have buttons in a row and make them look good in center?.. we might also want to use flex for positioning items in a row
const PaginationComponent = () => {
return (
<>
<div className="flex justify-center mt-10 mx-8">
<section className="w-10/12 sm:w-10/11 lg:w-1/2 max-w-2xl flex justify-center">
<nav aria-label="Page navigation">
<ul className="inline-flex space-x-2">
<li>
<button className={`w-10 h-10 text-white transition-colors duration-150 bg-gray-500 border border-r-0 border-gray-500 rounded-full focus:shadow-outline`} >1</button>
</li>
<li>
<button className={`w-10 h-10 transition-colors duration-150 rounded-full focus:shadow-outline hover:bg-gray-100`} >2</button>
</li>
<li>
<button className={`w-10 h-10 transition-colors duration-150 rounded-full focus:shadow-outline hover:bg-gray-100`}>3</button>
</li>
</ul>
</nav>
</section>
</div>
</>
)
}
export default PaginationComponent;
Not very much of an explaination right? 😹 Don't worry 😉, get the source code down below and use it as an example and build a new one out of it while referencing TailwindCSS amazing doc!!!.
Go Back.