Vuetify - List menu activator visibility toggle - mouseover

I have 3 cards when mouse hover on card title it shows a arrow_down icon & i can click on it , it a drop down menu with Delete function when i hover over the v-card-title it shows the icon but after i click on it, mouse on drop-down menu the arrow_down icon disappeared,
how to properly implement it ?
https://codepen.io/sharon-the-encoder/pen/WLWyoG?editors=0010
const cards = [
{
title: "Gooey PBJ Brownies",
author: "John Walibur",
image: "https://placeimg.com/640/480/nature"
},
{
title: "Crisp Spanish Tortilla Matzo Brei",
author: "Colman Andrews",
image: "https://placeimg.com/640/480/animals"
},
{
title: "Grilled Shrimp with Lemon and Garlic",
author: "Celeste Mills",
image: "https://placeimg.com/640/480/arch"
}
];
new Vue({
el: "#app",
data: {
cards: cards,
selectedCard: -1
},
methods: {
hoverCard(selectedIndex) {
this.selectedCard = selectedIndex
},
isSelected(cardIndex) {
return this.selectedCard === cardIndex
},
passmsgid(index) {
alert(index)
}
}
});
body {
background-color: #e1e7e7;
}
.grey--text.selected {
color: red !important;
}
.iconkey {
display: none;
}
.iconkey.selected {
display: block;
color: blue !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.18/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuetify/1.4.2/vuetify.min.js">
</script>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css'>
<link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons'>
<div id="app">
<v-app>
<v-content>
<v-container>Hello world</v-container>
<v-container fluid>
<v-layout row wrap>
<v-flex xs12 sm4 md4 lg4 v-for="(card, index) in cards" :key="index">
<v-card class="ml-3 mt-3">
<v-img :src="card.image" height="200px">
</v-img>
<v-card-title primary-title #mouseover="hoverCard(index)" #mouseout="hoverCard(-1)">
<div>
<div class="headline">{{card.title}}</div>
<span class="grey--text" :class="{'selected': isSelected(index)}">{{card.author}} -
</span>
<v-expand-transition>
<v-menu bottom transition="scale-transition" nudge-bottom="40">
<v-btn icon slot="activator" styole="margin-bottom: -1em;">
<v-icon class="iconkey" :class="{'selected': isSelected(index)}">keyboard_arrow_down</v-icon>
</v-btn>
<v-list>
<v-list-tile>
<v-list-tile-title #click="passmsgid(index)">Delete</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
</v-expand-transition>
</div>
</v-card-title>
<v-card-actions>
<v-btn flat>Share</v-btn>
<v-btn flat color="purple">Explore</v-btn>
<v-spacer></v-spacer>
</v-card-actions>
</v-card>
</v-flex>
</v-layout>
</v-container>
</v-content>
</v-app>
</div>

Updated pen using more CSS, and without v-hover: Codepen
(Originally I used v-hover but for this case not needed)
Codepen
We will control visibility by using the following CSS class:
.hidden {
visibility: hidden;
}
menu-button is hidden unless:
a) we are hovering over its parent-tile or
b) when the corresponding menu is opened.
So we need to set up custom item (tile) component:
Set menu visibility control:
data: () => ({
menu: false, // control button-menu state (opened / closed)
})
And our template starts with v-hover component so we can detect when we hover over it and react to that event:
<template>
<v-hover>
<v-list-tile slot-scope="{ hover }" #click="">
// ...
<v-menu v-model="menu" offset-y left >
<v-btn slot="activator"
:class="{hidden: !hover && !menu}"
>
:class="{hidden: !hover && !menu}" - we set hidden class on button when we are not hovering over the parent-tile and when corresponding menu is closed.

Related

How do I programmatically scroll to a specific v-list-item in v-list?

