Tiếng Việt

How to build a simple button component

cat.png

Author

Phước Hữu

10/18/2022

Share

logo-og.png

How to build a simple button component

Hello everyone, the day I wrote this article was a rainy day, to have such a rainy day, that cloud has accumulated a lot of water drops. Similarly, the application, the website we come into contact with daily, is also built from "small pieces of code". Here I want to mention the concept of components. And through this article, I will show you how to build a simple button component. But to understand this article you should know a little about reactjs, nextjs, and tailwindcss.

Post layout:

  1. Introduction to reactjs, components, nextjs, taitlwindcss.
  2. Set up the environment.
  3. Build components.
  4. Conclusion.

1. Introduction to reactjs, nextjs, tailwindcss, and the concept of Component.

  • React is a free and open-source front-end JavaScript library for building user interfaces based on UI components. It is maintained by Meta and a community of individual developers and companies.
  • Next.js is an open-source web development framework created by Vercel enabling React-based web applications with server-side rendering and generating static websites.
  • Tailwind CSS is an open-source CSS framework. The main feature of this library is that, unlike other CSS frameworks like Bootstrap, it does not provide a series of predefined classes for elements such as buttons or tables.

And finally the Component concept: Components let you split the UI into independent, reusable pieces, and think about each piece in isolation. We have two ways to declare components: a functional component and a class component. In this article, I will use the function component.

2. Setup environment:

Create a root folder containing files, here I name it my-app, and organize the folder as follows (icon download link: setup-env.png

public: contains image and audio resources.

src: contains the source code of the system.

components: contains the components of the system.

pages: contains the pages of the system.

vendors: contains the libraries used for the system.

and the necessary configuration files:

package.json

{
  "scripts": {
    "dev": "next dev"
  },
  "dependencies": {
    "classnames": "^2.3.2",
    "next": "^12.1.0",
    "react": "^17.0.2",
    "react-dom": "^17.0.2"
  },
  "devDependencies": {
    "@types/node": "18.7.18",
    "@types/react": "18.0.21",
    "autoprefixer": "^10.4.12",
    "postcss": "^8.4.16",
    "sass": "^1.55.0",
    "tailwindcss": "^3.1.8",
    "typescript": "4.8.3"
  }
}

postcss.config.js

module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};

tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./src/pages/**/*.{js,ts,jsx,tsx}", "./src/components/**/*.{js,ts,jsx,tsx}"],
  theme: {
    extend: {},
  },
  plugins: [],
};

tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": false,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "incremental": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve"
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
  "exclude": ["node_modules"]
}

After organizing, we open the terminal and enter the command "yarn" to install the necessary libraries.

3. Build components

To use tailwindcss, we write to the file “vendors/tailwindcss/style.scss”

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

And then write to the file _app.tsx so that your application can use tailwind.

import "../vendors/tailwindcss/style.scss";
export default function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

Now we need a page to display our component, here we have a page called HomePage written into the files pages/index.tsx.

export default function HomePage() {
  return <h1 className="text-rose-500 font-bold text-3xl">Homge Page</h1>;
}

Then run the command “yarn dev” to see if your HomePage is displayed and tailwind is working properly. Result of our home page:

step-1.png

After guiding everyone to set up and have a page to house their button component, now the main part. Together we will build a simple button component. We will write a simple component with its style as follows:

.com-button :global {
  @apply px-7 py-3 border rounded-lg text-center mx-4 text-orange-400;
}
import styles from "./style.module.scss";
const Button = () => {
  return <button className={styles["com-button"]}>Button nè</button>;
};
export default Button;

And now we bring this button to the home page to see how the Result: Result:

step-2.png

We start to ask the question, every button contains the content "Button", now what if we want the content to not only have text but can contain other things? We will add IProps to the button component so that we can use the button component more flexibly. These IProps will have children of the type Reactnode, required.

import { FC, ReactNode } from "react";
import styles from "./style.module.scss";
interface IProps {
 children: ReactNode;
}
const Button: FC<IProps> = ({ children }) => {
 return <button className={styles["com-button"]}>{children}</button>;
};
export default Button;

Now we bring it to Home to see the results:

export default function HomePage() {
  return (
  <>
   <h1 className="text-rose-500 font-bold text-3xl">Homge Page</h1>
   <br />
   <Button children={"Button 1"} />
   <Button children={"Button 2"} />
   <Button children={<img src="/images/arrow-down-circle.svg" alt="Your Name" />} />
   <Button children={<img src="/images/arrow-left-circle.svg" alt="Your Name" />} />
   <Button children={<img src="/images/arrow-right-circle.svg" alt="Your Name" />} />
   <Button children={<img src="/images/arrow-up-circle.svg" alt="Your Name" />} />
</>
);
}

Result: step-3.png

2nd question: button has many types such as button (default), submit, and reset, what should we do? So we will add the IProps of the button component and then call it using the following:

interface IProps {
  children: ReactNode;
  type?: "button" | "reset" | "submit";
}
const Button: FC<IProps> = ({ children, type = "button" }) => {
  return (
    <button className={styles["com-button"]} type={type}>
      {children}
    </button>
  );
};

Depending on the purpose of use, you will declare each corresponding type.

<Button children={"Button 1"} type="button" />
<Button children={"Button 2"} type="reset" />
<Button children={"Button 2"} type="submit" />

3rd question: now we want to pass the onClick event to the button. We will continue to pass IProps an onClick of type: “() => void”, optional.

interface IProps {
  children: ReactNode;
  type?: "button" | "reset" | "submit";
  onClick?: () => void;
}
const Button: FC<IProps> = ({ children, type = "button", onClick }) => {
  return (
    <button className={styles["com-button"]} type={type} onClick={onClick}>
      {children}
    </button>
  );
};

Depending on the purpose of use, you will declare accordingly:

<Button children={"Button 1"} onClick={() => alert("Hello World!")} />
<Button children={"Button 2"} onClick={() => setCount(count + 1)} />
<Button children={"Button 2"} onClick={handleSomethings} />

4th question: What do we do if the button has many different designs and shapes? Here I will build two styles of buttons with borders, and without borders as well as the two most visible themes are light and dark. Style files:

.com-button:global {
  @apply px-7 py-3 text-center mx-4;
  &.contained {
    @apply border text-white rounded-lg;
    &.light {
      @apply bg-rose-500;
    }
    &.dark {
      @apply bg-slate-700;
    }
  }
  &.outline {
    @apply right-1 rounded-lg;
    &.light {
      @apply text-rose-500;
    }
    &.dark {
      @apply text-slate-700;
    }
  }
}
import cls from "classnames";
interface IProps {
  children: ReactNode;
  type?: "button" | "reset" | "submit";
  theme?: "dark" | "light";
  variants?: "contained" | "outline";
  onClick?: () => void;
}
const Button: FC<IProps> = ({ children, type = "button", theme, variants, onClick }) => {
  return (
    <button className={cls(styles["com-button"], theme, variants)} type={type} onClick={onClick}>
      {children}
    </button>
  );
};
export default Button;

Use:

<Button children={"Button 1"} variants="contained" theme="dark" />
<Button children={"Button 2"} variants="contained" theme="light" />
<Button children={"Button 3"} variants="outline" theme="dark" />
<Button children={"Button 4"} variants="outline" theme="light" />

Result:

step-4.png

4. Conclusion:

From a simple Html button tag, you can build your button component. The purpose of building components is to be reusable in many places as well as to be easier to maintain later. Hopefully, after reading this article, you can imagine how to build a component as well as being able to build the components you like yourself.

Reference source:

 

Share

Contact Us