Use a style for react.js map without using CSS - css

So I have this css code:
.tab-top {
padding-left: 12%;
padding-top: 2%;
color: var(--cloudy-white);
display: flex;
flex-direction: row;
font-family: "NTR Regular";
font-size: 15px;
}
.tab-top > div {
text-align: center;
margin-left: 3%;
border: 1px red solid;
}
How would I do this in react.js with the following code:
function Navigation() {
const topTabs = tabs.map(tab =>
<div>
{tab}
</div>
);
return (
<div className="tab-top">
{topTabs}
</div>
);
}
(tabs is declared)
Also I'm fairly new to react.js so if I can improve the following code in any way please leave suggestions.

you can use style of react if you want create mutiple css style do like this
function Navigation() {
const styles={ tabtop:{
textAlign: "center",
marginLeft: "2%",
marginTop: "1%",
},
anohter:{ width:"100%"},
}
const topTabs = tabs.map(tab =>
<div>
{tab}
</div>
);
return (
<div style={styles.tabtop}>
{topTabs}
</div>
);
}
or you can do it like that for single usage
function Navigation() {
const topTabs = tabs.map(tab =>
<div>
{tab}
</div>
);
return (
<div style={{
textAlign: "center",
marginLeft: "2%",
marginTop: "1%",
}}>
{topTabs}
</div>
);
}
or
i think it should be like this
import React from "react";
import styled from "styled-components";
const Thing = styled.div.attrs(() => ({ tabIndex: 0 }))`
.tab-top {
padding-left: 12%;
padding-top: 2%;
color: var(--cloudy-white);
display: flex;
flex-direction: row;
font-family: "NTR Regular";
font-size: 15px;
}
.tab-top > div {
text-align: center;
margin-left: 3%;
border: 1px red solid;
}
`;
function Navigation() {
const topTabs = tabs.map(tab =>
<div>
{tab}
</div>
);
return (
<Thing className="tab-top">
{topTabs}
</Thing>
);
}

Related

Mobile Dropdown Design Next.js (CSS or Tailwind)

