Hamburger Icon
  • Labs icon Lab
  • Core Tech
Labs

Guided: Styling a Next.js Finance Application with Daisy UI and Tailwind CSS

In this lab, you will style pieces of an existing Next.js application using Daisy UI and Tailwind CSS. You will become familiar with the advantages of Tailwind CSS and Daisy UI as well as address one of the main concerns of Tailwind CSS, class duplication. By the end of this lab, you should feel confident when styling other applications using these design tools.

Labs

Path Info

Level
Clock icon Beginner
Duration
Clock icon 1h 15m
Published
Clock icon Jul 02, 2024

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Table of Contents

  1. Challenge

    Introduction

    Welcome to the Guided: Daisy UI and Tailwind CSS to Style a Next.JS Finance Application lab.

    Throughout this lab, you will become familiar with how to integrate Tailwind CSS in combination with Daisy UI to an existing finance application. DaisyUI significantly reduces the effort required to build modern, responsive web interfaces by providing ready-to-use components while maintaining the flexibility and customization options offered by Tailwind CSS.

    To start, you have been given a Next.JS application without any styling in a few locations. The Next.JS application already performs data fetching and server/client component rendering. You will have the freedom to choose some of the style options from the Daisy UI and Tailwind CSS, and by the end of this course, you will have styled a navigation bar, table, and modal. You will also be familiar with how to tackle duplication introduced by Tailwind CSS and the basics of how to configure Tailwind CSS.

    You do not need any previous experience with Next.JS, Daisy UI, or Tailwind CSS to complete this lab. This lab assumes you have basic experience with React, JavaScript, JSX and CSS. Details on Next.JS, Daisy UI, and Tailwind CSS will be given to provide context for your implementations in each step.

    There is a solution directory that you can refer to if you are stuck or want to check your implementations at any time. Keep in mind that the solution provided in this directory is not the only solution, so it is acceptable for you to have a different solution so long as the application functions as intended.


    Activity

    Launch the application by entering npm run dev in the Terminal. The application can be seen in the Web Browser tab at localhost:3000. The starting application should look like the picture below:

    Starting Page

    Remember: throughout the lab, code changes will be live on the website after refreshing if the application is running. If you do however want to stop and restart the application, you can do so by typing Ctrl+C in the Terminal and rerunning npm run dev.

  2. Challenge

    Tailwind CSS Overview

    Tailwind CSS Overview

    Tailwind CSS is a utility-first CSS framework designed to enable developers to build custom user interfaces quickly and efficiently. Instead of providing pre-styled components like traditional CSS frameworks (e.g., Bootstrap), Tailwind CSS offers low-level utility classes that can be combined to create any design directly in the HTML. Here are some key aspects of Tailwind CSS:

    • Utility-First Approach: Tailwind CSS provides a large set of utility classes for common CSS properties like padding, margin, color, font size, and more. These classes can be combined to build complex designs without writing custom CSS. For example, the following div tag uses utility classes to style it.
    <div class="p-4 bg-blue-500 text-white">Hello, Tailwind!</div>
    
    • Customization: Tailwind CSS is highly customizable. Developers can extend the default theme, add custom utility classes, and configure various aspects through the configuration file (tailwind.config.js). In the future, you will configure Tailwind CSS to work hand in hand with Daisy UI. In the example below, you can see a custom color being created for an application using Tailwind CSS.
    // tailwind.config.js
    module.exports = {
      theme: {
        extend: {
          colors: {
            customBlue: '#1E3A8A',
          },
        },
      },
    }
    
    • Responsive Design: Tailwind CSS includes built-in support for responsive design with utility classes that can be applied conditionally based on breakpoints. The div tag below styles a paragraph to change sizes responsively.
    <div class="p-4 sm:p-6 lg:p-8">Responsive Padding</div>
    
    • State Variants: It supports state variants like hover, focus, active, and disabled, allowing you to style elements based on their state. The button below would change color when hovered over with a mouse.
    <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Hover Me</button>
    
    • Performance: Tailwind CSS includes a tool called PurgeCSS that removes unused CSS classes from the production build, significantly reducing the file size. You will not be using purge in this application, but you would add the configuration below if you wanted to use it in the future.
    // tailwind.config.js
    module.exports = {
      purge: ['./src/**/*.{js,jsx,ts,tsx,html}'],
      // other configurations...
    }
    
    • Component-Friendly: While Tailwind CSS itself doesn't provide pre-styled components, it works well with component libraries and frameworks like React, Vue, and Angular, making it easy to create reusable components. In this lab, you will also use Daisy UI which is built on top of Tailwind CSS to provide pre-styled components, but it is important to note that Tailwind CSS can be quickly used on any component without the use of a design library like Daisy UI. Tailwind CSS can also be used alongside a Daisy UI component to apply custom styles on the fly.

    --- ## Starting with Tailwind CSS

    The finance application you are working on already has Tailwind CSS installed as it comes by default with most Next.js applications (unless you select otherwise when creating your application).

    When you start the application using npm run dev and visit localhost:3000 in the web browser you will see the following page:

    Starting Page

    Parts of the application are already using Tailwind CSS utility classes, but they are being ignored since they cannot be found. In order to locate Tailwind CSS utility classes, the global CSS file needs to include a few Tailwind CSS directives and have none of your traditional CSS classes or styling. The global CSS must include the following directives.

    @tailwind base;
    @tailwind components;
    @tailwind utilities;
    

    These directives import Tailwind CSS in three layers. The base is Tailwind CSS’s Preflight classes that wipe any browser CSS that may be applied to HTML elements that do not have CSS. The components layer is a small layer that contains Tailwind’s component class. Lastly, the utilities layer includes the entirety of Tailwind’s utility classes. With these imports in global CSS, you can use Tailwind CSS utility classes in your HTML or JSX files.

    Once Tailwind CSS is imported in app/globals.css, you can use Tailwind CSS throughout the application in any component, and it is not necessary to have these imports in other CSS files as they will be included globally.


    Activity

    Currently, app/globals.css is an empty file.

    Import Tailwind CSS by adding the following to the app/globals.css file.

    @tailwind base;
    @tailwind components;
    @tailwind utilities;
    

    Refresh localhost:3000, you should see the app is already different as Tailwind CSS utility classes that were already being used to style existing HTML elements can be found. The application should now look like:

    Tailwind CSS Base Application

  3. Challenge

    Daisy UI Overview

    Daisy UI Overview

    Daisy UI is a popular component library built on top of Tailwind CSS. It provides a set of pre-designed, responsive, and customizable UI components that are easy to integrate and use in web projects. Daisy UI simplifies the development process by offering a wide range of styled components, such as buttons, forms, cards, and more, without the need to write extensive custom CSS.

    Here are some key features of Daisy UI:

    • Tailwind CSS Integration: Daisy UI works seamlessly with Tailwind CSS, leveraging its utility classes to provide a consistent design system.

    • Customizable Components: Components can be easily customized using Tailwind CSS classes, allowing developers to tailor them to their specific design needs.

    • Responsive Design: Components are designed to be responsive out of the box, ensuring they work well on different screen sizes.

    • Ease of Use: Daisy UI components are easy to use and can be quickly integrated into projects, reducing the time and effort required to build a polished user interface.

    • Theme Support: Daisy UI includes built-in theme support, making it simple to apply different color schemes to your project.

    --- ## Get Started with Daisy UI

    The finance application used throughout this lab already has Daisy UI installed and can be found in the package.json file.

    To use Daisy UI in the application, you must configure Tailwind CSS to require Daisy UI as a plugin.


    Activity

    Add the following to the tailwind.config.js file:

    module.exports = {
      …
      plugins: [require('daisyui')],
    }
    

    Now, Daisy UI is available throughout the application! Parts of the application were already using Daisy UI classes to style and transform certain HTML elements into Daisy UI components.

    Refresh localhost:3000, and you should now see a home page that looks like:

    Daisy UI Starting Page

  4. Challenge

    Styling the Navigation Bar Links

    Styling the Navigation Bar Links

    When you start up your application, you will see a navigation bar that looks like this:

    Application's Starting Navigation Bar


    Navigate to app/(ui)/components/nav-bar.jsx where this navigation is being created. You will be restyling this component to be a beautiful navigation bar using Daisy UI and Tailwind CSS.

    To style the navigation bar, you will begin by styling the navigation links. Follow the steps below to style the navigation links using Daisy UI and Tailwind CSS.

    1. Transform your Next.JS Link elements to be Daisy UI Button components by adding className="btn" to the Link tag. The btn class is a Daisy UI class that can be applied to any HTML tag to style it like a Button component.
      • Example Link Daisy UI Button
      	<Link href="/" className="btn">
      		Home
      	</Link>
      
      • Note: You can refresh the webpage and see that the navigation links should now look like buttons thanks to Daisy UI,
    2. Remove the | and spaces between each Link element. These were here to separate navigation elements before they were styled.
    3. Add a color of your choice to the navigation buttons using Daisy UI button color modifications. Color modifications are added to an elements class name list.
      • Example Link Daisy UI Button with Color Modifier
      	<Link href="/" className="btn btn-primary">
      		Home
      	</Link>
      
      • Here are a few Daisy UI button color modifications to pick from with an example picture and several more can be found in Daisy UI's documentation.
        • btn-neutral
        • btn-primary
        • btn-secondary
        • btn-accent
        • btn-ghost
        • btn-link
          Daisy UI Button Examples
    4. Increase the navigation button font size using a Tailwind CSS utility class. Style your Link elements with the text-xl Tailwind CSS utility class.
      • Example Link Daisy UI Button with larger text
      	<Link href="/" className="btn btn-primary text-xl">
      		Home
      	</Link>
      
      • Note: above you were able to use both Daisy UI and Tailwind CSS classes to style an HTML element. This is a great example of how Daisy UI and Tailwind CSS can be used hand in hand to style an application.

    Now, your navigation bar should look something like below except with your color of choice. This example uses btn-primary as the color modifier and the example in the solution directory uses btn-ghost.

    Extra Large Text Navigation Bar

  5. Challenge

    Styling the Navigation Bar

    Styling the Navigation Bar

    In the previous step, you styled the navigation buttons. Continue to work in app/(ui)/components/nav-bar.jsx and follow the steps below to transform the existing HTML nav element to be a Navbar Daisy UI component with Tailwind CSS custom styling.

    1. Transform the existing HTML nav element to be a Daisy UI Navbar by adding the Daisy UI navbar class.
      • Example Daisy UI Navbar
      	<nav className="navbar">
      		...
      	</nav>
      
      • Note: The application navigation bar will now look something like the picture below. You can note the left padding that was introduced when the navigation bar because a Daisy UI navigation component. Navbar Component Example with Daisy UI Buttons
    2. Use Tailwind CSS to color the background of the navigation bar so the bar stands out on the webpage. Add a Tailwind CSS background color class of your choosing to the nav element.
      • Example Daisy UI Navbar with a blue background
      	<nav className="navbar bg-sky-200">
      		...
      	</nav>
      
      • Note: Tailwind CSS is built with a lot of background color options that can be added to any HTML element using their corresponding class name. All the available background colors Tailwind offers can be found here.
      • Note: Your navigation bar should look something like the picture below after completing this step. The example below uses bg-sky-200 as its background color and the navigation bar in the solution directory uses bg-emerald-500 as its background color. Background Colored Navigation Bar
  6. Challenge

    Styling the Expenses Table

    Styling the Expenses Table

    When you visit the Expenses page on the application, you will be greeted with a table that is not styled. It should look like:

    Starting Expenses Page


    In app/(ui)/expenses/page.jsx, follow the steps below to style the existing table by transforming it into a Daisy UI Table component that has a body with a white background.

    1. Transform the existing HTML table element to be a Daisy UI Table component by styling the element with Daisy UI's table class.

      • Example Daisy UI Table Component
      	<table className="table">
      		...
      	</table>
      
      • Note: Refresh the expenses page, and the table should now look like: Daisy UI Table Component on Expenses Page
    2. Style the table body to have a white background color (use the bg-white class provided by Tailwind CSS).

      • Example Table Body with a White Background
      	<tbody className="bg-white">
      		...
      	</tbody>
      
      • Note: The white background color is different than the Daisy UI Card component the table rests on. This is what makes the table body stand out on the card.
      • Note: Your expenses page should now look like: Table Component with a Body that is a White Background
  7. Challenge

    Add a Basic Dialog to the Expenses Page

    Add a Basic Dialog to the Expenses Page

    Follow the steps below to add a Daisy UI Modal component to the ServerActionClientComponentAddTransactionForm component available at app/(ui)/components/server-action-client-component-add-transaction-form.jsx.

    1. In the top div element above the form element, add a new dialog HTML element that would display the placeholder text, "Hello".
      • Example Dialog Element
      	<dialog>Hello</dialog>
      
    2. Label the id attribute of this new dialog element to be "createExpenseModal". This id may seen robust now, but in the next step of this lab this modal be used to create a new expense and the id will be fitting.
      • Example Dialog Element with an Id
      <dialog id="createExpenseModal">Hello</dialog>
      
      • Note: When you look at the Expenses page, nothing should be different because the dialog you just added has no way to appear.
    3. In the ServerActionClientComponentAddTransactionForm component, add a new Daisy UI Button. Have the button reads "Create" since in the next step of the lab this button will serve to start the expense creation process.
      • Example Create Button
      	<button className="btn">
      		<p>Create</p>
      	</button>
      
    4. Style the button with any Daisy UI color modifier like you have done in previous steps.
      • Note: the solution directory uses the btn-accent color modifier.
    5. Style the button with Tailwind CSS margin classes and flex classes until you are happy with the location of the button on the expenses page.
      • Note: the solution directory styles the create expenses button with the following Tailwind CSS utility classes: my-2 mr-4 flex flex-row. my-2 adds a top and bottom margin of 0.5rem, or 8px and mr-4 applies a margin to only the right of the button. The other classes allow the button to be a part of a flexible layout and align itself horizontally.
    6. Style the button's p tag with Tailwind CSS utility classes until you are happy with the font and text details.
      • Note: The solution directory styles the p tag with the following classes: font-sans text-sm text-white.
    7. Program the button open the basic dialog.
      • Hint: You need to add an onClick method that calls document.getElementById("createExpenseModal").showModal(). This will show the dialog when the create button is clicked.

      • Note: The form on the expenses page may now look something like before clicking Create: Create Button On Form

      • Note: You should see a dialog that says "Hello" after clicking Create, and it should look something like: After Create has Been Clicked

      • Note: You will not be able to perform any actions on the website until you close the dialog which is currently not implemented

    8. Inside the dialog, add a Daisy UI Button to close it.
      • Hint: Inside the dialog next to the "Hello" text, add a Daisy UI Button that calls document.getElementById("createExpenseModal").close(); when clicked.
      • Note: When the dialog is open, it should now look something like the picture below and close when you click the Close. Dialog with Close Button
    Example of a Styled Create Button that Opens a Dialog
    <button
      className="my-2 mr-4 flex flex-row btn btn-accent"
      onClick={() =>
        document.getElementById("createExpenseModal").showModal()
      }
    >
      <p className="font-sans text-sm text-white">Create</p>
    </button>
    
    Example of a Dialog with a Close Button
    <dialog id="createExpenseModal">
      Hello
      <button
        className="btn"
        onClick={() => {
          document.getElementById("createExpenseModal").close();
        }}
      >
        Close
      </button>
    </dialog>
    
  8. Challenge

    Transform the Basic Dialog into a Daisy UI Modal

    Transform the Basic Dialog into a Daisy UI Modal Component

    Now that you have a dialog that can be opened and closed, follow the steps below to transform the dialog into a Daisy UI Modal component.

    1. Add Daisy UI's modal class to the dialog element.
      • Example of Daisy UI Modal Component
      	<dialog id="createExpenseModal" className="modal">
      		...
      	</dialog>
      
    2. Style the dialog content to look like a modal using Daisy UI's modal-box and modal-action classes.
      • Note: Daisy UI Modals already have styling for a modal box (the container of the content that will go in the modal) and styling for modal actions (the buttons and forms that will perform modal actions like closing the modal and creating expenses).
      1. Inside the dialog element, wrap Close button in a div tag styled with the modal-action class.
      2. Wrap the entire contents of the dialog element in another div tag styled with the modal-box class.

    If you click Create, your modal should now look like this:

    Daisy UI Modal Example

    Example Daisy UI Modal
    <dialog id="createExpenseModal" className="modal">
      <div className="modal-box">
        Hello
        <div className="modal-action">
          <button
            className="btn"
            onClick={() => {
              document.getElementById("createExpenseModal").close();
            }}
          >
            Close
          </button>
        </div>
      </div>
    </dialog>
    
  9. Challenge

    Move the Create Expense Form into the Basic Modal

    Move the Create Expense Form into the Modal

    In the previous lab step you transformed the basic dialog into a Daisy UI Modal. Follow the steps below to move the Create Expense form into the Modal.

    1. Remove the Modal's "Hello" text placeholder.
    2. Copy the form element and and its contents into the Modal's modal box section.

    Your modal should now look something like:

    Create Form in the Modal

    Example with Form in Modal Element
    <dialog id="createExpenseModal" className="modal">
      <div className="modal-box">
        <form
          action={async (formData) => {
            const transactions = await createTypeTransaction(formData);
            if (transactionPath === "/income") {
              setTransactions(transactions);
            }
          }}
          id="createTransactionForm"
        >
          <input name="date" type="date" required />
    
          <input
            name="amount"
            type="number"
            step="0.01"
            placeholder="10.00"
            required
          />
    
          <input
            name="category"
            type="text"
            placeholder="Category"
            required
          />
    
          <textarea name="notes" placeholder={"Notes"} />
    
          <input
            name="type"
            type="text"
            placeholder={"expense"}
            hidden={!!transactionType}
          />
    
          <button
            type="submit"
            className="btn float-right btn-accent font-sans text-sm text-white"
          >
            Create {transactionType ? transactionType : "Transaction"}
          </button>
        </form>
        <div className="modal-action">
          <button
            className="btn"
            onClick={() => {
    document.getElementById("createExpenseModal").close();
            }}
          >
            Close
          </button>
        </div>
      </div>
    </dialog>
    

    Close and Reset the Modal on Form Submission

    Create an expense using the Modal on the Expenses page. You will notice the Modal does not close when submitting the form. Close the Modal on form submission by following the step below.

    1. Add document.getElementById("createExpenseModal").close(); to the bottom of form's action method to close the Modal upon creating an expense.

    Create an expense again in the application and you will notice that the Modal closes upon form submission; however, if you start to create a second expense by reopening the Modal, you will notice another problem that the form's data does not reset on form submission. Follow the step below to reset form data on form submission.

    1. The form's id is createTransactionForm, so find the form element using the id and reset the data as part of the form's action.
      • Hint: Add document.getElementById("createTransactionForm").reset(); to the bottom of form's action method to reset the Modal upon creating an expense.
    Example Form Element that Can Close and Reset the Modal
    <form
      action={async (formData) => {
        const transactions = await createTypeTransaction(formData);
        if (transactionPath === "/income") {
          setTransactions(transactions);
        }
        document.getElementById("createExpenseModal").close();
        document.getElementById("createTransactionForm").reset();
      }}
      id="createTransactionForm"
    >
    	...
    </form>
    

    Lastly, on the application open the Modal, fill out the form, and close the Modal without submitting the form. Reopen the Modal and you will notice that the form's data was not reset. Follow the steps below to address this.

    1. Move the Close button into the form element underneath the form's create button.
    2. Set the Close button's type to reset to clear the form's data when you close the Modal without creating an expense.
      • Example of a Close Button on a form the resets form data when clicked
      	<button
      		className="btn"
      		type="reset"
      		onClick={() => {
      			document.getElementById("createExpenseModal").close();
      		}}
      	>
      		Close
      	</button>
      
    3. Remove the Modal's modal-action section as it now is empty.
    Example Create Expense Dialog After the Above Steps
    <dialog id="createExpenseModal" className="modal">
      <div className="modal-box">
        <form
          action={async (formData) => {
            const transactions = await createTypeTransaction(formData);
            if (transactionPath === "/income") {
              setTransactions(transactions);
            }
            document.getElementById("createExpenseModal").close();
            document.getElementById("createTransactionForm").reset();
          }}
          id="createTransactionForm"
        >
          <input name="date" type="date" required />
    
          <input
            name="amount"
            type="number"
            step="0.01"
            placeholder="10.00"
            required
          />
    
          <input
            name="category"
            type="text"
            placeholder="Category"
            required
          />
    
          <textarea name="notes" placeholder={"Notes"} />
    
          <input
            name="type"
            type="text"
            placeholder={"expense"}
            hidden={!!transactionType}
          />
    
          <button
            type="submit"
            className="btn float-right btn-accent font-sans text-sm text-white"
          >
            Create {transactionType ? transactionType : "Transaction"}
          </button>
          <button
            className="btn"
            type="reset"
            onClick={() => {
              document.getElementById("createExpenseModal").close();
            }}
          >
            Close
          </button>
        </form>
      </div>
    </dialog>
    

    You should now have a blank form whenever you create an expense or close the modal without creating an expense. Try it out in the web browser to verify.

  10. Challenge

    Tailwind CSS Forms

    Configure the Application to Use Tailwind CSS Forms

    In this step of the lab, you will update the create expense form from the previous step to be a Tailwind CSS Form.

    Tailwind CSS Forms are available as a plugin and are not brought into a Tailwind CSS application by default. The Tailwind CSS Forms plugin has already been installed for you, but the application is not yet configured to use them. Configure the application to use Tailwind CSS Forms by following the instruction below.

    1. Adding @tailwindcss/forms to the plugin list in tailwind.config.js.

      • The application plugin configuration should now look something like below now as you added the Daisy UI plugin in a previous lab step:
      	module.exports = {
      		…
      		plugins: [require('daisyui'), require("@tailwindcss/forms")],
      	}
      

    Update the Create Expense Form to be a Tailwind CSS Form

    Transforming the create expense form into a Tailwind CSS Form is as simple as styling with Tailwind CSS. The table below provides some of the relevant class names based on the create expense form's input types. Follow the instruction under the table to transform the create expense form into Tailwind CSS Form and style the form.

    | Base | Class | | -------- | ------- | | [type='text'] | form-input | | [type='number'] | form-input | | [type='date'] | form-input | | textarea | form-textarea |

    1. Add the correct class to each of the create expense form's inputs based based on the input's type.
    2. Style the create expense form's inputs using Tailwind CSS utility classes until you are happy with the design. Relevant classes may change padding, border radius, margin, and width. You can reference Tailwind CSS documentation for more class ideas if you need to.
      • For reference, the form in the solution directory applies the following classes to all form inputs: px-4 rounded mb-5 w-full.

    Your form should now look something like:

    Tailwind CSS Form

    Example Tailwind CSS Form
    <form
      action={async (formData) => {
        const transactions = await createTypeTransaction(formData);
        if (transactionPath === "/income") {
          setTransactions(transactions);
        }
        document.getElementById("createExpenseModal").close();
        document.getElementById("createTransactionForm").reset();
      }}
      id="createTransactionForm"
      className="w-full"
    >
      <input className="formInput px-4 rounded mb-5 w-full" name="date" type="date" required />
    
      <input
        className="formInput px-4 rounded mb-5 w-full"
        name="amount"
        type="number"
        step="0.01"
        placeholder="10.00"
        required
      />
    
      <input
        className="formInput px-4 rounded mb-5 w-full"
        name="category"
        type="text"
        placeholder="Category"
        required
      />
    
      <textarea
        className="form-textarea px-4 pxy-3 rounded w-full"
        name="notes"
        placeholder={"Notes"}
      />
    
      <input
        name="type"
        type="text"
        placeholder={"expense"}
        hidden={!!transactionType}
        className="formInput px-4 rounded mb-5 w-full"
      />
      <button
        type="submit"
        className="btn float-right btn-accent font-sans text-sm text-white"
      >
        Create {transactionType ? transactionType : "Transaction"}
      </button>
      <button
        className="btn"
        type="reset"
        onClick={() => {
          document.getElementById("createExpenseModal").close();
        }}
      >
        Close
      </button>
    </form>
    
  11. Challenge

    Duplication While Using Tailwind CSS

    Duplication While Using Tailwind CSS

    One of the largest concerns with Tailwind CSS is the potential for a lot of duplication. You will start this step by seeing how this issue can come to life while styling an application with Tailwind CSS. Follow the steps below to add labels to the create expense form and style the new labels.

    1. Add a label for each create expense form input.
      • Example Label for date `input
      	<label htmlFor="date">Date</label>
      	<input name="date" type="date" required />
      
      • Note: The input's name and the label's htmlFor properties match.
    2. Style each label with the following set of Tailwind CSS utilitiy classes: block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2.
      • Note: Your form will now look like something like: Form with Labels
    Form with Labels Example
    <form
      action={async (formData) => {
        const transactions = await createTypeTransaction(formData);
        if (transactionPath === "/income") {
          setTransactions(transactions);
        }
        document.getElementById("createExpenseModal").close();
        document.getElementById("createTransactionForm").reset();
      }}
      id="createTransactionForm"
      className="w-full"
    >
      <label className={formLabelTailwindCSS} htmlFor="date">
        Date
      </label>
      <input className="formInput" name="date" type="date" required />
    
      <label className={formLabelTailwindCSS} htmlFor="amount">
        Amount
      </label>
      <input
        className="formInput"
        name="amount"
        type="number"
        step="0.01"
        placeholder="10.00"
        required
      />
    
      <label className={formLabelTailwindCSS} htmlFor="category">
        Catgeory
      </label>
      <input
        className="formInput"
        name="category"
        type="text"
        placeholder="Category"
        required
      />
      <label className={formLabelTailwindCSS} htmlFor="notes">
        Notes
      </label>
      <textarea
        className="form-textarea px-4 pxy-3 rounded w-full"
        name="notes"
        placeholder={"Notes"}
      />
      <label
        className={classNames(formLabelTailwindCSS(), {
          invisible: !!transactionType,
        })}
        htmlFor="type"
      >
        Transaction Type
      </label>
      <input
        name="type"
        type="text"
        placeholder={"expense"}
        hidden={!!transactionType}
        className="formInput"
      />
      <button
        type="submit"
        className="btn float-right btn-accent font-sans text-sm text-white"
      >
        Create {transactionType ? transactionType : "Transaction"}
      </button>
      <button
        className="btn"
        type="reset"
        onClick={() => {
          document.getElementById("createExpenseModal").close();
        }}
      >
        Close
      </button>
    </form>
    

    Above, you added form labels that you wanted to be styled with all the same Tailwind CSS classes for design consistency. However, it might have felt tedious typing out the same classes for each label. It is encouraged to see this duplication issue as part of your larger code setup instead of one brought to you by Tailwind CSS.


    Address the Styling Duplication Introduced Above and Examine Other Ways the Solution Addresses Styling Duplication

    You can address this Tailwind CSS className duplication in a few different ways.

    • You can extract a method that simply returns the class string and use that for the value of every label’s className attribute.
    • You can extract a React component called something like CreateExpenseFormLabel that is a form label with styling and renders children and render that component in the form for each label.
    • Lastly, Tailwind CSS also uses the @apply directive for duplication. In CSS files, you can use the @apply directive to use Tailwind classes in the definition of other CSS selectors.

    Take some time to explore each of these options to avoid the label duplication introduced above. This is a self-guided exercise in this lab environment.

    The solution directory contains a version of the app directory that has an example for each way to combat duplication above. Read more about the examples below to find them in the solution directory if you are interested in previewing them.

    • The label class duplication introduced in this lab step is solved in the solution directory's app using an extracted method that returns the styling class string.
    • The Home page uses a Header component to display its title. This Header component could be reused on the Income and Expenses pages to avoid duplication in styling. Look at solution/app/page.js, solution/app/(ui)/components/header.jsx, solution/app/income/page,jsx, and solution/app/expenses/page,jsx.
    • Just like you saw class duplication on the form labels in the step of the lab, in the solution, there was also class duplication on the form inputs. The solution directory's app uses the @apply directive on a class in solution/app/global.css to create a CSS class that is applied all form inputs.
  12. Challenge

    Tailwind CSS Configuration

    Tailwind CSS Configuration

    The tailwind.config.js file is where the configuration for Tailwind CSS resides. In previous steps, you have added plugins to the configuration of Tailwind CSS. A minimal configuration file looks like this:

    module.exports = {
      future: {},
      purge: [],
      theme: {
        extend: {},
      },
      variants: {},
      plugins: [],
    };
    

    Tailwind CSS considers each family of utilities to be a core plugin. Here is a list of all Tailwind CSS core plugins.

    The theme object in Tailwind CSS configuration is helpful to define overarching design themes within your application. It can be used to customize core plugins. This can include overriding all of the core plugins options and extending those options.

    To override all of a core plugins options, you would provide a new set of values for it in theme. Below is an example of overriding the screens core plugin. This example could be useful if you wanted to completely replace all of the screen breakpoints with custom or reworked ones.

    theme: {
      screens: {
        'phone': '600px',
        'laptop': '1280px',
      }
    }
    

    With the above theme you could start using phone and laptop as Tailwind CSS utility classes.

    If you did not want to override all of a core plugin's values, you can keep the existing values and extend that core plugin.

    The configuration file can also be used to exclude utility classes from being generated (if you needed it for performance reasons), configure variant prefixes (things like active, checked, and hover), and so much more. Tailwind CSS even has a way to prune off all the utility classes you did not use in an application by using the purge option in the configuration.

    You may reference Tailwind’s documentation for configuration for more details.


    Activity

    The finance application you have been working on throughout this lab already references two custom colors on the Home page's transaction table. The application has not been able to use these custom colors because it has been unable to find the definition to them. The Home page's table currently looks like:

    Home Page without Custom Colors

    Extend the color core plugin to include them.

    In tailwind.config.js, add the code below to the configuration object.

    theme: {
      extend: { colors: { "light-red": "#f54248", "light-green": "#42f59b" } },
    },
    

    The home page's table should now look like:

    Home Page with Custom Colors

    For reference, the transaction table now highlights expense rows with a red color and income rows with a green color. You added the custom red and green colors to the configuration.

Jaecee is an associate author at Pluralsight helping to develop Hands-On content. Jaecee's background in Software Development and Data Management and Analysis. Jaecee holds a graduate degree from the University of Utah in Computer Science. She works on new content here at Pluralsight and is constantly learning.

What's a lab?

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Provided environment for hands-on practice

We will provide the credentials and environment necessary for you to practice right within your browser.

Guided walkthrough

Follow along with the author’s guided walkthrough and build something new in your provided environment!

Did you know?

On average, you retain 75% more of your learning if you get time for practice.