vue-router transition suddenly stopped working - javascript

I am working on my personal website currently. For the frontend I am using Vue.js with vue-router. Until today the transition worked fine, you can see here: https://imanuel.ulbricht.codes/ (you need to scroll down or use the arrow key down). But after some changes that I cannot really find it stopped working.
This is how it "works" now: https://imanuel-not-working.ulbricht.codes/. I really have no idea what I changed, that might affect this change in behavior, maybe someone has an idea.
Side note: The published code has sourcemaps enabled so you should see the complete Vue.js source code.
Another point, the code should animate the page transition, that doesn't happen currently. After 2h searching I couldn't find the root of the problem, if anyone could give me a hint what code might be the cause I will add it to the question.
This is the code, that might cause the issue:
App.vue
<template>
<div class="ulbricht-app" id="app" #wheel="navigateWheel" #keyup.down="navigateNext" #keyup.up="navigatePrevious">
<ribbon v-if="!$route.meta.isHelloWorld"/>
<transition>
<div class="ulbricht-slice__top" :class="{ 'ulbricht-slice__hello-world': $route.meta.isHelloWorld }"></div>
</transition>
<NavIndicator v-if="!$route.meta.isHelloWorld"/>
<transition name="ulbricht-router__fade" mode="out-in">
<router-view/>
</transition>
<transition>
<div class="ulbricht-slice__bottom" v-if="!$route.meta.isHelloWorld"></div>
</transition>
</div>
</template>
<script>
export default {
components: {
NavIndicator,
Ribbon
},
name: 'App',
mounted() {
window.addEventListener('keyup', (event) => {
if (event.key === 'ArrowUp') {
this.navigatePrevious();
} else if (event.key === 'ArrowDown') {
this.navigateNext();
}
});
},
methods: {
navigateWheel($event) {
if ($event.deltaY > 0) {
this.navigateNext();
} else {
this.navigatePrevious();
}
},
navigateNext() {
if (this.$route.meta.next) {
this.$router.push(this.$route.meta.next);
}
},
navigatePrevious() {
if (this.$route.meta.previous) {
this.$router.push(this.$route.meta.previous);
}
}
}
};
</script>
<style lang="scss">
.ulbricht-app {
.ulbricht-slice__top {
background: var(--primary);
position: absolute;
width: 200%;
z-index: 0;
transition: transform 0.4s, height 0.4s;
height: 250px;
transform: skewY(-3deg);
left: 0;
top: -210px;
&.ulbricht-slice__hello-world {
transition: transform 0.4s, height 0.2s;
top: -25px;
height: 120%;
transform: skewY(15deg);
}
}
.ulbricht-router__fade-enter-active {
span,
p,
h1,
img {
transition: opacity 0.3s;
opacity: 1;
}
}
.ulbricht-router__fade-leave-active {
span,
p,
h1,
img {
transition: opacity 0.3s;
opacity: 0;
}
}
}
</style>
And one of the components, they basically all look the same just the content varies.
<template>
<div class="ulbricht-app ulbricht-app__hello">
<img class="ulbricht-hello__background" src="../assets/background.png" alt="">
<div class="ulbricht-hello__content">
<h1 class="ulbricht-hello__header">
Hello World, I am Imanuel
</h1>
<p class="ulbricht-hello__text">
What I do is dead simple, I write software, design websites and landscapes,<br/>
let me show you what I am capable of
</p>
<router-link class="ulbricht-chevron" :to="$route.meta.next">
<span class="ulbricht-chevron__button"></span>
</router-link>
</div>
</div>
</template>
<script>
export default {
name: 'HelloWorld'
};
</script>
And the NavIndicator component, I think after adding this component it stopped working, but I am not sure.
<template>
<div class="ulbricht-sidenav">
<router-link :to="$route.meta.previous || ''" class="ulbricht-sidenav__chevron is--up"
:class="{'is--disabled': !$route.meta.previous}"></router-link>
<router-link :to="nav" class="ulbricht-sidenav__dot" :class="{'is--active': $route.name === nav.name}"
:title="nav.meta.title" v-for="nav in navs"></router-link>
<router-link :to="$route.meta.next || ''" class="ulbricht-sidenav__chevron is--down"
:class="{'is--disabled': !$route.meta.next}"></router-link>
</div>
</template>
<script>
import Routes from "../router/Routes";
export default {
name: "NavIndicator",
computed: {
navs() {
return Routes;
}
}
}
</script>
<style lang="scss">
.ulbricht-sidenav {
position: fixed;
right: 1em;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
z-index: 9999;
}
.ulbricht-sidenav__chevron {
&::before {
border-style: solid;
border-width: 0.25em 0.25em 0 0;
content: '';
display: inline-block;
height: 0.45em;
left: 0.15em;
position: relative;
vertical-align: top;
width: 0.45em;
border-color: var(--primary);
margin-right: 0.3em;
}
&.is--disabled {
&::before {
border-color: var(--primary-grey);
}
}
&.is--up {
&::before {
transform: rotate(-45deg);
top: 0.5em;
}
}
&.is--down {
&::before {
top: 0;
transform: rotate(135deg);
}
}
}
.ulbricht-sidenav__dot {
border-radius: 50%;
width: 1em;
height: 1em;
border: 0.2em solid var(--primary-opaque-0\.5);
margin-top: 0.25em;
margin-bottom: 0.25em;
transition: border 0.3s, background 0.3s;
&.is--active {
background: var(--primary);
}
&:hover {
border: 0.2em solid var(--primary-opaque-0\.7);
background: var(--primary);
}
}
</style>
Removing this component, however, didn't have an effect.
As addition, here is the Github Link, so you can investigate all of the source code if I might have forgotten something, that might be relevant.
https://github.com/DerKnerd/imanuel.ulbricht.codes/tree/98272361549617191bb6d6f5d88ad88c94cbdcfe