I want to make my mobile menu have a dropdown when the main labels are clicked as they do for the regular desktop navigation. The dropdown works for the mobile menu, but it displays it on the left side of the main label. What I want it to do is expand or toggle/show underneath the top label when clicked if that makes sense. An example would be the mobile menu here: https://www.youtube.com/watch?v=JEV7WE0UBiQ&t=2738s, but in my case, I only need to go one dropdown deep.
Here are my Navbar and Dropdown components for review. I also provided the relevant CSS as well.
I know there is much to be improved and there are other small errors I am getting, but if I can get help on this part, that would be great. I've actually been using the help of ChatGPT to assist with some things, but it can only get me so far. Sometimes it's great, and other times I just want to punch it, lol!
import React, { useState } from "react";
import Link from "next/link";
import Dropdown from "./Dropdown";
import { menuItems, mobileMenuItems } from "./MenuItems";
// Import the FontAwesomeIcon component
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
// import the icons you need
import {
faChevronDown,
faBars,
faXmark,
} from "#fortawesome/free-solid-svg-icons";
function Navbar() {
const [click, setClick] = useState(false);
const [dropdownOpen, setDropdownOpen] = useState({
dropdown1: false,
dropdown2: false,
dropdown3: false,
});
const handleClick = () => {
setClick(!click);
setDropdownOpen({ dropdown1: false, dropdown2: false, dropdown3: false });
};
const closeMobileMenu = () => {
setClick(false);
setDropdownOpen({ dropdown1: false, dropdown2: false, dropdown3: false });
};
const toggleDropdown = (dropdown) => {
if (window.innerWidth < 950) {
setDropdownOpen({ [dropdown]: !dropdownOpen[dropdown] });
} else {
setDropdownOpen({ [dropdown]: !dropdownOpen[dropdown] });
}
};
return (
<nav>
<div className="container mx-auto px-10 mb-8">
<div className="relative border-b w-full inline-block border-blue-400 py-8">
<div className="absolute inset-y-0 left-0 flex items-center sm:hidden">
{/* Mobile menu button*/}
<button
className="inline-flex p-2 rounded-md text-gray-400 hover:text-white hover:bg-violet-700 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white text-3xl md:hidden"
onClick={() => {
setClick(!click);
}}
>
<FontAwesomeIcon icon={click ? faXmark : faBars} />
</button>
</div>
<div className="flex-1 flex items-center justify-center sm:items-stretch sm:justify-start">
<div className="flex-1 flex flex-shrink-0 flex px-12 items-center ">
<h1 className="font-bold text-4xl cursor-pointer text-white">
My<span className="text-blue-500">site</span>
</h1>
</div>
<div className="hidden md:float-left md:contents">
<ul className="nav-menu">
{menuItems.map((link, index) => (
<li
key={index}
className="nav-item"
onMouseEnter={
link.dropdownType
? () => toggleDropdown(link.dropdownType)
: null
}
onMouseLeave={
link.dropdownType
? () => toggleDropdown(link.dropdownType)
: null
}
>
<Link href={link.href}>
<a className="menuItems nav-links">
{link.icon && (
<FontAwesomeIcon
className="px-2"
icon={link.icon}
style={{ fontSize: 20, color: link.color }}
/>
)}
{link.label}
{link.dropdownType && (
<span className="faChevronDown">
<FontAwesomeIcon
icon={faChevronDown}
></FontAwesomeIcon>
</span>
)}
</a>
</Link>
{link.dropdownType && dropdownOpen[link.dropdownType] && (
<Dropdown type={link.dropdownType} />
)}
</li>
))}
</ul>
</div>
</div>
</div>
</div>
{/* ----------------------Hamburger Menu----------------------- */}
<ul
className={click ? "mobileNav-menu active" : "sm:hidden mobileNav-menu"}
>
{mobileMenuItems.map((link, index) => (
<li key={index} className="nav-item">
<Link href={link.href}>
<a
onClick={
link.dropdownType
? () => toggleDropdown(link.dropdownType)
: closeMobileMenu
}
className="menuItems nav-links dropdown-toggle"
>
{link.icon && (
<FontAwesomeIcon
className="px-2"
icon={link.icon}
style={{ fontSize: 20, color: link.color }}
/>
)}
{link.label}
{link.dropdownType && (
<span className="faChevronDown">
<FontAwesomeIcon icon={faChevronDown}></FontAwesomeIcon>
</span>
)}
</a>
</Link>
{link.dropdownType && dropdownOpen[link.dropdownType] && (
<ul className="dropdown-menu">
<Dropdown type={link.dropdownType} onClick={closeMobileMenu} />
</ul>
)}
</li>
))}
</ul>
</nav>
);
}
export default Navbar;
and the Dropdown component
import React, { useState, useEffect } from "react";
import Link from "next/link";
import {
getFeaturedArticlesCategories,
getNewsCategories,
getReviewsCategories,
} from "../services";
function useCategories() {
const [categories, setCategories] = useState({
featured: [],
news: [],
reviews: [],
});
useEffect(() => {
let cancel = false;
const fetchCategories = async () => {
const featured = await getFeaturedArticlesCategories();
const news = await getNewsCategories();
const reviews = await getReviewsCategories();
if (!cancel) {
setCategories({ featured, news, reviews });
}
};
fetchCategories();
return () => {
cancel = true;
};
}, []);
return categories;
}
function Dropdown({ type, onClick }) {
const [click, setClick] = useState(false);
const categories = useCategories();
const handleClick = () => setClick(!click);
return (
<>
<ul
onClick={() => {
handleClick();
onClick();
}}
className={click ? "dropdown-menu clicked" : "dropdown-menu"}
>
{categories[type].map((item, { active }) => (
<Link href={`/${type}/${item.slug}`} key={item.slug}>
<a
className={`group flex justify-center items-center px-4 py-2 text-sm font-semibold cursor-pointer ${
active
? "text-gray-700"
: "menuItems hover:bg-indigo-500 transition-all duration-500 ease-in"
}`}
>
{item.name}
</a>
</Link>
))}
</ul>
</>
);
}
export default Dropdown;
and the CSS
//Nav Menu
.menuItems {
&:hover {
color: rgb(255, 0, 0);
}
}
.navbar {
width: 90%;
height: 6rem;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.2rem;
padding-left: 2.5rem;
padding-right: 2.5rem;
margin-left: auto;
margin-right: auto;
margin-bottom: 5rem;
border-bottom-width: 1px;
border-color: #60a5fa;
}
.navbar-logo {
color: #fff;
justify-self: start;
margin-left: -1rem;
cursor: pointer;
text-decoration: none;
line-height: 2.5rem;
font-size: 2.25rem;
font-weight: 700;
}
.nav-menu {
display: grid;
grid-template-columns: repeat(5, auto);
grid-gap: 1rem;
list-style: none;
text-align: center;
width: 70vw;
justify-content: end;
margin-right: 2rem;
}
.nav-item {
display: flex;
align-items: center;
height: 4rem;
}
.nav-links {
color: white;
text-decoration: none;
padding: 0.5rem 1rem;
display: inline-flex;
font-weight: 600;
justify-content: center;
width: 100%;
cursor: pointer;
}
.nav-links:hover {
background-color: #1888ff;
border-radius: 4px;
transition: all 0.2s ease-out;
}
.faBars {
color: #fff;
}
.nav-links-mobile {
display: none;
}
.menu-icon {
display: none;
}
#media screen and (max-width: 950px) {
.NavbarItems {
position: relative;
}
.mobileNav-menu {
display: flex;
flex-direction: column;
width: 100%;
height: 90vh;
position: absolute;
padding-top: 5rem;
padding-bottom: 15rem;
padding-left: 1rem;
bottom: 0;
top: 5rem;
left: -100%;
opacity: 1;
transition: all 0.5s ease;
}
.mobileNav-menu.active {
background: #242222;
left: 0;
opacity: 1;
transition: all 0.5s ease;
z-index: 1;
}
.nav-links {
text-align: center;
padding: 2rem;
width: 100%;
display: table;
}
.nav-links:hover {
background-color: #1888ff;
border-radius: 0;
}
.navbar-logo {
position: absolute;
top: 0;
left: 0;
transform: translate(25%, 50%);
}
.menu-icon {
display: block;
position: absolute;
top: 0;
right: 0;
transform: translate(-100%, 60%);
font-size: 1.8rem;
cursor: pointer;
}
.faXmark {
color: #fff;
font-size: 2rem;
}
.faChevronDown {
margin-left: 0.5rem;
padding: 0.5rem;
}
.nav-links-mobile {
display: block;
text-align: center;
padding: 1.5rem;
margin: 2rem auto;
border-radius: 4px;
width: 80%;
background: #1888ff;
text-decoration: none;
color: #fff;
font-size: 1.5rem;
}
.nav-links-mobile:hover {
background: #fff;
color: #1888ff;
transition: 250ms;
}
}
//Dropdown
.dropdown-menu {
background: rgb(184, 183, 231);
width: 10rem;
position: absolute;
border-radius: 0.375rem;
top: 6rem;
list-style: none;
text-align: start;
z-index: 10;
}
.dropdown-menu li {
background: #1888ff;
cursor: pointer;
}
.dropdown-menu li:hover {
background: #5cabff;
}
.dropdown-menu.clicked {
display: none;
}
.dropdown-link {
display: block;
height: 100%;
width: 100%;
text-decoration: none;
color: #fff;
padding: 16px;
}

