ipyvuetify#
ipyvuetify provides Jupyter widgets based on vuetify UI components and implementing Google’s Material Design with the Vue.js-Framework framework.
Installation#
$ pipenv install ipyvuetify
Installing ipyvuetify…
…
$ pipenv run jupyter nbextension enable --py --sys-prefix ipyvuetify
Enabling notebook extension jupyter-vuetify/extension...
      - Validating: OK
Examples#
Imports#
[1]:
import ipywidgets
import ipyvuetify as v
from threading import Timer
from traitlets import (Any, Unicode, List)
Menu#
[2]:
def on_menu_click(widget, event, data):
    if len(layout.children) == 1:
        layout.children = layout.children + [info]
    info.children=[f'Item {items.index(widget)+1} clicked']
items = [v.ListItem(children=[
    v.ListItemTitle(children=[
        f'Item {i}'])])
         for i in range(1, 5)]
for item in items:
    item.on_event('click', on_menu_click)
menu = v.Menu(offset_y=True,
    v_slots=[{
        'name': 'activator',
        'variable': 'menuData',
        'children': v.Btn(v_on='menuData.on', class_='ma-2', color='primary', children=[
            'menu',
            v.Icon(right=True, children=[
                'arrow_drop_down'
            ])
        ]),
    }]
    ,
    children=[
        v.List(children=items)
    ]
)
info = v.Chip(class_='ma-2')
layout = v.Layout(children=[
    menu
])
layout
Buttons#
[3]:
v.Layout(children=[
    v.Btn(color='primary', children=['primary']),
    v.Btn(color='error', children=['error']),
    v.Btn(disabled=True, children=['disabled']),
    v.Btn(children=['reset']),
])
[4]:
v.Layout(children=[
    v.Btn(color='primary', flat=True, children=['flat']),
    v.Btn(color='primary', round=True, children=['round']),
    v.Btn(color='primary', flat=True, icon=True, children=[v.Icon(children=['thumb_up'])]),
    v.Btn(color='primary', outline=True, children=['outline']),
    v.Btn(color='primary', fab=True, large=True, children=[v.Icon(children=['edit'])]),
])
[5]:
def toggleLoading():
    button2.loading = not button2.loading
    button2.disabled = button2.loading
def on_loader_click(*args):
    toggleLoading()
    Timer(2.0, toggleLoading).start()
button2 = v.Btn(loading=False, children=['loader'])
button2.on_event('click', on_loader_click)
v.Layout(children=[button2])
[6]:
toggle_single = v.BtnToggle(v_model=2, class_='mr-3', children=[
    v.Btn(flat=True, children=[v.Icon(children=['format_align_left'])]),
    v.Btn(flat=True, children=[v.Icon(children=['format_align_center'])]),
    v.Btn(flat=True, children=[v.Icon(children=['format_align_right'])]),
    v.Btn(flat=True, children=[v.Icon(children=['format_align_justify'])]),
])
toggle_multi = v.BtnToggle(v_model=[0,2], multiple=True, children=[
    v.Btn(flat=True, children=[v.Icon(children=['format_bold'])]),
    v.Btn(flat=True, children=[v.Icon(children=['format_italic'])]),
    v.Btn(flat=True, children=[v.Icon(children=['format_underline'])]),
    v.Btn(flat=True, children=[v.Icon(children=['format_color_fill'])]),
])
v.Layout(children=[
    toggle_single,
    toggle_multi,
])
[7]:
v.Layout(children=[
    v.Btn(color='primary', children=[
        v.Icon(left=True, children=['fingerprint']),
        'Icon left'
    ]),
    v.Btn(color='primary', children=[
        'Icon right',
        v.Icon(right=True, children=['fingerprint']),
    ]),
    v.Tooltip(bottom=True, children=[
        v.Btn(slot='activator', color='primary', children=[
           'tooltip'
        ]),
        'Insert tooltip text here'
    ])
])
[8]:
lorum_ipsum = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'
v.Layout(children=[
    v.Dialog(width='500', v_slots=[{
        'name': 'activator',
        'variable': 'x',
        'children': v.Btn(v_on='x.on', color='success', dark=True, children=[
            'Open dialog'
        ]),
    }],
    children=[
        v.Card(children=[
            v.CardTitle(class_='headline gray lighten-2', primary_title=True, children=[
                "Lorem ipsum"]),
            v.CardText(children=[
                lorum_ipsum])
        ])
    ])
])
Slider#
[9]:
slider = v.Slider(v_model=25)
slider2 = v.Slider(thumb_label=True, v_model=25)
slider3 = v.Slider(thumb_label='always', v_model=25)
ipywidgets.jslink((slider, 'v_model'), (slider2, 'v_model'))
v.Container(children=[
    slider,
    slider2,
])
Tabs#
[10]:
tab_list = [v.Tab(children=['Tab ' + str(i)]) for i in range(1,4)]
content_list = [v.TabItem(children=[lorum_ipsum]) for i in range(1,4)]
tabs = v.Tabs(
    v_model=1,
    children=tab_list + content_list)
