Transform Based Animation using Vue Transition Wrapper - vue.js

I'm trying to port some animation implemented mostly through css and little javascript to a Vue component. The animation is simple - user clicks a button and a little panel opens from the bottom of his browser and slides upwards.
I have a working Vue component implemented using the same css and no javascript.
Now, I'm aware of the transition wrapper that Vue provides. But I'm unable to figure out how to get similar functionality using the transition wrapper (if at all).
Can someone help me out here?
// register modal component
Vue.component('modal', {
template: '#modal-template',
props: ['show']
})
// start app
new Vue({
el: '#app',
data: {
showModal: false
}
})
.drawer-wrapper {
position: fixed;
top: 100%;
left: 0;
right: 0;
height: 50%;
z-index: 9998;
transition: transform .3s ease-out;
}
.drawer-wrapper.open {
transform: translateY(-100%);
}
.drawer-container {
height: 100%;
width: 100%;
background-color: white;
}
.drawer-header h3 {
margin-top: 0;
color: #42b983;
}
.drawer-body {
margin: 20px 0;
}
.drawer-default-button {
float: right;
}
<script src="https://unpkg.com/vue#latest/dist/vue.js"></script>
<!-- template for the modal component -->
<script type="text/x-template" id="modal-template">
<div class="drawer-wrapper" :class="{ open: show }">
<div class="drawer-container">
<div class="drawer-header">
<slot name="header">
default header
</slot>
</div>
<div class="drawer-body">
<slot name="body">
default body
</slot>
</div>
<div class="drawer-footer">
<slot name="footer">
default footer
<button class="drawer-default-button" #click="$emit('close')">
OK
</button>
</slot>
</div>
</div>
</div>
</script>
<!-- app -->
<div id="app">
<button id="show-modal" #click="showModal = true">Show Modal</button>
<!-- use the modal component, pass in the prop -->
<modal #close="showModal = false" :show="showModal">
<!--
you can use custom content here to overwrite
default content
-->
<h3 slot="header">custom header</h3>
</modal>
</div>

I got this to work using a transition wrapper, but the code isn't as elegant as I'd expected. Particularly the use of the following attributes in the drawer-wrapper class:
top: 100%;
transform: translateY(-100%);
Fiddle is here
If anyone can simplify the code further, I'd really appreciate it.

Related

Vuejs: How to add Transition to slot content?

I have a modal component that handles the overlay and css etc. and allows for modal content to be passed in via a slot:
<div class="slot-content">
<slot></slot>
</div>
And it's being used like
<Modal ...>
<div class="some-modal-content-div">
...
</div
</Modal>
Currently the modal appearance is a bit "abrupt".
I do want the overlay be there instantly, but would like to add a bit of a transition to the appearance of the content div.
How do I add a <Transition> to just the slot content?
If I understood you correctly maybe like following snippet:
const app = Vue.createApp({
data() {
return {
show: false,
};
},
})
app.component('modal', {
template: `
<div class="slot-content">
<p>other content</p>
<transition name="slide-fade" appear>
<slot></slot>
</transition>
</div>
`
})
app.mount('#demo')
.slide-fade-enter-active {
transition: all 0.5s ease-out;
}
.slide-fade-leave-active {
transition: all 1s cubic-bezier(1, 0.5, 0.8, 1);
}
.slide-fade-enter-from,
.slide-fade-leave-to {
transform: translateX(20px);
opacity: 0;
}
.mod {
border: 1px solid purple;
}
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<button #click="show = !show">show</button>
<modal v-if="show" class="mod">
<div class="some-modal-content-div">
<b>slot content</b>
</div>
</modal>
</div>
I was actually too fixated on using the vue Transition instead of just applying the css animation directly to the slot content container:
<div class="slot-content animate-class">
<slot></slot>
</div>
...
.animate-class {
animation: foo 0.1s;
}

Vue Video Background does not start