I'm using Vue/Vuetify and have a v-list that is scrollable:
<v-layout scrollable ...
<v-list ...
<template v-for=id...
<v-list-item :key=id...
Is it possible to programmatically scroll the items so that a particular one is in the visible area of the scrollable list?
You can scroll to any DOM element using plain JavaScript method scrollIntoView.
Before that you can give an id for each element of your list. By example, this way:
<v-container>
<v-row>
<v-col>
<v-btn
ref="button"
block
color="primary"
#click="scrollTo"
>
scroll to Item-20
</v-btn>
</v-col>
<v-col cols="12">
<v-card>
<v-list max-height="300" class="overflow-y-auto">
<v-subheader>ITEMS</v-subheader>
<v-list-item
v-for="(item, i) in items"
:key="i"
:id="'list-item-' + (item.id + 1)">
<v-list-item-content>
<v-list-item-title v-text="item.text"></v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
</v-card>
</v-col>
</v-row>
</v-container>
...
data () {
return {
items: [],
}
},
mounted() {
for (let i = 0; i < 50; i++) {
this.items.push({ id: i, text: 'Item-' + (i + 1)})
}
},
methods: {
scrollTo() {
document.getElementById("list-item-20").scrollIntoView()
}
}
Test this at CodePen.
P.S.: there is no scrollable prop in v-layout API. At least, in latest v2.6.3.

Why isn't the v-icon displayed inside the v-text-field?

Can you tell me why the icon to the right of the v-text-field is not displayed?
I want to make the calendar open when you click on the icon.
codepen
<div id="app">
<v-app id="inspire">
<v-menu>
<template v-slot:activator="{ on }">
<v-text-field label="Hello world" style="max-width: 200px">
<!--The icon is not displayed-->
<v-icon v-on="on" color="primary" dark>event</v-icon>
</v-text-field>
</template>
<v-date-picker>
</v-date-picker>
</v-menu>
</v-app>
</div>
P.S.
Here is a good example. It's not mine.
Codepen
The HTML input field is empty https://www.w3schools.com/tags/tag_input.asp
There's an attribute to prepend and append icons in textfields in Vuetify: https://vuetifyjs.com/en/components/text-fields/#icons
You simply need to add it:
<v-text-field label="Hello world" style="max-width: 200px" append-icon="event">
I managed to do it. I did this without the activator template.
codepen vuetify
<div id="app">
<v-app id="inspire">
<v-text-field
label="Hello world"
style="max-width: 200px"
append-icon="event"
#click:append="show">
</v-text-field>
<v-menu
v-model="menu"
:position-x="x"
:position-y="y"
absolute >
<v-date-picker />
</v-menu>
</v-app>
</div>
show (e) {
console.log(123);
e.preventDefault();
this.menu = false;
this.x = e.clientX;
this.y = e.clientY;
this.$nextTick(() => {
this.menu = true
})
},

Vuetify button icon with inline text

what I would like to achieve is a v-chip that act as a button and not like something to select...
So far I tried:
<v-btn icon>
<v-avatar>
<img :src="user.avatar" />
</v-avatar>
My Text
</v-btn>
But it is not looking as expected...
I also tried to wrap everything inside a chip but even here I can not manage to let it work properly...
Can someone explain how can I do it? Basically in my top toolbar I need to display the user icon with its name on the right, it should be inline with other v-btn icon elements and also, by clicking on the chip/btn it should open a dropdown...
Of course I don't need all this from you, just to understand how to create a icon button with some inline text on the right...
Thanks
I used v-chip to create a icon with text inline and used css to change the pointer of v-chip, wrapped with v-hover to maintain the elevation on hover and lastly wrapped v-hover by v-menu to show dropdown menu list when v-chip is clicked.
<div id="app">
<v-menu offset-y>
<template v-slot:activator="{ on }">
<v-hover>
<v-chip slot-scope="{ hover }"
:class="`elevation-${hover ? 5 : 2}`" v-ripple color="indigo" text-color="white" v-on="on">
<v-avatar>
<v-icon>account_circle</v-icon>
</v-avatar>
Sagar
</v-chip>
</v-hover>
</template>
<v-list>
<v-list-tile
v-for="(item, i) in items"
:key="i"
#click=""
>
<v-list-tile-title>{{ item.title }}</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
</div>
<script>
new Vue({
el: '#app',
data() {
return {
items: [
{ title: 'Click Me' },
{ title: 'Click Me' },
{ title: 'Click Me' },
{ title: 'Click Me 2' }
],
}
}
})
</script>
<style>
.v-chip .v-chip__content{
cursor: pointer;
}
</style>

Handsontable not immediately shown when inside Vuetify Stepper

