React Bulma mobile nav bar is not working as expected - css

When I click the button to toggle the mobile nav bar it's not working. I am using Bulma css framework with react. Here is the React nav bar component:
onst Header = (props) => {
const dispatch = useDispatch()
const { loginUser, isAuthenticated, history, errors } = props;
const dropdownRef = useRef(null);
const [isActive, setIsActive] = useDetectOutsideClick(dropdownRef, false);
const [isMobileActive, setisMobileActive] = useState(false);
const onClick = () => setIsActive(!isActive);
const onLogout = () => {
dispatch(logout())
}
return (
<nav className="navbar" role="navigation" aria-label="main navigation">
<div className="navbar-brand">
<a className="navbar-item" href="https://bulma.io">
<img
src="https://bulma.io/images/bulma-logo.png"
width="112"
height="28"
/>
</a>
<a
onClick={() => {
setisMobileActive(!isMobileActive)
}}
role="button"
className={`navbar-burger burger ${isActive ? "is-active" : ""}`}
aria-label="menu"
aria-expanded="false"
data-target="navbarBasicExample"
>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div id="navbarBasicExample" className="navbar-menu">
<div className="navbar-end">
<a className="navbar-item">Dashboard</a>
<div
onClick={onClick}
ref={dropdownRef}
className={`navbar-item has-dropdown ${
isActive ? "is-active" : ""
}`}
>
<a className="navbar-link">Account</a>
<div className="navbar-dropdown is-right">
<a className="navbar-item">Account settings</a>
<a className="navbar-item">Set Job filters</a>
<a className="navbar-item">Report an issue</a>
<a className="navbar-item" onClick={onLogout}>Log out</a>
</div>
</div>
</div>
</div>
</nav>
);
};
The most bottom part with dropdown is for desktop nav bar. What is missing for mobile toggle menu. How can I fix it? Who I click the toggle button nothing happens.

Iā€˜m not familiar with React, but on the bulma side you need to toggle the class is-active on both the navbar-burger and the targeted navbar-menu.
There are implementation examples in Bulma navbar documentation, personally I'm using the jQuery implementation which works perfectly :
$(document).ready(function() {
// Check for click events on the navbar burger icon
$(".navbar-burger").click(function() {
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
$(".navbar-burger").toggleClass("is-active");
$(".navbar-menu").toggleClass("is-active");
});
});
but there's also a Vanilla Javascript implementation in the docs if you want.

Related

NVDA and JAWS screen reader is announcing unwanted text when readmore button is activated

NVDA-FF and JAWS-Chrome>, when read more element is activated while traversing through tab navigation then screen reader announces the unnecessary information along with the updated content. When read more element is activated in the arrow key navigation, for the instance, , screen reader announces as ā€œ <> and <>ā€. Note: same goes with the read less element as well
<div class="pros-cons-block" tabindex="-1">
<div class="pros-block">
<h4>Pros-text</h4>
<div>
eachReview.pros
</div>
</div>
<div class="cons-block">
<h4>cons-text</h4>
<div>
eachReview.cons
</div>
</div>
</div>
<div v-show="eachReview" class="read-more">
<button v-if="eachReview.readMore" class="readless" #click="readMore(eachReview)">
<span aria-live="assertive" aria-atomic="true"></span>
<span v-if="eachReview.readMore">
<span class="phw-visually-hidden">{{eachReview.headline}}
</span>
{{readLessButton.text }}
</span>
</button>
<button v-if="eachReview && !eachReview?.readMore" class="readMoreButton" #click="readMore(eachReview, index)">
<span aria-live="assertive" aria-atomic="true"></span>
<span v-if="eachReview && !eachReview?.readMore">
<span class="phw-visually-hidden">{{ eachReview && eachReview?.headline }}</span>
{{ content.readMoreButton.text }}
</span>
</span>
</span>
</button>
</div>
<script>
const readMore = (eachReview: any, index: number) => {
eachReview.readMore = !eachReview.readMore;
const focusElem = root.value.querySelectorAll('.glassdoorReviews .each-review')[index];
if (eachReview.readMore) {
setTimeout(() => {
const readLessButton = root.value.querySelectorAll('.read-less-button')[index];
readLessButton?.setAttribute('aria-hidden', 'true');
focusElem.querySelector('.pros-cons-block').focus();
readLessButton?.setAttribute('aria-hidden', 'false');
}, 0);
} else {
setTimeout(() => {
focusElem.querySelector('.readMoreButton').focus();
}, 0);
}
};
</script>