Hiding Side Nav in Hamburger Menu

I have a sidebar, that I would like to collpase on mobile devices, and only be accessed on mobile using a hamburger menu
Using React, what is the best way for me to do so? Would this still be media queriers, or is there an alternate way that would make this type of configuration more seamless?
Please note that I only want the sidebar to collapse on mobile. I do not want to give the user the ability to collpase the sidebar when viewed on desktop.
Sidebar.Js
const sidebarNavItems = [
{
display: 'Home',
to: '/'
},
{
display: 'Blog',
to: 'Blog/'
},
{
display: 'Contact Us',
to: '/contact-us/'
},
{
display: 'Sign Up',
to: '/sign-up/'
},
{
display: 'Login',
to: '/sign-in/'
},
]
const Sidebar = () => {
const [activeIndex, setActiveIndex] = useState(0);
const [stepHeight, setStepHeight] = useState(0);
const sidebarRef = useRef();
const indicatorRef = useRef();
const location = useLocation();
useEffect(() => {
setTimeout(() => {
const sidebarItem = sidebarRef.current.querySelector('.sidebar__menu__item');
indicatorRef.current.style.height = `${sidebarItem.clientHeight}px`;
setStepHeight(sidebarItem.clientHeight);
}, 50);
}, []);
// change active index
useEffect(() => {
const curPath = window.location.pathname.split('/')[1];
const activeItem = sidebarNavItems.findIndex(item => item.section === curPath);
setActiveIndex(curPath.length === 0 ? 0 : activeItem);
}, [location]);
return (
<div className='sidebar'>
<div className="sidebar__logo">
<div><img src = {Logo} alt='Logo'className='Logo' /></div>
</div>
<div ref={sidebarRef} className="sidebar__menu">
<div
ref={indicatorRef}
className="sidebar__menu__indicator"
style={{
transform: `translateX(-50%) translateY(${activeIndex * stepHeight}px)`
}}
></div>
{
sidebarNavItems.map((item, index) => (
<Link to={item.to} key={index}>
<div className={`sidebar__menu__item ${activeIndex === index ? 'active' : ''}`}>
<div className="sidebar__menu__item__icon">
{item.icon}
</div>
<div className="sidebar__menu__item__text">
{item.display}
</div>
</div>
</Link>
))
}
</div>
</div>);
};
Here is the Sidebar.CSS
.sidebar {
position: fixed;
top: 0;
left: 0;
height: 100vh;
width: 20vw;
background-color: #fff;
}
.sidebar__logo {
display: grid;
place-items: center;
margin-bottom: 5vh;
}
.sidebar__menu {
position: relative;
}
.sidebar__menu__item {
display: flex;
align-items: center;
place-content: flex-start;
padding: 1rem 3rem;
font-size: 1.25rem;
font-weight: 500;
color: #555;
transition: color 0.3s ease-in-out;
}
.sidebar__menu__item.active {
color: #fff;
}
.sidebar__menu__item__icon {
margin-right: 1rem;
}
.sidebar__menu__item__icon i {
font-size: 1.75rem;
}
.sidebar__menu__indicator {
position: absolute;
top: 0;
left: 50%;
width: calc(100% - 40px);
border-radius: 5px;
background-color: #FD954E;
z-index: -1;
transform: translateX(-50%);
transition: 0.3s ease-in-out;
}