I'm starting as a frontend developer with VueJs and I'm having a problem that I can't understand... So I hope if some could help me... I'm currently using avidofood
/
vue-responsive-video-background-player
Because I need some kind of video playlist in the background. I implemented such as official documentation said (at least I think so..) but nothing happened, I mean, I have no errors, but the video does not start. This is my code:
In App.vue
<template>
<div id="App">
<video-background
src="https://www.youtube.com/watch?v=PpAxlizirDI"
style="max-height: 80%; height: 100vh"
>
<h1 style="color: white">Test App!</h1>
</video-background>
<div class="container mt-5">
<div class="row">
<div class="col-xl-12 col-lg-10">
<div class="form-group barcode">
<div class="row">
<div class="col">
<input
id="barcode"
type="text"
name="barcode"
class="form-control pl-3 shadow-none bg-transparent border-0"
placeholder="Acerca el producto al lector..."
autofocus
onfocus="this.value=''"
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
//Oculto el mouse
//document.body.style.cursor = "none";
export default {
name: "App",
};
</script>
<style>
#myVideo {
position: fixed;
right: 0;
bottom: 0;
min-width: 100%;
min-height: 100%;
}
body {
background: #eee;
}
.text-color {
color: rgb(212, 14, 14) !important;
}
.barcode {
border: 1px solid;
border-color: #cccccc;
border-radius: 45px;
}
.container {
position: absolute;
bottom: 0px;
left: 10%;
margin: 0 auto;
}
</style>
In main.js
import Vue from 'vue'
import BootstrapVue from 'bootstrap-vue/dist/bootstrap-vue.esm';
import App from './App.vue'
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap-vue/dist/bootstrap-vue.css';
import VideoBackground from "vue-responsive-video-background-player";
Vue.component("video-background", VideoBackground);
Vue.use(BootstrapVue);
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#App')
In Vue dev Tool:
In Chrome Console:
This is de Project Structure:
I hope someone could help me because I have no little idea what's going on.
Thanks in advance!
As source, you have a YouTube page, this is not a video.
<video-background
src="https://www.youtube.com/watch?v=PpAxlizirDI"
style="max-height: 80%; height: 100vh"
>
This is your path to your video. You can just use this value for
showing your video in every resolution.
The source of the video has to be in a format the browser can play (mp4 is a good format to use).
For example:
<video-background
src="/files/my-video.mp4"
style="max-height: 80%; height: 100vh">
Update based on your comment:
Because vue gets compiled it does not know what assets/demo.mp4 is,. You should import it first via an loader.
<script>
import video from 'assets/demo.mp4' // Or '#/assets/demo.mp4' depending on what loader you use.
export default {
name: "App",
};
</script>
And now you could use:
<video-background
:src=video
style="max-height: 80%; height: 100vh">

Navbar transparent in buefy

I am creating a landpaging and I am facing some style difficulties due to lack of practice.
I want to modify the backgroud of the navbar, so I wanted to make the background transparent so that the bottom of the page appears. How can I do this?
enter image description here
<template>
<div class="Shellhub-LP-1280">
<div class="textura Nuvem">
<b-navbar>
<template slot="brand">
<b-navbar-item tag="router-link" :to="{ path: '/' }" transparent="true">
<img
src="https://raw.githubusercontent.com/buefy/buefy/dev/static/img/buefy-logo.png"
alt="Lightweight UI components for Vue.js based on Bulma"
>
<!-- <img src="#/static/logo-inverted.png"> -->
</b-navbar-item>
</template>
...
</b-navbar>
</div>
</div>
</template>
<style>
.Shellhub-LP-1280 {
/* width: 100%; */
height: 2283px;
background-color: #333640;
}
.textura {
/* width: 100%; */
height: 771px;
}
.Nuvem {
width: 100%;
height: 755px;
object-fit: contain;
opacity: 0.9;
float: right;
background: url('../static/nuvem.png');
background-repeat: no-repeat;
background-position: right;
}
Thanks
buefy navbar API:
https://buefy.org/documentation/navbar/#api-view
Passing this props:
<b-navbar :fixed-top="true" :transparent="true" >
Vue docs - components props (recommend to read):
https://v2.vuejs.org/v2/guide/components-props.html
transparent "bug":
Open github issue:
BUG: navbar is-transparent not working .
IMPORTANT: transparent affect navbar items (Not the navbar wrapper himself).
Remove any hover or active background from the navbar items
So add simple CSS styling:
nav.navbar.is-fixed-top {
background: transparent;
}
body top padding issue
I won't find a way to remove body top padding. I added this style:
body{
padding-top: 0px!important;
}
Basic example:
const app = new Vue()
app.$mount('#app')
img.responsive_img{
width: 100%;
height: auto;
}
body{
padding-top: 0px!important;
}
/* change navbar background color */
nav.navbar.is-fixed-top {
background: transparent;
}
<link href="https://unpkg.com/buefy/dist/buefy.min.css" rel="stylesheet"/>
<div id="app">
<b-navbar class="is-link" :fixed-top="true" :transparent="true">
<template slot="brand">
<b-navbar-item tag="router-link" :to="{ path: '/' }">
<img
src="https://raw.githubusercontent.com/buefy/buefy/dev/static/img/buefy-logo.png"
alt="Lightweight UI components for Vue.js based on Bulma"
>
</b-navbar-item>
</template>
<template slot="start">
<b-navbar-item href="#">
Home
</b-navbar-item>
<b-navbar-item href="#">
Documentation
</b-navbar-item>
<b-navbar-dropdown label="Info">
<b-navbar-item href="#">
About
</b-navbar-item>
<b-navbar-item href="#">
Contact
</b-navbar-item>
</b-navbar-dropdown>
</template>
<template slot="end">
<b-navbar-item tag="div">
<div class="buttons">
<a class="button is-primary">
<strong>Sign up</strong>
</a>
<a class="button is-light">
Log in
</a>
</div>
</b-navbar-item>
</template>
</b-navbar>
<header style="min-height: 200vh;">
<img class="responsive_img" src="https://picsum.photos/2000/600"/>
</header>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script src="https://unpkg.com/buefy/dist/buefy.min.js"></script>
Change navbar background color on scroll
only by custom code
See this codepen (I added a class on scroll):
https://codepen.io/ezra_siton/pen/jOPZgmR
Change the background color on scroll her:
nav.navbar.is-fixed-top.isActive{
transition: background-color 0.5s ease;
background: red; /* change color on scroll */
}
Change navbar links color to white (For dark hero) - add "is-link" modifier:
https://bulma.io/documentation/components/navbar/#colors
<b-navbar class="is-link" :fixed-top="true" :transparent="true" >
Remove hover/active
:transparent="true"
Remove any hover or active background from the navbar items.

