Hello all 👋
Today I will be creating a hamburger menu within react
, typescript
and tailwind css
.
First things first, before we start we will be needing a few things.
- Working machine with an IDE or text editor
- Working react environment with
typescript
andtailwind
support. (I recommend vite) - Coffee or drink of your choice. (I am going with Kofola)
Preparing props and methods
So before we actually start typing our component, I would like to create an interface for it.
For those who don't know what interface
is, basically it just is a block of code, that we use to tell us how are objects shaped.
// file: ~/components/hamburger/Hamburger.tsx
export interface HamburgerProps {
/** Callback function, which should be executed on click */
onClick: () => void;
/** Initial state of our button */
isInitiallyOpen?: boolean;
}
As you can see, we don't need much there. If you are fancy enough through, you can extend it with for example ButtonHTMLAttributes<HTMLButtonElement>
with this your component will inherit every property and methods of react button component.
Component structure
// file: ~/components/hamburger/Hamburger.tsx
...
export function Hamburger(props: HamburgerProps) {
const { onClick, isInitiallyOpen } = props;
const [isOpen, setIsOpen] = useState<boolean>(isInitiallyOpen ?? false);
const handleClick = () => {
setIsOpen(prev => !prev);
onClick();
}
return (
<button onClick={handleClick} type="button" className={``}>
<div className={``}/>
<div className={``}/>
<div className={``}/>
</button>
);
}
So there is the basic structure of our component. As you can see it's pretty straight forward, we just have a button with three div
s and a simple onClick
handler.
Styling the component
// file: ~/components/hamburger/Hamburger.tsx
...
export function Hamburger(props: HamburgerProps) {
...
return (
<button onClick={handleClick} type="button" className={`w-8 h-8 flex justify-around flex-col flex-wrap z-10 cursor-pointer`}>
<div className={`bg-black block w-8 h-[0.35rem] rounded transition-all origin-[1px]`}/>
<div className={`bg-black block w-8 h-[0.35rem] rounded transition-all origin-[1px]`}/>
<div className={`bg-black block w-8 h-[0.35rem] rounded transition-all origin-[1px]`}/>
</button>
);
}
Next, we add the effect itself.
// file: ~/components/hamburger/Hamburger.tsx
...
export function Hamburger(props: HamburgerProps) {
...
return (
<button onClick={handleClick} type="button" className={`w-8 h-8 flex justify-around flex-col flex-wrap z-10 cursor-pointer`}>
<div className={`... ${isOpen ? 'rotate-45' : 'rotate-0'}`}/>
<div className={`... ${isOpen ? 'translate-x-full bg-transparent' : 'translate-x-0'}`}/>
<div className={`... ${isOpen ? 'rotate-[-45deg]' : 'rotate-0'}`}/>
</button>
);
}
Hooray! With this done, we should be able to actually see the component in its final form.
Final code
// file: ~/components/hamburger/Hamburger.tsx
export interface HamburgerProps {
/** Callback function, which should be executed on click */
onClick: () => void;
/** Initial state of our button */
isInitiallyOpen?: boolean;
}
export function Hamburger(props: HamburgerProps) {
const { onClick, isInitiallyOpen } = props;
const [isOpen, setIsOpen] = useState<boolean>(isInitiallyOpen ?? false);
const handleClick = () => {
setIsOpen((prev) => !prev);
onClick();
};
return (
<button
onClick={handleClick}
type="button"
className={`w-8 h-8 flex justify-around flex-col flex-wrap z-10 cursor-pointer`}
>
<div
className={`bg-black block w-8 h-[0.35rem] rounded transition-all origin-[1px] ${
isOpen ? 'rotate-45' : 'rotate-0'
}`}
/>
<div
className={`bg-black block w-8 h-[0.35rem] rounded transition-all origin-[1px] ${
isOpen ? 'translate-x-full bg-transparent' : 'translate-x-0'
}`}
/>
<div
className={`bg-black block w-8 h-[0.35rem] rounded transition-all origin-[1px] ${
isOpen ? 'rotate-[-45deg]' : 'rotate-0'
}`}
/>
</button>
);
}
Using this component is very simple, all it requires is a callback function.
I like to use this setup with sidebar menu. So I have useState
with current state of sidebar and I have function to change the state. I use both of these as props for <Hamburger/>
component.
I hope I helped or entertained you enough, and please excuse the quality of this post, it is my first post here at dev.to
.
Top comments (0)