how to align a component at the bottom of the page

below in App.js i am displaying a Todo app where Todo Component displays each Todo task and TodoForm is used display a input through which we can add task
import "./App.css";
import Todo from "./Components/Todo";
import React, { Component } from "react";
import TodoForm from "./Components/TodoForm";
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
todos: [
{ id: 1, name: "First Todo", completed: true },
{ id: 2, name: "Second Todo", completed: false },
{ id: 3, name: "Third Todo", completed: false },
],
};
}
addTodo = (todo) => {
todo.id = this.state.todos.length + 1 || 0;
let todoList = [...this.state.todos, todo];
this.setState({ todos: todoList });
};
completeTodo = (id) => {
let todoList = [...this.state.todos];
const index = todoList.findIndex((todo) => todo.id === id);
todoList[index].completed = !todoList[index].completed;
this.setState({ todos: todoList });
};
deleteTodo = (id) => {
console.log(id);
let todoList = [...this.state.todos];
const index = todoList.findIndex((todo) => todo.id === id);
todoList.splice(index, 1);
this.setState({ todos: todoList });
};
render() {
return (
<div className="App">
<div className="developer">
<span>Developer</span>
<br />
<p>Kishore Pantra</p>
</div>
<h1 className="header">Todo React Component</h1>
<div className="todos">
{this.state.todos.map((todo) => (
<Todo
key={todo.id}
todo={todo}
completeTodo={this.completeTodo}
deleteTodo={this.deleteTodo}
/>
))}
</div>
<TodoForm addTodo={this.addTodo} />
</div>
);
}
}
here in App.css i am providing the css required for App.js
body,
html {
margin: 0;
padding: 0px;
box-sizing: border-box;
background-color: skyblue;
height: 100%;
overflow-y: hidden;
overflow-x: hidden;
}
.header {
color: white;
text-align: center;
}
.todos {
height: 400px;
overflow: auto;
margin: 5px;
padding: 5px;
border-radius: 5px;
background-color: yellowgreen;
}
.developer {
background-color: gold;
width: 150px;
text-align: center;
color: white;
transform: rotate(-45deg);
position: absolute;
top: 10px;
left: -10px;
}
Todo.js
import React, { Component } from "react";
import "./Todo.css";
export default class Todo extends Component {
completeTodo = (id) => {
this.props.completeTodo(id);
};
deleteTodo = (id) => {
this.props.deleteTodo(id);
};
render() {
return (
<div className="todo">
<p
style={{
textDecoration: this.props.todo.completed ? "line-through" : "",
}}
>
{this.props.todo.name}
</p>
<div className="status">
<button
className="completed"
onClick={() => this.completeTodo(this.props.todo.id)}
>
{this.props.todo.completed ? "Reinitialize Todo" : "Todo Completed"}
</button>
<button
className="remove"
onClick={() => this.deleteTodo(this.props.todo.id)}
>
X
</button>
</div>
</div>
);
}
}
Todo.css
.todo {
background-color: white;
display: flex;
flex-direction: row;
align-items: center;
margin: 10px;
padding: 10px;
border-radius: 5px;
}
.todo p {
width: 89%;
}
.status button {
margin: 2px;
border-radius: 100px;
outline: none;
border: 1px solid grey;
}
.completed {
background-color: rgb(6, 250, 38);
color: white;
}
.remove {
background-color: rgba(238, 15, 15, 0.884);
color: white;
}
TodoForm.js
import React, { Component } from "react";
import "./TodoForm.css";
export class TodoForm extends Component {
constructor(props) {
super(props);
this.state = {
todotext: "",
};
}
addTodo = (e) => {
e.preventDefault();
this.props.addTodo({ name: this.state.todotext, completed: false });
this.setState({ todotext: "" });
};
render() {
return (
<form className="todoform" onSubmit={this.addTodo}>
<input
type="text"
value={this.state.todotext}
onChange={(e) => this.setState({ todotext: e.target.value })}
placeholder="Add your Todo here..."
/>
</form>
);
}
}
export default TodoForm;
todoForm.css
.todoform {
display: flex;
justify-content: center;
}
.todoform input {
outline: none;
width: 98%;
padding: 10px;
margin: 10px;
border: none;
border-radius: 10px;
}
i want to align Todoform component at the bottom of the screen how can i align it.
To align TodoForm component to the bottom, You can use flexbox or grid. In this case, I used the grid because it is lighter (less code)
In App.css file on .App class selector You need to set this few properties.
.App {
min-height: 100vh;
margin: 0;
display: grid;
grid-template-rows: auto 1fr auto;
}
Before change =>
After change =>

