VueJS - How to toggle between dark and light themes in vuexy by clicking on icon - vue.js

I am trying to toggle between the dark and light themes using icon, i have tried using the radio buttons and it works absolutely fine i don't know where i am going wrong with icons.
Here is the code that works with vs-radio buttons:
<vs-radio v-model="changeTheme" vs-value="light" vs-name="theme-mode-light">Light</vs-radio>
<vs-radio v-model="changeTheme" vs-value="dark" vs-name="theme-mode-dark">Dark</vs-radio>
...
<script>
watch: {
layoutType (val) {
// Reset unsupported options
if (val === 'horizontal') {
if (this.changeTheme === 'semi-dark') this.changeTheme = 'light'
if (this.navbarType === 'hidden') this.navbarTypeLocal = 'floating'
this.$emit('updateNavbarColor', '#fff')
}
}
},
computed: {
changeTheme: {
get () { return this.$store.state.themecolr},
set (val) { this.$store.dispatch('updateTheme', val) }
},
}
</script>
Here is the code which i am trying to achieve currently:
<div class="con-img ml-3">
<feather-icon v-if="this.$store.state.themecolr=== 'light'" icon="Icon" v-model="changeTheme" vs-name="theme-mode-light"/>
</div>
<div class="con-img ml-3">
<feather-icon v-if="this.$store.state.themecolr=== 'dark'" icon="Icon" v-model="changeTheme" vs-value="dark" vs-name="theme-mode-light"/>
</div>
...
methods: {
changeTheme: {
get () { return this.$store.state.themecolr},
set (val) { this.$store.dispatch('updateTheme', val) }
},
}
I tried adding #change and #click to the feather icon but that did not work out, and i also tried adding the function like this :
changeTheme (){
if(this.$store.state.themecolr=== 'light'){
return this.$store.state.themecolr=== 'dark'
}else if(this.$store.state.themecolr=== 'dark'){
this.$store.state.themecolr=== 'light'
}
}
Please someone help me to achieve this, i want to toggle the theme using the feather icons, but i am able to do it with the radio buttons, but that s not what i want.

I looked at the implementation of the vue-feather-icons here
and it is missing the event handlers.
If that is the case, it means those components don't emit any events.
I would suggest you move your event handler to the surrounding div for the icons. see what I did here for an example: https://codesandbox.io/s/distracted-noether-gud0p?file=/src/App.vue

Related

How to replace a navbar with a search div when scrolling down in VueJS3?

I am new to vuejs, I am trying to make my search component to replace my fixed-top navbar when the searchdiv hit the top of the screen while scrolling down, and when I scroll up, the navbar will only appear when the user is on top. I have seen this kind of functionaliy like google search. please see:
This is the normal view:
This is the scrolled view:
and this is mine:
Here is my code:
created() {
window.addEventListener('scroll', this.handleScroll);
},
destroyed() {
window.removeEventListener('scroll', this.handleScroll);
},
mounted() {
console.log("HomeLandingComponent mounted");
},
methods: {
handleScroll() {
let scrollY = window.scrollY
if (scrollY > this.startY) {
this.navbar_visible = false;
} else {
this.navbar_visible = true;
}
this.startY = scrollY;
}
}
what is does is just basically hide the navbar when scroll down and show navbar on scroll up. Is there a way on how to achieve it?
Simple.
Ensure that the search bar comes after the navbar and that the search bar is not nested; then on the search bar, position fixed; z-index: 1; you can use JavaScript to add a new class to give background a new colour.
Shouldn't be too hard. I'll write the code once I'm on my PC.

How to Customize just the property pane without building webpart

