Vue - How to convert the entire project to dark mode by clicking a button? - vue.js

I have a Vue project and I have more than 50 components now, I want to prepare a dark mode for the entire project and I want to control the Mode type from a button on my navbar. I made a test version so I figured how to active and deactive classes but I don't know how to do that for the entire project by clicking a single button or check a checkbox. Here is my test;
<div class="container-main" :class="{'background-dark' : darkMode }">
<!-- Enable Dark Mode -->
<div>
<label class="form-switch">
<input type="checkbox" class="switch switch-md" v-model="darkMode" />
</label>
<label">Enable Dark Mode</label>
</div>
</div>
<style scoped>
.background-dark {
background-color: black;
}
</style>
When the switch is checked, darkMode variable turns to true and the class gets active, so my background color turns to black. My question is, I will create the dark mode version of the CSS file I use right now and I want this control to be in the navbar, how can a button or switch control the entire components' css classes in a project. If I need to use props, how do I do that? Thanks in advance.

Related

Vuetify use v-dialog components inside v-card-actions without causing padding issues

You can see the issue I'm having here:
https://codepen.io/ryanrapini/pen/LYeWZKR?editors=1010
Essentially, I have several dialogs which I have contained into their own custom "vue components" i.e. order-dialog.vue. In an ideal world, I could simply include this <order-dialog> component wherever I need it, and it would render the activator button and then handle all of the dialog state inside the component, so the parent doesn't need to worry.
Unfortunately, if I do this in a v-card-actions section I get spacing issues. Is this a bug with Vuetify or am I doing something wrong?
I thought that by moving the activator out of the <v-dialog> tag it might fix the issue, but it still doesn't unless I break my component up into a v-dialog component and a separate activator, which means I now need to manage the state of the dialog in the parent.
Thanks for any help.
I don't think you are doing something wrong, and I'm not sure that it's a Vuetify bug.
This comes from CSS rule in Vuetify library:
.v-application--is-ltr .v-card__actions>.v-btn.v-btn+.v-btn {
margin-left: 8px;
}
I think the authors assumed that this block should contain only buttons. But in your case (in 2nd and 3rd approach) an output HTML looks like this:
<div class="v-card__actions">
<button class="v-btn ...">
...
</button>
<div class="v-dialog__container"><!----></div>
<button type="button" class="v-btn ...">
...
</button>
<button type="button" class="v-btn ...">
...
</button>
</div>
So v-dialog__container breaks this rule.
You can fix you issue, by example, with an additional rule:
.v-application--is-ltr .v-card__actions>.v-btn:not(:first-child) {
margin-left: 8px !important;
}
Or you can also apply helper classes (ml-2) into specific buttons.

BSVue and VuejS2: How to show correct toggle state of accordion icons?

I am using Bootstrap-Vue's accordion component and I am struggling with trying to figure out how I can show the correct collapse state for the + and - icons on the right hand side of the accordion buttons.
Does anyone know how to start the icon in the + state and when the user clicks the accordion button and shows the content, I want the icon to be -.
I hope this makes sense. I have JSFiddle here: https://jsfiddle.net/26gvdxqo/
Adding this to the code will fix your issue:
...
<div class="when-open"> + </div>
<div class="when-closed"> - <div>
...
<style>
.collapsed > .when-open,
:not(.collapsed) > .when-closed {
display: none;
}
</style>

Vue vuetify v-dialog preventing screen from scrolling

A Vuetify question. Something has just started appearing in my app. On several views/components, I have a v-dialog. Up until a short while ago, the dialog would open correctly but as it was often taller than the screen I could comfortably scroll. Now the dialog seems to have taken control in the respect that I cannot scroll at all when a dialog is open.
This won’t scroll, so I can’t move to the bottom of the dialog. As I said, this is a “new” thing:
What I did, maybe this helps. I put a vue-youtube inside a new component (which is in a v-dialog), I was not happy with exactly where it was, I wanted it higher on the screen so I did the following:
<style scoped>
.v-dialog {
position: absolute;
top: 10%;
}
</style>
However, I initially forgot to use scoped. Not sure if this is the cause but all my dialogs have been affected.
What you need is a scrollable dialog, Please check the link https://vuetifyjs.com/en/components/dialogs/#scrollable
<v-dialog v-model="dialog" scrollable>
<v-card class="pa-3">
<v-card-text>
<v-form>
<!-- Add your form here -->
</v-form>
</v-card-text>
</v-card>
</v-dialog>