How do you apply Vue Transitions when Changing CSS Class?

I can't get Vue to apply Transition animation effects when changing from one CSS class to another (using V-bind).
I've gone through the Vue documentation but none of the examples work for my use case. I basically want the DIV to transition by fading nicely from full screen to "regular size" by toggling.
Please see Fiddle at https://jsfiddle.net/luckman8/892ktedz/
`
<div v-bind:class="{'fullscreen':isFullScreen, 'regularSize':!isFullScreen}">
<button type="button" #click="toggle">
Toggle
</button>
<p>
{{isFullScreen}}
</p>
</div>
`
The CSS:
.fade-enter-active, .fade-leave-active {
transition: opacity 3s ease-out;
}
.fade-enter, .fade-leave-to {
opacity: 0.1;
}
.regularSize
{
width: "50%";
height: "50%";
background-color: "green";
}
.fullscreen
{
display: flex;
flex-direction: column;
position: fixed;
background-color:blue;
top:0;
left:0;
width: 100%;
height: 100%;
flex-basis:10%;
overflow-y:hidden;
}
The Vue code:
new Vue({
el: "#app",
data: {
isFullScreen:false
},
methods: {
toggle()
{
this.isFullScreen = !this.isFullScreen
}
}
})
Thank you in advance!
The <transition> effects will only work for elements that change their visibility. So for example by using v-if.
So you have two options.
Either add a v-if logic to your template.
For example: (a quick mock up. could be refactored to be cleaner)
<div id="app">
<button type="button" #click="toggle">
Toggle
</button>
<transition name="fade">
<div
v-if="isFullScreen"
v-bind:class="{
'fullscreen':isFullScreen,
'regularSize':!isFullScreen
}">
<p>FULL SCREEN</p>
<button type="button" #click="toggle">
Toggle
</button>
</div>
</transition>
<transition name="fade">
<div
v-if="!isFullScreen"
v-bind:class="{
'fullscreen':isFullScreen,
'regularSize':!isFullScreen
}">
<p>SMALL SCREEN</p>
</div>
</transition>
</div>
Create the transition effect purely with css.

Extracting methods and data out to component

very new to VueJS. Appreciate any help you can give me!
I'm wanting to extract some code that I've put within app.js out to my component. It appears that the vuejs syntax changes depending on what you're including? Sometimes template is within a property, and other times it has its own tag. Not quite sure what to do here.
VueJS + Laravel 5.5
app.js:
require('./bootstrap');
require('sweetalert');
window.Vue = require('vue');
import Modal from './components/Modal';
Vue.component('Modal', require('./components/Modal.vue'));
const app = new Vue({
el: '#app',
data: {
showModal: false
},
methods: {
openModal() {
this.showModal = true;
},
closeModal() {
this.showModal = false;
},
submitAndClose() {
//
}
}
});
components/Modal.vue
<template>
<transition name="modal">
<div class="modal modal-mask" style="display: block">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<slot name="header"></slot>
</div>
<div class="modal-body">
<slot name="body"></slot>
</div>
<div class="modal-footer">
<slot name="footer"></slot>
</div>
</div>
</div>
</div>
</transition>
</template>
<style>
.modal-mask {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .5);
display: table;
transition: opacity .3s ease;
}
</style>
Is there a way to extract the methods and data out of app.js and contain it all within Modal.vue. Quite a basic question I'm sure but Vue seems to be very confusing with its syntax..
Thanks!
You can register a component by using Vue.component(tagName, options). The 2nd parameter options is an object with different properties like name, template etc
You could also use single-file components with the extension .vue in combination with a build tool like Webpack. The template will be placed with a <template> tag, styles within a <style> tag and the options object within a <script> tag. You can read more about single-file components here.