Does anyone know how can I show the property pane without creating webpart?
I want to show the property pane after clicking the User Management icon, which is created with extension
Taken from this repo which has some of the official samples from the SPFx extensions model and depicts a pretty close use-case to the one that you are searching, there is an element in Fluent UI called Panel.
As it is written in the documentation:
Panels are overlays that contain supplementary content and are used for complex creation, edit, or management experiences. For example, viewing details about an item in a list or editing settings.
Furthermore, scouring the repo we can see that the panel is triggered:
...
import { Panel, PanelType } from "office-ui-fabric-react/lib/Panel";
...
class GraphBot extends React.Component<IGraphBotProps, IGraphBotState> {
....
public render() {
// Be careful, the user Id is mandatory to be able to use the bot state service (i.e privateConversationData)
return (
<div className={ styles.banner }>
<ActionButton onClick= { this._login } checked={ true } iconProps={ { iconName: "Robot", className: styles.banner__chatButtonIcon } } className={ styles.banner__chatButton}>
{ strings.GraphBotButtonLabel }
</ActionButton>
<Panel
isOpen={ this.state.showPanel }
type={ PanelType.medium}
isLightDismiss={ true }
onDismiss={ () => this.setState({ showPanel: false }) }
>
{ this.state.isBotInitializing ?
....
}
</Panel>
</div>
);
}
There is an <ActionButton> with an OnClick Eventhandler to execute the below function :
private async _login() {
this.setState({
isBotInitializing :true,
showPanel: true,
});
....
The above function sets the showPanel prop to true and this prop is used in the Panel Component, where it checks when set to true to open the Panel and move on with the Business Logic of the application extension.
The same can be seen in the Fluent UI Documentation here, in the basic example.
import * as React from 'react';
import { DefaultButton } from '#fluentui/react/lib/Button';
import { Panel } from '#fluentui/react/lib/Panel';
import { useBoolean } from '#fluentui/react-hooks';
export const PanelBasicExample: React.FunctionComponent = () => {
const [isOpen, { setTrue: openPanel, setFalse: dismissPanel }] = useBoolean(false);
return (
<div>
<DefaultButton text="Open panel" onClick={openPanel} />
<Panel
headerText="Sample panel"
isOpen={isOpen}
onDismiss={dismissPanel}
// You MUST provide this prop! Otherwise screen readers will just say "button" with no label.
closeButtonAriaLabel="Close"
>
<p>Content goes here.</p>
</Panel>
</div>
);
};

Can't change transition on the fly for a transition group

In my app, clicking a modal's close button makes it disappear with a fade animation whereas swiping it down makes it disappear with a swipe animation. This is done by changing the modal's <transition name> based on event.
The same thing doesn't seem to work with a transition group. Am I doing something wrong, or is it actually not possible?
CodeSandbox
Template:
<transition-group :name="itemTransition">
<div
v-for="item in items"
:key="item.id"
v-hammer:swipe.up="() => onSwipeUp(notification.id)"
>
</div>
</transition-group>
Script:
export default {
data () {
return {
applySwipeTransition: false
}
},
computed: {
itemTransition () {
return this.applySwipeTransition ? 'swipe' : 'fade'
}
},
methods: {
onSwipeUp (id) {
this.applySwipeTransition = true
this.$nextTick(() => {
this.closeItem(id)
this.applySwipeTransition = false
})
}
}
}
CSS:
.fade-leave-active {
animation: fade-out .75s;
}
.swipe-leave-active {
animation: slide-up .25s;
}
The problem lies in the timing of component update. You are switching the transition mode back to fade in the same update cycle as when the element is closed. Thus, when the next component update is triggered (by removal of the item), the transition is already switched back to fade. At this point, you may have guessed that all that needs to be done, is to switch the transition back in the next update, triggered by removal of the item:
onSwipeUp (id) {
this.applySwipeTransition = true
this.$nextTick(() => {
this.closeItem(id)
this.$nextTick(()=>{
this.applySwipeTransition = false
})
})
}
Since there are no reasons to wait for component update to close the item, you can simplify the code a bit:
onSwipeUp (id) {
this.applySwipeTransition = true
this.closeItem(id)
this.$nextTick(() => {
this.applySwipeTransition = false
})
}
Here is your working sandbox: https://codesandbox.io/s/vue-template-forked-60lkk?file=/src/App.vue
So, I've worked around with your CSS by manually changing the name of the <transition-group to either fade or swipe to see if the there's a problem with the CSS animations.
Verdict: The fade works. swipe only transitions the list-item off the page by a click and drag, not true swipe, if that concerns you (by the way, my swipe is MacOS swipe - two-finger, no click)
Still, without changing the CodePen, the issue seems to be with your computed property where there's nothing telling the name to change dynamically even though you've bound it to a computed property - the logic for itemTransition() seems to always default to fade because the applySwipeTransition would never equal to "swipe", given that the CSS does work when you manually change name to swipe (see "Verdict)".
To see where the underlying issue was, I worked around with your itemTransition():
computed: {
itemTransition() {
return this.applySwipeTransition ? "fade" : "swipe";
},
Switching the order of the fade and swipe now makes swipe work. I hope this gives you some insight into the issue. You may need to create a custom Vue directive or event to handle the swipe / fade logic if needed.

enter and leave classes of vue transition doesn't work

I created this codepen, which is a simple flip card and it works fine in codepen, but when I add this project in my vue project created with cli, everything works fine; upon clicking a card, it shows back of the card, but it doesn't apply that transition so user can visually see that it is rotating. It rotates very fast, sounds like transition is not effecting.
This is the template code
<div v-for="card in cards" #click="toggleCard(card)" :key="card.id">
<transition name="flip">
<div
v-bind:key="card.flipped"
v-html="card.flipped ? card.back : card.front"
></div>
</transition>
</div>
and the script code
export default {
name: "FlipCard",
data() {
return {
cards: [
// cards here
],
};
},
methods: {
toggleCard: function (card) {
const isFlipped = card.flipped;
this.cards.forEach((strategy) => {
strategy.flipped = false;
});
isFlipped === true ? (card.flipped = false) : (card.flipped = true);
},
},
};
and css code:
.flip-enter-active {
transition: all 2s ease;
}
.flip-leave-active {
display: none;
}
.flip-enter,
.flip-leave {
transform: rotateY(180deg) !important;
opacity: 0;
}
can anyone help why in vue cli project the transition is so fast or maybe not applying?
Thank you in advance
The codepen you provided uses Vue 2. Your question is tagged Vue 3, so I assume you are using Vue 3.
Vue 3 made changes to transition class names - https://v3-migration.vuejs.org/breaking-changes/transition.html#_2-x-syntax.
-enter and -leave are now -enter-from and -leave-from.

Resize button according to screen size

For a button, by default Bootstrap 4 allow you to set default button "size" between : xs, sm, md, lg, xl.
So, in my code, small screen first, i use sm size for screen <576px :
<button type="button" class="btn btn-success btn-sm"></button>
But for xl screen ≥1200px, need i to change size attribute or something else with Bootstrap to adjust button size ?
I don't really understand Bootstrap responsive behavior for button and 'size' attribute between small and large screen.
Thanks.
I don't think there's anything built out of the box for responsive buttons in bootstrap, you'd probably be better off extending the existing bootstrap button sizes in sass/media queries ie
.responsive-button {
#media (min-width: 576px) { #extend .btn-sm }
#media (min-width: 768px) { #extend .btn-md }
}
I haven't tested this so may need to research a bit further but hopefully this gets you on track :)
According to the Vue.js documentation, i had finally computed my CSS class dynamically according to window.onresizeevent call in mounted () function.
Example :
Here is my Bootstrap button :
<b-button :size="nsize" variant="outline-success" class="my-2 my-sm-0">
<font-awesome-icon icon="search"/>
</b-button>
Here is my function in App.vue file:
<script>
export default {
name: 'topnavbar',
data () {
return {
nsize: "sm",
mediaWidth: Math.max(document.documentElement.clientWidth, window.innerWidth || 0)
}
},
mounted () {
if (window.addEventListener) {
window.addEventListener("resize", this.updateSize, false);
} else if (window.attachEvent) {
window.attachEvent("onresize", this.updateSize);
}
},
methods : {
updateSize: function (){
let sizeEl = "md";
let width = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
if(width <= 576){
sizeEl = "sm";
}
this.nsize = sizeEl;
}
}
}
</script>
Sources:
Get the browser viewport dimensions with JavaScript
https://fr.vuejs.org/v2/guide/class-and-style.html