There is a <!-- --> comment between
<div class="ulbricht-slice__top ulbricht-slice__hello-world"></div>
and
<div class="ulbricht-app ulbricht-app__hello">
on the copy of your site that is not working. Something is being rendered/removed there.
It may be causing a CSS selector to be applied incorrectly.

Related

How do i refer the className when having a nested scss ? nextjs reactjs

I have a navbar with a hamburger button and i want to change the style (the bar color and the hamburger button style) on tap. I mention that i've tried using &:active, &.activeBar on the scss file.
For some reason the background color doesn t change and the hamburger button doesn't turn into an X
This is my SCSS file:
.topbar {
width: 100%;
background-color: $secondaryColor;
color: $mainColor;
height: 70px;
position: fixed;
top: 0;
z-index: 3;
transition: all 1s ease;
overflow: hidden;
.wrapper {
padding: 10px 30px;
display: flex;
align-items: center;
justify-content: space-between;
}
.left {
display: flex;
align-items: center;
margin: 10;
.itemContainer {
display: flex;
align-items: center;
.icon {
font-size: 36px;
margin-right: 5px;
&:hover {
color: blue;
}
}
span {
font-size: 15px;
font-weight: 700;
}
}
.logo {
font-size: 40px;
font-weight: 700;
text-decoration: none;
color: inherit;
margin-right: 40px;
}
}
.right {
.hamburger {
width: 32px;
height: 25px;
display: flex;
flex-direction: column;
justify-content: space-between;
span {
width: 100%;
height: 3px;
background-color: $mainColor;
transform-origin: left;
transition: all 0.5s ease;
}
}
}
&.activeBar {
background-color: $mainColor;
color: $secondaryColor;
.hamburger span {
&:first-child {
background-color: $secondaryColor;
transform: rotate(45deg);
}
&:nth-child(2) {
opacity: 0;
}
&:last-child {
background-color: $secondaryColor;
transform: rotate(-45deg);
}
}
}
}
And this is where i try to change the classname in my js file:
import React from 'react';
import styles from './topbar.module.scss';
import { Facebook } from '#material-ui/icons';
const Topbar = ({ open, toggle }) => {
function menuToggled() {
toggle(!open);
console.log('menuToggled', open);
}
return (
<div className={`${styles.topbar} ${open ? 'active' : ''}`}>
<div className={styles.wrapper}>
<div className={styles.left}>
<a href='#slider' className={styles.logo}>
Muntenia cu gust
</a>
<div className={styles.itemContainer}>
<Facebook
className={styles.icon}
onClick={() => window.open('https://stackoverflow.com/')}
/>
</div>
</div>
<div className={styles.right}>
<div className={styles.hamburger} onClick={menuToggled}>
<span className={styles.line1}></span>
<span className={styles.line2}></span>
<span className={styles.line3}></span>
</div>
</div>
</div>
</div>
);
};
export default Topbar;
In your code, you're adding active as a class in the "global" scope. By default with css-modules, all classes are output in "local" scope. So your .topbar class, after compilation, would look something like: .Topbar_topbar__abc12 ("abc12" would be a hash).
So, the .active class is also being compiled to local scope, looking something like: .Topbar_active_def34
In your markup, you're toggling the .active class as a string rather than as styles.active. So, on output, you're expecting your "active" class to be .Topbar_topbar__abc12.active when in actuality, your stylesheet is declaring .Topbar_topbar_abc12.Topbar_active_def32 as the "active" class.
By declaring .active as being in the global scope, the output would then be as expected. Try adding the :global flag to your stylesheet:
...
&:global(.active) {
background-color: $mainColor;
color: $secondaryColor;
.hamburger span {
&:first-child {
background-color: $secondaryColor;
transform: rotate(45deg);
}
&:nth-child(2) {
opacity: 0;
}
&:last-child {
background-color: $secondaryColor;
transform: rotate(-45deg);
}
}
}
...
use classnames package (https://www.npmjs.com/package/classnames) to combine classes that are on the same element, the rest is handled the same as in vanilla html/css/js
In your code you use active it also should come from styles and be combined using:
classnames('styles.ElementClassName', active && styles.active)
Adding the active selector on the regular .hamburger class should trigger on touch. Also the classname in you scss is activeBar but in your react app is only active.
&.clicked {
background-color: $mainColor;
color: $secondaryColor;
.hamburger span {
&:first-child {
background-color: $secondaryColor;
transform: rotate(45deg);
}
&:nth-child(2) {
opacity: 0;
}
&:last-child {
background-color: $secondaryColor;
transform: rotate(-45deg);
}
}
}
If you want to change the topBar also then you'll need to change your TopBar component a bit
import React, { useState } from 'react';
import styles from './topbar.module.scss';
import { Facebook } from '#material-ui/icons';
const Topbar = ({ open, toggle }) => {
const [isClicked, setIsClicked] = useState(false);
function menuToggled() {
toggle(!open);
console.log('menuToggled', open);
}
return (
<div className={`${styles.topbar} ${open ? 'active' : ''} ${ isClicked && ' clicked'}`}>
<div className={styles.wrapper}>
<div className={styles.left}>
<a href='#slider' className={styles.logo}>
Muntenia cu gust
</a>
<div className={styles.itemContainer}>
<Facebook
className={styles.icon}
onClick={() => window.open('https://stackoverflow.com/')}
/>
</div>
</div>
<div className={styles.right}>
<div className={styles.hamburger} onClick={menuToggled} onTouchStart={(e) => setIsClicked(true)}>
<span className={styles.line1}></span>
<span className={styles.line2}></span>
<span className={styles.line3}></span>
</div>
</div>
</div>
</div>
);
};

vue - transform rotate doesn't rotate back when toggle state

When I click the button, the state showMore will be toggled.
If I click it at the first time, it rotates as expected.
But when I click again the button, the animation doesn't works.
App.vue
<template>
<div class="item">
<button class="learn-more-btn" #click="toggleShow">
<span>Rotate</span>
<img
src="./assets/logo.png"
alt="arrow"
:class="arrowLeft"
width="50"
height="50"
/>
</button>
</div>
</template>
<script>
export default {
components: {},
data() {
return {
showMore: false,
};
},
methods: {
toggleShow() {
this.showMore = !this.showMore;
},
},
computed: {
arrowLeft() {
let arrow = "turn-arrow";
if (this.showMore === true) {
return arrow;
}
return true;
},
},
};
</script>
<style scoped lang="scss">
.item {
display: flex;
border: 1px solid grey;
width: 150px;
.learn-more-btn {
display: flex;
justify-content: center;
align-items: center;
background-color: transparent;
border: none;
&:hover {
cursor: pointer;
}
img {
display: inline-block;
}
.turn-arrow {
-moz-transform: rotate(180deg);
-ms-transform: rotate(180deg);
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
transition: all 3000ms;
}
span {
padding: 0 0.5rem;
}
}
}
</style>
Codesandbox:
https://codesandbox.io/s/headless-fire-ng001?file=/src/App.vue
I just refactored your code a little bit and simplified things.
Instead of using transitions I replaced them with animations and toggled between .rotate-down and .rotate-up classes which use this animations.
Check it out: https://codesandbox.io/s/wonderful-wescoff-icnnm?file=/src/App.vue
Hope it's helpful :)!

onClick event not working within nested React / Next.js component

I can't seem to get the hideMoreDetails() function to work on this component. Nothing gets logged in the console and state remains unchanged when clicking on the 'close-more-info-cross' div.
Any clue? Could it be a stacking issue?
import { useState } from "react";
import TracklistAndPlayer from "./TracklistAndPlayer";
function ReleaseEntry(props) {
const [playerDisplayId, setPlayerDisplayId] = useState(null);
const [showMoreDetails, setShowMoreDetails] = useState(true);
function showPlayer(event) {
setPlayerDisplayId(event.target.getAttribute("data-tag"));
}
function hideMoreDetails() {
console.log("hide more details");
setShowMoreDetails(false);
}
function renderSection(section) {
return (
<div className="section">
{section[0] && section.map(paragraph => <p>{paragraph.text}</p>)}
</div>
);
}
return (
props.releases &&
props.releases.map(function(release, index) {
let tracklist = Object.values(release.data.tracks[0]);
return (
<div>
<div className="release-entry-wrapper">
<div onClick={showPlayer}>
<img
className="release-cover"
key={`cover${index}`}
src={release.data.cover.url}
alt="release-cover"
data-tag={index}
/>
<div className="release-details">
<div
key={`artist${index}`}
className="artist-name"
data-tag={index}
>
{release.data.artist[0].text}
</div>
<div
key={`title${index}`}
className="release-name"
data-tag={index}
>
<img
className="mini-play"
src="/img/play-song.png"
alt="mini-play"
data-tag={index}
/>
{release.data.title[0].text}
</div>
</div>
</div>
{parseInt(playerDisplayId) === index && showMoreDetails && (
<div>
{
<div className="more-info-about-release">
<img
className="close-more-info-cross"
src="/img/cross.png"
alt="cross"
onCLick={hideMoreDetails}
/>
<div className="tracklist-details">
{renderSection(release.data.tracklist)}
</div>
<div className="about-release">
{renderSection(release.data.about)}
</div>
<div className="credits">
{renderSection(release.data.credits)}
</div>
</div>
}
<TracklistAndPlayer
tracklist={tracklist}
setPlayerDisplayId={setPlayerDisplayId}
/>
</div>
)}
</div>
<style jsx>{`
.release-entry-wrapper {
padding-left: var(--global-margin);
padding-right: var(--global-margin);
font-family: var(--font1);
font-size: var(--standard-font-size);
text-transform: uppercase;
}
.release-cover {
cursor: pointer;
width: 100%;
transition: transform 0.5s;
}
.release-cover:hover {
transform: scale(1.005);
}
.release-details {
padding-top: 1rem;
padding-bottom: 1rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
text-align: center;
letter-spacing: 0.05rem;
transition: opacity 0.3s;
transition: transform 0.5s;
cursor: pointer;
}
.release-details:hover {
opacity: 0.85;
transform: scale(1.01);
}
.mini-play {
width: 0.5rem;
margin-right: 0.7rem;
}
.artist-name,
.release-name {
padding-top: 0.5rem;
padding-bottom: 0.3rem;
}
.tracklist-details {
margin-bottom: 2rem;
}
.close-more-info-cross {
width: 0.6rem;
position: absolute;
right: 0;
top: 0;
transition: transform 0.3s;
opacity: 0.7;
cursor: pointer;
}
.close-more-info-cross:hover {
width: 0.7rem;
opacity: 1;
}
.more-info-about-release {
text-transform: none;
margin-bottom: 2rem;
position: relative;
}
.more-info-section-title {
margin-bottom: 1rem;
margin-top: 1rem;
}
.about-release {
margin-bottom: 2rem;
}
`}</style>
</div>
);
})
);
}
export default ReleaseEntry;
PS : link to the entire project: https://github.com/jeremieemk/elis-records-website
You have a small typo on your onClick method:
<img
className="close-more-info-cross"
src="/img/cross.png"
alt="cross"
onCLick={hideMoreDetails}
^~~~~~ 👻
/>
It should be onClick, not onCLick.
If you open the browser's console, you would probably see a red warning such as onCLick method is not a dom property or such. I recommend keeping the console open when working with React, it will show many useful warnings.
In my case, I had to rename the file name of the component in lowercase. After that, all click listeners worked. Ex: Footer.js (old file name) -> footer.js
Before that, I couldn't able to see changes in real-time (not only click listeners, UI changes didn't appear). I had to restart the server to see changes.