tabs
Accordion#
[11]:
vepc1 = v.ExpansionPanel(children=[
    v.ExpansionPanelHeader(children=['item1']),
    v.ExpansionPanelContent(children=['First Text'])])
vepc2 = v.ExpansionPanel(children=[
    v.ExpansionPanelHeader(children=['item2']),
    v.ExpansionPanelContent(children=['Second Text'])])
vep = v.ExpansionPanels(children=[vepc1, vepc2])
vl = v.Layout(class_='pa-4', children=[vep])
vl
You can search for all available components and attributes in the Vuetify documentation. Ipyvuetify is based on the syntax of Vue.js- and Vuetify, but there are also some differences:
Description  | 
Vuetify  | 
ipyvuetify  | 
|---|---|---|
Component names are written in CamelCase and the   | 
  | 
  | 
Child components and text are defined in the child traitlet  | 
  | 
  | 
Flag attributes require a Boolean value  | 
  | 
  | 
Attributes are snake_case  | 
  | 
  | 
The   | 
  | 
  | 
The scope of   | 
  | 
  | 
Event listeners are defined with   | 
  | 
  | 
Regular HTML tags can be created with the   | 
  | 
  | 
An underscore must be added to the   | 
  | 
  | 
VuetifyTemplate#
You can get a closer match with the Vue/Vuetify API with VuetifyTemplate. For this you create a subclass of VuetifyTemplate and define your own traitlets. The traitlets can be accessed via the template as if they were in a Vue model. Methods can be defined with the prefix vue_, e.g. def vue_button_click(self, data), which can then be called with @click="button_click(e)". In the following I show you a table with search, sorting and number of lines:
[12]:
import pandas as pd
import traitlets
import ipyvuetify as v
import json
class PandasDataFrame(v.VuetifyTemplate):
    """
    Vuetify DataTable rendering of a pandas DataFrame
    Args:
        data (DataFrame) - the data to render
        title (str) - optional title
    """
    headers = traitlets.List([]).tag(sync=True, allow_null=True)
    items = traitlets.List([]).tag(sync=True, allow_null=True)
    search = traitlets.Unicode('').tag(sync=True)
    title = traitlets.Unicode('DataFrame').tag(sync=True)
    index_col = traitlets.Unicode('').tag(sync=True)
    template = traitlets.Unicode('''
        <template>
          <v-card>
            <v-card-title>
              <span class="title font-weight-bold">{{ title }}</span>
              <v-spacer></v-spacer>
                <v-text-field
                    v-model="search"
                    append-icon="search"
                    label="Search ..."
                    single-line
                    hide-details
                ></v-text-field>
            </v-card-title>
            <v-data-table
                :headers="headers"
                :items="items"
                :search="search"
                :item-key="index_col"
                :rows-per-page-items="[25, 50, 250, 500]"
            >
                <template v-slot:no-data>
                  <v-alert :value="true" color="error" icon="warning">
                    Sorry, nothing to display here :(
                  </v-alert>
                </template>
                <template v-slot:no-results>
                    <v-alert :value="true" color="error" icon="warning">
                      Your search for "{{ search }}" found no results.
                    </v-alert>
                </template>
                <template v-slot:items="rows">
                  <td v-for="(element, label, index) in rows.item"
                      @click=cell_click(element)
                      >
                    {{ element }}
                  </td>
                </template>
            </v-data-table>
          </v-card>
        </template>
        ''').tag(sync=True)
    def __init__(self, *args,
                 data=pd.DataFrame(),
                 title=None,
                 **kwargs):
        super().__init__(*args, **kwargs)
        data = data.reset_index()
        self.index_col = data.columns[0]
        headers = [{
              "text": col,
              "value": col
            } for col in data.columns]
        headers[0].update({'align': 'left', 'sortable': True})
        self.headers = headers
        self.items = json.loads(
            data.to_json(orient='records'))
        if title is not None:
            self.title = title
iris = pd.read_csv('https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv')
test = PandasDataFrame(data = iris, title='Iris')
test
[13]:
v.Banner(single_line=True,
    v_slots=[{
        'name': 'icon',
        'children': v.Icon(children=['thumb_up'])
    }, {
        'name': 'actions',
        'children': v.Btn(text=True, color='deep-purple accent-4', children=['Action'])
    }],
    children=['One line message text string with two actions on tablet / Desktop'])