When placing the Handsontable HotTable component inside of a Vuetify Stepper the Handsontable is only visible after you click somewhere on the page. But if I place the HotTable component outside of the Stepper it would be shown immediately. It should be visible inside step 1 immediately.
To demonstrate this unexpected behavior I forked the Vuetify Stepper example on CodePen and added "handsontable" and "#handsontable/vue".
Vuetify Stepper with Handsontable on CodePen
<div id="app">
<v-app id="inspire">
<v-stepper v-model="e1">
<v-stepper-header>
<v-stepper-step :complete="e1 > 1" step="1">Name of step 1</v-stepper-step>
<v-divider></v-divider>
<v-stepper-step :complete="e1 > 2" step="2">Name of step 2</v-stepper-step>
<v-divider></v-divider>
<v-stepper-step step="3">Name of step 3</v-stepper-step>
</v-stepper-header>
<v-stepper-items>
<v-stepper-content step="1">
<v-card
class="mb-5"
color="grey lighten-1"
height="200px"
>
<div id="hot-preview">
<hot-table :settings="hotSettings"></hot-table>
</div>
</v-card>
<v-btn
color="primary"
#click="e1 = 2"
>
Continue
</v-btn>
<v-btn flat>Cancel</v-btn>
</v-stepper-content>
<v-stepper-content step="2">
<v-card
class="mb-5"
color="grey lighten-1"
height="200px"
></v-card>
<v-btn
color="primary"
#click="e1 = 3"
>
Continue
</v-btn>
<v-btn flat>Cancel</v-btn>
</v-stepper-content>
<v-stepper-content step="3">
<v-card
class="mb-5"
color="grey lighten-1"
height="200px"
></v-card>
<v-btn
color="primary"
#click="e1 = 1"
>
Continue
</v-btn>
<v-btn flat>Cancel</v-btn>
</v-stepper-content>
</v-stepper-items>
</v-stepper>
</v-app>
</div>
new Vue({
el: '#app',
data () {
return {
e1: 0,
hotSettings: {
data: Handsontable.helper.createEmptySpreadsheetData(1, 8),
colHeaders: true,
rowHeaders: true
}
}
},
components: {
HotTable
}
});
I think the problem is because you initialize it before component is mounted.
Try to initialize it in mounted hook:
hotSettings: {
data: null,
//...
mounted() {
this.hotSettings.data = Handsontable.helper.createEmptySpreadsheetData(1, 8)
}

navigation drawer in dialog, multiple v-content?

I'm just checking out vuetify and I would like to add a dialog that contains a v-navigation-drawer.
How do I need to structure the layout inside the dialog to achieve the same effect in the dialog like with a v-navigation-drawer ( menu on the left, content on the right ).
thats my markup right now:
v-app
v-dialog
v-toolbar
v-navigation-drawer
v-list
.. menuitems
v-content
(content here is under the left menu not on the right side as on my screenshot)
v-content
v-container
https://imgur.com/a/dRTpC
This may not be the cleanest solution, but it could be something like this:
new Vue({
el: '#app',
data () {
return {
dialog: null,
notifications: false,
sound: true,
widgets: false
}
}
})
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vuetify/dist/vuetify.min.js"></script>
<link href="https://unpkg.com/vuetify/dist/vuetify.min.css" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons" />
<div id="app">
<v-app id="inspire">
<v-btn primary dark v-on:click.stop="dialog = true">Open Dialog</v-btn>
<v-dialog v-model="dialog" transition="dialog-bottom-transition" width="80%" fullscreen hide-overlay >
<v-card>
<v-toolbar dark class="primary">
<v-btn icon #click.native="dialog = false" dark>
<v-icon>close</v-icon>
</v-btn>
<v-toolbar-title>Settings</v-toolbar-title>
<v-spacer></v-spacer>
<v-toolbar-items>
<v-btn dark flat #click.native="dialog = false">Save</v-btn>
</v-toolbar-items>
</v-toolbar>
<v-navigation-drawer
permanent
absolute
left
width="250"
class='mt-5'
height=""
>
<v-list light one-line class="grey pa-1">
<v-list-tile>
<v-list-tile-content>
<v-list-tile-title class="white--text subheading">
HEADER
</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
<v-list class="pt-0" dense>
<v-divider></v-divider>
<v-list-tile >
Lorem ipsum lorem ipsum
</v-list-tile>
</v-list>
</v-navigation-drawer>
<v-flex class="text-xs-center">
<h3 class="headline mb-0">Kangaroo Valley Safari</h3>
<div>Located two hours south of Sydney in the <br>Southern Highlands of New South Wales, ...</div>
</v-flex>
</v-card>
</v-dialog>
</v-app>
</div>

Resources