ReactJS - Javascript run on browser but not in class App

I'm currently building a React project, I'm introducing a js code which is needed to display a popup properly. The code from the beginning is for clearing the URL from (#nameOfThePopup) and is introducing 2 functions : Close() and Open().
It runs just great in a normal HTML page, but when i want to fill it in my React project, it does some compilation problems, specificly 2 lines:
history.replaceState(null, null, ' ');
event.stopPropagation();
I did try to make it in ComponentDidmount() method and introduce it in public index.html as a script but still the same compilation errors.
There is my full code:
import React from 'react';
class Popup extends React.Component {
/*Clear URL from #popup1 in the end*/
history.replaceState(null, null, ' '); /*<=== error compile*/
/*declar variables and clear the popup from the DOM*/
let id_popup = document.querySelector('#popup1');
let popup = id_popup.parentNode;
popup.removeChild(id_popup);
/*Opening the popup */
Open() {
popup.appendChild(id_popup);
event.stopPropagation(); /*<=== error compile*/
let class_popup = document.querySelector('.popup');
window.addEventListener('click', function (e) {
if (!class_popup.contains(e.target)) {
Close();
}
});
}
/*Closing the popup */
Close() {
popup.removeChild(id_popup);
history.replaceState(null, null, ' ');
}
render() {
return (
<div>
<input type="submit" onClick={this.Open} />
<title>test popup</title>
<div id="popup1" className="overlay">
<div className="popup">
<h2>Title</h2>
<a className="close" onClick={this.Close} href="javascript://">
×
</a>
<div className="content">
my popup content
</div>
</div>
</div>
</div>
)
}
}
export default Popup;
Css :
.overlay {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
transition: opacity 500ms;
visibility: hidden;
opacity: 0;
}
.overlay:target {
visibility: visible;
opacity: 1;
}
.popup {
margin: 70px auto;
padding: 20px;
background: #fff;
border-radius: 5px;
width: 60%;
position: relative;
transition: all 5s ease-in-out;
}
.popup h2 {
margin-top: 0;
color: #333;
font-family: Tahoma, Arial, sans-serif;
}
.popup .close {
position: absolute;
top: 20px;
right: 30px;
transition: all 200ms;
font-size: 30px;
font-weight: bold;
text-decoration: none;
color: #333;
}
.popup .close:hover {
color: #06D85F;
}
.popup .content {
height: 60%;
overflow: auto;
}
#media screen and (max-width: 700px) {
.box {
width: 70%;
}
.popup {
width: 70%;
}
}
</style>
Thank you.
It seems like your component is rendered on the server, if it is the case, history.replaceState(null, null, ' '); won't compile because history is a member of window which does not exist on the server. So you will need to check if your code is running on the server or the client, there are different ways to do this depending on the SSR framework you are using, for instance nextjs provides process.browser which is true if on the client or undefined in node:
if(process.browser) window.history.replaceState(null, null, ' ');
Then for your event.stopPropagation part, event is not defined anywhere in the code you provided, so there must be a problem in your implementation (maybe add it to the function parameter.)

