![]() |
VOOZH | about |
We’re so glad you’re here. You can expect all the best TNS content to arrive Monday through Friday to keep you on top of the news and at the top of your game.
Check your inbox for a confirmation email where you can adjust your preferences and even join additional groups.
Follow TNS on your favorite social media networks.
Become a TNS follower on LinkedIn.
Check out the latest featured and trending stories while you wait for your first TNS newsletter.
<Layout />, and can be found in src/layouts/layout.astro | .jsxon each of the branches.
src code for this example here: src/layouts/layout.astro
In the code snippet below you’ll see there are ~36 lines of code that make the sidebar navigation work! This kind of JavaScript can become difficult to maintain and there are a number of areas where things could go wrong.
<script>
var isNavOpen = false;
const menu = document.querySelector('#menu');
const lightbox = document.querySelector('#lightbox');
const sidebar = document.querySelector('#sidebar');
const lightboxOpen = 'fixed';
const lightboxOpenLg = 'lg:hidden';
const lightboxClosed = 'hidden';
const sidebarResponsiveClosed = '-left-[240px]';
const sidebarResponsiveOpen = 'left-[max(0px,calc(50%-45rem))]';
const menuIcon = 'M4 6h16M4 12h16m-7 6h7';
const closeIcon = 'M6 18L18 6M6 6l12 12';
const menuPath = document.querySelector('#menuPath');
menuPath.setAttribute('d', menuIcon);
sidebar.classList.add(sidebarResponsiveClosed);
lightbox.classList.add(lightboxClosed);
const handleNav = () => {
if (isNavOpen) {
menuPath.setAttribute('d', menuIcon);
lightbox.classList.remove(lightboxOpen, lightboxOpenLg);
sidebar.classList.remove(sidebarResponsiveOpen);
lightbox.classList.add(lightboxClosed);
sidebar.classList.add(sidebarResponsiveClosed);
isNavOpen = false;
} else {
menuPath.setAttribute('d', closeIcon);
lightbox.classList.remove(lightboxClosed);
lightbox.classList.add(lightboxOpen, lightboxOpenLg);
sidebar.classList.remove(sidebarResponsiveClosed);
sidebar.classList.add(sidebarResponsiveOpen);
isNavOpen = true;
}
};
menu.addEventListener('click', handleNav);
lightbox.addEventListener('click', handleNav);
</script>
id, creating variables to hold the different class names (I’m using Tailwind by the way), then there’s the classList methods to add and remove styles, plus the eventListener that needs to be attached to the DOM element.
const lightbox = document.querySelector('#lightbox');
const lightboxOpen = 'fixed';
const lightboxOpenLg = 'lg:hidden';
const lightboxClosed = 'hidden';
const handleNav = () => {
...
if (isNavOpen) {
lightbox.classList.remove(lightboxOpen, lightboxOpenLg);
lightbox.classList.add(lightboxClosed);
isNavOpen = false;
} else {
...
lightbox.classList.remove(lightboxClosed);
lightbox.classList.add(lightboxOpen, lightboxOpenLg);
isNavOpen = true;
}
};
lightbox.addEventListener('click', handleNav);
<div id='lightbox' aria-label='lightbox' tab-index='0' role='button' class='z-20 top-0 left-0 w-screen h-screen bg-custom-background opacity-80' > </div>
id from the HTML element, the navigation would break, making it impossible for people to use my site!
That said, the one thing this approach has got going for it is that it’s super lightweight. Vanilla JavaScript, or JavaScript that the browser can natively understand, doesn’t require any additional runtimes to be downloaded for it to work.
src code for this example here: src/layouts/layout.jsx
By contrast, if I enable the same functionality using React, you’ll see how much cleaner and easier it is to read. There are just ~5 lines of code to change a state value, which in turn causes React to re-render the HTML, and a ternary operator can be used to decide which classes should be present in the HTML when React has finished hydrating the page.
port { useState } from 'react';
const [isNavOpen, setIsNavOpen] = useState(false);
const handleNav = () => {
setIsNavOpen(!isNavOpen);
};
<div
aria-label='lightbox'
tab-index='0'
role='button'
className={`z-20 top-0 left-0 w-screen h-screen bg-custom-background opacity-80 ${isNavOpen ? 'fixed' : 'hidden'} lg:hidden`}
onClick={handleNav}
/>
src code for this example here: src/layouts/layout.jsx
As before with React, there are ~5 lines of code to change the state value. The HTML setup is very similar to React, where a ternary operator is used to control which class names are used.
import { useSignal, $ } from '@builder.io/qwik';
const isNavOpen = useSignal(false);
const handleNav = $(() => {
isNavOpen.value = !isNavOpen.value;
});
<div
aria-label='lightbox'
tab-index='0'
role='button'
className={`z-20 top-0 left-0 w-screen h-screen bg-custom-background opacity-80 ${isNavOpen.value ? 'fixed' : 'hidden' } lg:hidden`}
onClick$={handleNav}
></div>
Qwik, in my opinion, is the best of both worlds — it’s less verbose to write than Vanilla JavaScript and is considerably lighter compared to React.What I also like about the Qwik approach is that the JavaScript is inlined, like it would have been had I written it using the Vanilla method. So there’s no actual .js files downloaded when you look in the Network tab of your browser’s dev tools. 👁 Qwik - inline script
<Layout client:only='react'> <slot /> </Layout>
<Layout> <slot /> </Layout>