How to add a multiple choice system for my gallery filter

I'm working on a fictive project for my webdev formation, and I would need just a little help in fixing my filter system for my gallery. It's pretty straightforward, you click on a category and the gallery displays the images corresponding to the category. Everything (finally) works pretty nicely, the only two problems that keep bugging me are:
-Once a category is checked, I can't uncheck it and have to check another category instead (which automatically unchecks the previous one);
-And as the title of my question suggests, I can only select one category at a time.
I would like the user to be able to check multiple categories in order to display all photos corresponding to the categories selected, thus meaning I would like the user to be able to uncheck a category, and if no categories are checked, then the gallery would display all photos of the api.
Thank you for your help and your research.
import Head from 'next/head'
import Image from 'next/image'
import { useRouter } from 'next/router'
import { useState } from 'react'
import Nav from '../components/nav'
import styles from '../styles/style.module.css'
export default function Gallery({ res, res2 }) {
const [targetCategory, setTargetCategory] = useState("");
return(
<main className={`${styles.container} ${styles.gallery}`}>
{/* NAVBAR */}
<div className={`${styles.menu}`}>
<Nav />
</div>
{/* GALLERY FILTER - MOBILE COLLAPSIBLE */}
<div className={`${styles.filter}`}>
<div className="container-fluid">
<nav className="navbar navbar-expand-lg">
<button className="navbar-toggler text-white"
type="button"
data-bs-toggle="collapse"
data-bs-target="#filterContent"
aria-controls="filterContent"
aria-expanded="false"
aria-label="Toggle navigation">
<span className="align-self-center">Filtres</span>
<i className="bi bi-list fs-1"/>
</button>
<div className="collapse navbar-collapse" id="filterContent">
<form id="img-sort" action="">
<ul className="nav navbar-nav">
{res2.data.map((category) => (
<>
<label key={category.id} className={styles.formControl}>
<input
type="checkbox"
name="checkbox"
id={category.attributes.name}
value={category.attributes.name}
checked={targetCategory === category.attributes.name}
onClick={(e) => setTargetCategory(e.target.value)}/>
{category.attributes.name}
</label>
</>
))}
</ul>
</form>
</div>
</nav>
</div>
</div>
{/* GALLERY CONTENT */}
<div className={`${styles.pictures_holder}`}>
<div className={`${styles.pictures}`}>
{res.data.filter((photo) => photo.attributes.category.data.attributes.name.includes(targetCategory)).map((photo) => (
<div key={res.id}>
<img
src={`http://localhost:1337` + photo.attributes.img.data[0].attributes.formats.small.url}
alt={photo.attributes.img.data[0].attributes.formats.small.name}
/>
<p className="text-white text-center">{photo.attributes.name}</p>
</div>
))}
</div>
</div>
</main>
)
}
export async function getStaticProps() {
try {
const res = await fetch("http://localhost:1337/api/photos?populate=*").then((res) => res.json());
const res2 = await fetch("http://localhost:1337/api/categories?populate=*").then((res2) => res2.json());
return {
props: { res, res2 }
};
} catch (err) {
console.error(err);
}
}

Hide and show specific div coming from api in next.js

I am working on a menu drop down in next.js project,
I made a method to hide and show the data of the sub menu,but I am not able to show the specific sub dropdown. Here is the code
import {useEffect, useState } from "react";
function Header({data}){
const [showMe, setShowMe] = useState(false);
function toggle(param){
console.log(param)
setShowMe(!showMe);
};
return(
<div className="mobile-header">
<div className="mobile-menu">
<div className="menu-icon">
<div className="wrapper">
<input type="checkbox" id="navigation" />
<label for="navigation">
+
</label>
<nav>
<ul>
<li className="menu-heading">
<span>Menu</span>
<span>
<label for="navigation">X</label>
</span>
</li>
{data.menus.map((post, index) => {
return (
<li className="menu-list" id={index}>
{post.title} <span onClick = {(event)=>toggle({index})} index={index} >+</span>
<ul style={{display: showMe?"block":"none"}} index={index} value={index} className="category-one">
{post.menu_columns.map((subItems, sIndex) => {
return <li index={sIndex}>
{subItems.title}
<span>+</span>
<ul className="category-two">
{subItems.menu_items.map((x) => {
return <li>
{x.title}
</li>
})}
</ul>
</li>;
})}
</ul>
</li>)})}
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
)
}
export default Header;
toggle is the function, which responsible to show and hide the data, there is a parameter passed in this function which provide the specific index value, how do we target the specific div by using the index value in this.