Using .show/.hide with .next causing issues

I am wanting to display the service-specificBar-tab of serviceBarId1 on page load and hide the other tabs, which is working. However, the part that isn't working like I want is when I click on that tab, I want the rest of the other three tabs to show in the order in which the HTML is and then when I click on the first tab again, for tabs 2, 3 and 4 to close. The method I am using now is acting very buggy. When you click on serviceBarId1 to open the tabs, all of the tabs open, but then one disappears - this didn't happen until I added:
$("#serviceBarId1").click(function() {
$("#serviceBarId2").hide(1000);
$("#serviceBarId3").hide(1000);
$("#serviceBarId4").hide(1000);
});
When I try to close the tabs, nothing happens.
What am I doing wrong?
$("#serviceBarId1").addClass("active");
$("#serviceBarId2").hide();
$("#serviceBarId3").hide();
$("#serviceBarId4").hide();
$("#serviceBarId1").click(function() {
$(".service-specificBar-tab").first().show("fast", function showNext() {
$(this).next(".service-specificBar-tab").show("fast", showNext);
});
});
$("#serviceBarId1").click(function() {
$("#serviceBarId2").hide(1000);
$("#serviceBarId3").hide(1000);
$("#serviceBarId4").hide(1000);
});
#gray {
background: #f9f9f9;
width: 100%;
height: 700px;
position: relative;
}
#service-specificBar-container {
position: relative;
top: 50px;
width: 100%;
padding: 25px 0;
}
#service-specificBar {
width: 100%;
height: 100px;
position: relevant;
}
.service-specificBar-tab {
width: 25%;
height: 100%;
display: inline-block;
margin: 0;
padding: 0px;
text-align: center;
font-size: 1.6em;
}
.service-specificBar-tab:nth-child(odd) {
background: #dbdbdb;
transition: ease-in-out .3s;
cursor: pointer;
}
.service-specificBar-tab:nth-child(even) {
background: #FFF;
transition: ease-in-out .3s;
cursor: pointer;
}
#serviceBarId1:hover,
#serviceBarId2:hover,
#serviceBarId3:hover,
#serviceBarId4:hover {
transition: ease-in-out .3s;
color: #FFF;
}
#serviceBarId2:hover {
background: #0085A1;
}
#serviceBarId3:hover {
background: #a11c00;
}
#serviceBarId4:hover {
background: #00a16d;
}
/*----Test for page swithces ----*/
#serviceBarId1.active {
background: #a10085;
color: #FFF;
}
#serviceBarId2.active {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="gray">
<div id="service-specificBar-container">
<div id="service-specificBar">
<div class="service-specificBar-tab" id="serviceBarId1">A</div>
<div class="service-specificBar-tab" id="serviceBarId2">B</div>
<div class="service-specificBar-tab" id="serviceBarId3">C</div>
<div class="service-specificBar-tab" id="serviceBarId4">D</div>
</div>
</div>
</div>
On the click event you could check the number of visible items. If the length of the visible divs is 1, show the siblings, otherwise, hide them:
$("#serviceBarId1").click(function() {
if ($('#service-specificBar').find(':visible').length == 1) {
$(".service-specificBar-tab").first().show("fast", function showNext() {
$(this).next(".service-specificBar-tab").show("fast", showNext);
});
} else {
$(".service-specificBar-tab").next().hide("fast", function hideNext() {
$(this).next(".service-specificBar-tab").hide("fast", hideNext);
});
}
});
Fiddle Demo

Categories

Resources