How to dynamically change the size of icon in <IconContext.Provider>

currently, to style my icons under the 'react-icons' library, I am using the 'IconContext.Provider' tag. However, is there a solution for me to change the size of the icon dynamically based on the size of my media ?
Is the only solution to go about doing this only with the global stylesheet? I am avoiding it as I have only just started using NextJs and I do not want my style to have a possible clash with other style. Hence, I am separating them into modules.
Thank you.
NavBar.Module.Css
#import url("https://fontlibrary.org//face/metropolis");
.siteTitleWrapper {
box-sizing: border-box;
display: table-cell;
vertical-align: middle;
}
.siteTitle {
font-family: "MetropolisRegular";
font-weight: 600;
font-style: normal;
font-size: 20px;
letter-spacing: 2px;
text-transform: uppercase;
color: #000;
margin: 0;
padding-top: 0;
padding-bottom: 0;
line-height: 1em;
white-space: nowrap;
}
.headerInner {
padding: 20px 0;
display: table;
width: 100%;
}
.mainNavigation {
text-align: right;
position: relative;
z-index: 1000;
display: block;
}
.NavItemsWrapper {
display: inline-flex;
align-items: center;
overflow: hidden;
cursor: pointer;
}
.NavItems {
font: "MetropolisRegular";
font-weight: 600;
font-style: normal;
font-size: 13px;
letter-spacing: 2px;
text-transform: uppercase;
text-decoration: none;
}
#media only screen and (max-width: 830px) {
.mainNavigation {
-webkit-font-smoothing: subpixel-antialiased;
display: inline-flexbox;
position: fixed;
bottom: 64px;
left: 0;
height: auto;
width: 100%;
background-color: #f7f7f7;
overflow: hidden;
text-align: center;
vertical-align: top;
}
.NavItems {
display: none;
}
}
NavBar.tsx
import Link from 'next/link'
import styles from '../styles/components/NavBar.module.css'
import {HiHome} from 'react-icons/hi'
import {FaBloggerB} from 'react-icons/fa'
import {AiOutlineFundProjectionScreen} from 'react-icons/ai'
import {BsPersonBadge} from 'react-icons/bs'
import {IconContext} from 'react-icons'
import { IconType } from 'react-icons/lib'
interface navItemsTypes {
icon: IconType,
category: string,
link: string
}
const navItems : navItemsTypes[] = [
{icon: HiHome, category: 'Home', link: '/'},
{icon: AiOutlineFundProjectionScreen, category: 'Projects', link: '/projects'},
{icon: FaBloggerB, category: 'Blogs', link: '/blogs'},
{icon: BsPersonBadge, category: 'About', link: '/about'},
]
const NavBar = () => {
return (
<div>
<nav className={styles.headerInner}>
<div className={styles.siteTitleWrapper}>
<h1 id="site-title" className={styles.siteTitle} ><Link href='/'>Hong Sheng Yang</Link></h1>
</div>
<div className={styles.mainNavigation}>
<IconContext.Provider value={{ size: '1em', style:{marginLeft:'3em',marginRight:'0.5em', color:'#000'}}}>
{navItems.map((item) => (
<div className={styles.NavItemsWrapper}>
<Link href={item.link}>
<span style={{display:'flex'}}>
<item.icon/>
<p className={styles.NavItems}>
{item.category}
</p>
</span>
</Link>
</div>
))}
</IconContext.Provider>
</div>
</nav>
</div>
)
}
export default NavBar
I did "npm i react-responsive" and import the following in my code
import { useMediaQuery } from 'react-responsive'
Additionally, I declared the sizes for mobile and phone with 2 const
const phoneViewNav = {
size: '1em',
}
const DesktopViewNav = {
size: '1.5em',
}
Lastly, I use the media query to check for the screen size and apply accordingly
const NavBar = () => {
const isDesktopOrLaptop = useMediaQuery({maxWidth:830})
const iconSize = isDesktopOrLaptop ? phoneViewNav : DesktopViewNav
const router = useRouter();
return (
<div id="nav">
....
<IconContext.Provider value={{ size: iconSize.size, style:{color:"#000"}}}> ...
</div> )}