How I can add bulma.css toggle navbar in Next.js?

I have added bulma.css in my Next.js project and all runs well, but navbar toggle doesn't work because need add some pure javascript code and React doesn't provide pure DOM events
Just add React Lifecycle event and put your code.
ORIGINAL example:
import React from "react";
class NavBar extends React.Component {
componentDidMount() {
const $navbarBurgers = Array.prototype.slice.call(
document.querySelectorAll(".navbar-burger"),
0
);
if ($navbarBurgers.length > 0) {
// Add a click event on each of them
$navbarBurgers.forEach(el => {
el.addEventListener("click", () => {
// Get the target from the "data-target" attribute
const target = el.dataset.target;
const $target = document.getElementById(target);
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
el.classList.toggle("is-active");
$target.classList.toggle("is-active");
});
});
}
}
render() {
return (
<nav className="navbar" role="navigation" aria-label="main navigation">
<div className="navbar-brand">
<a className="navbar-item" href="https://bulma.io">
<img
src="https://bulma.io/images/bulma-logo.png"
width="112"
height="28"
/>
</a>
<a
role="button"
className="navbar-burger burger"
aria-label="menu"
aria-expanded="false"
data-target="navbarBasicExample"
>
<span aria-hidden="true" />
<span aria-hidden="true" />
<span aria-hidden="true" />
</a>
</div>
<div id="navbarBasicExample" className="navbar-menu">
<div className="navbar-start">
<a className="navbar-item">Home</a>
<a className="navbar-item">Documentation</a>
<div className="navbar-item has-dropdown is-hoverable">
<a className="navbar-link">More</a>
<div className="navbar-dropdown">
<a className="navbar-item">About</a>
<a className="navbar-item">Jobs</a>
<a className="navbar-item">Contact</a>
<hr className="navbar-divider" />
<a className="navbar-item">Report an issue</a>
</div>
</div>
</div>
<div className="navbar-end">
<div className="navbar-item">
<div className="buttons">
<a className="button is-primary">
<strong>Sign up</strong>
</a>
<a className="button is-light">Log in</a>
</div>
</div>
</div>
</div>
</nav>
);
}
}
export default NavBar;
I had the same issue and in my case I can resolve it adding in the _app component this line
import 'bulma/css/bulma.css

hamburger icon is not showing up even if I call componentHandler.upgradeDom();

<header class="mdl-layout__header">
<div class="mdl-layout__header-row">
<!-- Navigation -->
<nav class="mdl-navigation">
<a class="mdl-navigation__link is-active" href="/">link</a>
<a class="mdl-navigation__link is-active" href="/">link</a>
</nav>
</div>
</header>
<div class="mdl-layout__drawer">
<nav class="mdl-navigation">
<a class="mdl-navigation__link is-active" href="/">link</a>
<a class="mdl-navigation__link is-active" href="/">link</a>
</nav>
</div>
<!-- Colored FAB button with ripple -->
<button class="mdl-button mdl-js-button mdl-button--fab mdl-js-ripple-effect mdl-button--colored">
<i class="material-icons">add</i>
</button>
According to http://mdlhut.com/2015/07/where-is-the-mdl-drawer-icon/ it should work as long as I call componentHandler.upgradeDom() after I dynamically load the html. Just to make sure I'm calling the upgradeDom correct I added the button to see if the ripple effect is added. And the button is updated but the hamburger icon is not appearing.
If I inline the html the hamburger icon appears.
Since you are dynamically load the html, you should run the following inside your init function after the DOM is load. Notice that the setInterval function to ensure DOM has enough time to load before executing the componentHandler method
jQuery
$(document).ready(function() {
setInterval(function() {
componentHandler.upgradeAllRegisteredElements();
}, 1000);
});
DOM API
document.addEventListener('DOMContentLoaded', function() {
setInterval(function() {
componentHandler.upgradeAllRegisteredElements();
}, 1000);
});

Resources