27
loading...
This website collects cookies to deliver better user experience
create-react-app
and the --template typescript
flag. Open up your terminal and then run the following command;yarn create react-app react-sidebar --template typescript
cd react-sidebar
code .
yarn start
yarn add react-router-dom @types/react-router-dom styled-components @types/styled-components react-icons @types/react-icons
components
in the src
folder of our application. Right in this folder, create the SidebarData.tsx
file and update it as shown below;import React from 'react'
import * as FaIcons from 'react-icons/fa'
export const SidebarData = [
{
title: 'Home',
path: '/',
icon: <FaIcons.FaHome />
},
{
title: 'Team',
path: '/team',
icon: <FaIcons.FaUsers />
},
{
title: 'Tasks',
path: '/tasks',
icon: <FaIcons.FaTasks />
},
{
title: 'Chats',
path: '/chats',
icon: <FaIcons.FaRocketchat />
},
{
title: 'Analytics',
path: '/analytics',
icon: <FaIcons.FaRegChartBar />
}
]
Sidebar.tsx
in the components
folder. import React from 'react'
import { Link } from 'react-router-dom'
import * as FaIcons from 'react-icons/fa'
const Sidebar: React.FunctionComponent = () => {
return (
<>
<Navbar>
<MenuIconOpen to="#">
<FaIcons.FaBars />
</MenuIconOpen>
</Navbar>
</>
)
}
export default Sidebar
App.tsx
file by importing the sidebar component so we can have a view of what it is like;import React from 'react'
import Sidebar from './components/Sidebar'
const App: React.FunctionComponent = () => {
return (
<>
<Sidebar />
</>
)
}
export default App
Sidebar.tsx
, let's create the contents for the sidebar navigation. Here, we'll import our sidebar data and then map through. Also, we'll create a sidebar component that will wrap the close icon and sidebar data. Update your code as shown below;import React from 'react'
import { Link } from 'react-router-dom'
import * as FaIcons from 'react-icons/fa'
import { SidebarData } from './SidebarData'
const Sidebar: React.FunctionComponent = () => {
return (
<>
<Navbar>
<MenuIconOpen to="#">
<FaIcons.FaBars />
</MenuIconOpen>
</Navbar>
<SidebarMenu>
<MenuIconClose to="#">
<FaIcons.FaTimes />
</MenuIconClose>
{SidebarData.map((item, index) => {
return (
<MenuItems key={index}>
<MenuItemLinks to={item.path}>
{item.icon}
<span style={{marginLeft: '16px'}}>{item.title}</span>
</MenuItemLinks>
</MenuItems>
)
})}
</SidebarMenu>
</>
)
}
export default Sidebar
Sidebar.tsx
file, let's add the following so we can style each component created;import styled from 'styled-components'
const Navbar = styled.div`
display: flex;
justify-content: start;
align-items: center;
height: 3.5rem;
background-color: #000080;
`
const MenuIconOpen = styled(Link)`
display: flex;
justify-content: start;
font-size: 1.5rem;
margin-left: 2rem;
color: #ffffff;
`
const MenuIconClose = styled(Link)`
display: flex;
justify-content: end;
font-size: 1.5rem;
margin-top: 0.75rem;
margin-right: 1rem;
color: #ffffff;
`
const SidebarMenu = styled.div<{close: boolean}>`
width: 250px;
height: 100vh;
background-color: #000080;
position: fixed;
top: 0;
left: ${({ close}) => close ? '0' : '-100%'};
transition: .6s;
`
const MenuItems = styled.li`
list-style: none;
display: flex;
align-items: center;
justify-content: start;
width: 100%;
height: 90px;
padding: 1rem 0 1.25rem;
`
const MenuItemLinks = styled(Link)`
display: flex;
align-items: center;
padding: 0 2rem;
font-size: 20px;
text-decoration: none;
color: #ffffff;
&:hover {
background-color: #ffffff;
color: #000080;
width: 100%;
height: 45px;
text-align: center;
border-radius: 5px;
margin: 0 2rem;
}
`
close
prop which was added to the SidebarMenu
above has a type definition of boolean
. Now, we'll need to pass down this prop in the main component itself like so;<SidebarMenu close={close}>
<MenuIconClose to="#">
<FaIcons.FaTimes />
</MenuIconClose>
{SidebarData.map((item, index) => {
return (
<MenuItems key={index}>
<MenuItemLinks to={item.path}>
{item.icon}
<span style={{marginLeft: '16px'}}>{item.title}</span>
</MenuItemLinks>
</MenuItems>
)
})}
</SidebarMenu>
Sidebar.tsx
file let's set the state and also create a function that will handle the opening and closing of the sidebar when the icons are clicked upon;import { useState } from 'react'
const Sidebar: React.FunctionComponent = () => {
const [close, setClose] = useState(false)
const showSidebar = () => setClose(!close)
return (
<>
<Navbar>
<MenuIconOpen to="#" onClick={showSidebar}>
<FaIcons.FaBars />
</MenuIconOpen>
</Navbar>
<SidebarMenu close={close}>
<MenuIconClose to="#" onClick={showSidebar}>
<FaIcons.FaTimes />
</MenuIconClose>
{SidebarData.map((item, index) => {
return (
<MenuItems key={index}>
<MenuItemLinks to={item.path}>
{item.icon}
<span style={{marginLeft: '16px'}}>{item.title}</span>
</MenuItemLinks>
</MenuItems>
)
})}
</SidebarMenu>
</>
)
}
export default Sidebar
src
folder of our app, create a folder named pages
. Now, in this folder create 5 separate files named; Home.tsx
, Team.tsx
, Tasks.tsx
, Chats.tsx
and Analytics.tsx
.import React from 'react'
import styled from 'styled-components
const HomeText = styled.div`
display: flex;
align-items: center;
justify-content: center;
font-size: 50px;
height: 70vh;
`
const Home: React.FunctionComponent = () => {
return (
<HomeText>Home</HomeText>
)
}
export default Home
import React from 'react'
import styled from 'styled-components'
const TeamText = styled.div`
display: flex;
align-items: center;
justify-content: center;
font-size: 50px;
height: 70vh;
`
const Team: React.FunctionComponent = () => {
return (
<TeamText>Team</TeamText>
)
}
export default Team
import React from 'react'
import styled from 'styled-components'
const TaskText = styled.div`
display: flex;
align-items: center;
justify-content: center;
font-size: 50px;
height: 70vh;
`
const Tasks: React.FunctionComponent = () => {
return (
<TaskText>Tasks</TaskText>
)
}
export default Tasks
import React from 'react'
import styled from 'styled-components'
const ChatText = styled.div`
display: flex;
align-items: center;
justify-content: center;
font-size: 50px;
height: 70vh;
`
const Chats: React.FunctionComponent = () => {
return (
<ChatText>Chats</ChatText>
)
}
export default Chats
import React from 'react'
import styled from 'styled-components'
const AnalyticsText = styled.div`
display: flex;
align-items: center;
justify-content: center;
font-size: 50px;
height: 70vh;
`
const Analytics: React.FunctionComponent = () => {
return (
<AnalyticsText>Analytics</AnalyticsText>
)
}
export default Analytics
App.tsx
file and update it like so;import React from 'react'
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Sidebar from './components/Sidebar'
import Home from './pages/Home';
import Team from './pages/Team';
import Tasks from './pages/Tasks';
import Chats from './pages/Chats';
import Analytics from './pages/Analytics';
const App: React.FunctionComponent = () => {
return (
<>
<Router>
<Sidebar />
<Routes>
<Route path='/' element={<Home />} />
<Route path='/team' element={<Team />} />
<Route path='/tasks' element={<Tasks />} />
<Route path='/chats' element={<Chats />} />
<Route path='/analytics' element={<Analytics />} />
</Routes>
</Router>
</>
)
}
export default App
Note: In react-router-rom v6 Switch
was replaced with Routes
and components
was replaced with elements
. To learn more check out this docs
src
folder, create astyles
. Then, create a global.ts
file in the styles folder and update as shown below;import { createGlobalStyle } from "styled-components";
export const GlobalStyle = createGlobalStyle`
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'Open Sans', sans-serif;
}
`
index.tsx
file and import the GlobalStyle
like so;import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import { GlobalStyle } from './styles/global';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<GlobalStyle />
<App />
</React.StrictMode>,
document.getElementById('root')
);