How to use a button inside v-text-field label slot

I need to insert a clickable button inside v-text-field under label slot. Meaning that there will be label : " Start typing or Select Search Panel" where "Select Search Panel" will be a link or button.
I'm able to make it visible using the v-slot:label but the button is not clickable and onSearchPanelClicked in not triggered..
<v-text-field class="input-field" clearable prepend-inner-icon="search" solo >
<template v-slot:label class="linkLabel" v-on:click="onSearchPanelClicked">
Start typing or <v-btn v-on:click="onSearchPanelClicked" class="link" flat > Select Search Panel</v-btn>
</template>
</v-text-field>
Is there any way to transfer click event to the element ? If I start typing the label must disappear like it used to work on v-text-field.
Regards
Jan
You have to overwrite your input .v-label CSS rule pointer-events.
Vuetify sets the label inside a v-text-field like this:
.v-text-field .v-label {
pointer-events: none; // unclickable element
}
So changing it to auto will enable your button inside v-text-field label to become the target of pointer events, just be aware of deep selectors when working with scoped styles at your component.
.v-input.input-field .v-label {
pointer-events: auto;
}
/* or for scoped styles */
::v-deep .v-input.input-field .v-label {
pointer-events: auto;
}
In this example the rule is applied only to fields with your custom class .input-field, if you'd like to overwrite for all the v-text-fields just remove it from the CSS code.

How do I make the expansion-panel open only on clicking collapse icon on the right?

How do I make this expansion-panel open content only on clicking icon?
Tried using readonly but it didn't help.
Thanks in advance!
https://vuetifyjs.com/en/components/expansion-panels#expansion-panel
You can put online the argument in all collapse like: expanded={!expanded}
and in the icon you put the onClick={toggle}
I was having the same problem and just found a solution for that.
You need to implement a custom button on the expansion panel, so it will accept custom events. You can achieve that using template and v-slot:
<v-expansion-panel #click.prevent="onClick()">
<v-expansion-panel-header>
...your expansion panel code here
<template v-slot:actions>
<v-btn icon #click.stop="onClick()">
<v-icon>mdi-filter-variant</v-icon>
</v-btn>
</template>
</v-expansion-panel-header>
</v-expansion-panel>
...and your onClick method would be like this:
onClick() {
/*this will toggle only by icon click. at the same time, will prevent toggle
by clicking on header. */
const curr = this.panel
this.panel = curr === undefined ? 0 : undefined
}
It may seem a little magical that the same function is toggling on icon click and preventing toggle on header click, but this happens because the custom icon button does not toggle itself, so we force that using the onClick method. On the other hand, the expansion panel header has its native property of toggling the panel. So when we click it, its value will automatically change and we need to change it back to what it was before the click.
To make the expansion-panel open only on clicking icon you can use css that disables all clicks on the header and only allows clicks on the icon:
<style>
.v-expansion-panel-header{
pointer-events: none;
}
.v-expansion-panel-header__icon{
pointer-events: All;
}
</style>
Keep in mind if you are using scoped style you have use >>>:
https://vue-loader.vuejs.org/guide/scoped-css.html#deep-selectors
Here is the template example, I added #click to provide btn like experience when user clicks on an icon, it's not necessary:
<template>
<v-expansion-panel>
<v-expansion-panel-header>
<template #actions>
<v-icon class="icon Icon Icon--32 icon-utility-arrows-carrot_down-32"
#click/>
</template>
</v-expansion-panel-header>
<v-expansion-panels >
<v-expansion-panel-content >
<!--content here-->
</v-expansion-panel-content>
</v-expansion-panels>
</v-expansion-panel>
</template>