css flex-box nested layout have issue

I can't using flex-box well.
This is current state :
I want this flex layout :
This is my code :
Lobby.js (Container)
const TopBlock = styled.div`
display: flex;
`;
const Lobby = () => {
return (
<>
<TopBlock>
<CreateRoom />
<Profile />
</TopBlock>
</>
)
}
Profile.js
const ProfileBlock = styled.div`
`;
const Profile = () => {
return (
<ProfileBlock>
<p>hello0</p>
<p>hello1</p>
<p>hello2</p>
</ProfileBlock>
)
}
What should I do? ..T_T
I think , ProfileBlock should be wrapped and put into your <p>hello</p>. Because if using flexbox for ProfileBlock look like a container in this case for grouping inside the container we need wrapper. working example
Lobby.js (Container)
const TopBlock = styled.div`
display: flex;
height: 100vh;
`;
export const Lobby = () => {
return (
<>
<TopBlock>
<CreateRoom />
<Profile />
</TopBlock>
</>
);
};
Profile.js
const ProfileBlock = styled.div`
width: 100%;
height: 100%;
display: flex;
align-items: flex-start;
border: 3px solid red;
div {
display: flex;
flex-wrap: wrap;
}
p {
width: 200px;
display: flex;
color: black;
padding: 15px;
border: 2px solid blue;
}
`;
export const Profile = () => {
return (
<ProfileBlock>
<div className="profile-wrapper">
<p>hello0</p>
<p>hello1</p>
<p>hello2</p>
</div>
</ProfileBlock>
);
};

Resources