Vuetensils

🍴 A tasty toolset for Vue.js 🛠

Vuetensils is a collection of Vue components desined to be light weight, accessible, and extensible. It is not a full blown UI library. Instead, it is designed to jump start a project with some of the most common UI solutions, but does not bring with it any opinionated styles. Bring your own styles, and let Vuetensils handle things like a modal popup that is accessible, traps user tab focus, and closes when the escape key is pressed. View on GitHub or NPM.

Comparison of bundle sizes from other popular libraries:

  • None: 94.3kb
  • Vuetify: 791kb
  • BootstrapVue: 460kb
  • Vuetensils: TODO

Getting Started

Install:

npm install vuetensils

Import into your Vue project:

// main.js
import Vue from 'vue'
import vuetensils from 'vuetensils'
import 'vuetensils/dist/vuetensils.min.css'

Vue.use(vuetensils)

Alternatively, import just the components you need:

// main.js
import Vue from 'vue'
import { VtsModal } from 'vuetensils'

Vue.use(VtsModal)

Use the components:

// Example.vue
<template>
  <div>
    <vts-modal v-model="show">
      My modal content
    </vts-modal>
  </div>
</template>
<script>
export default {
  data: () => ({
    show: true
  })
}
</script>

Components

  • <vts-drawer> - A sidebar that can be toggled on or off.
  • <vts-dropdown> - Show/hide inline content.
  • <vts-fetch> - Makes JSON API requests and provides responses, loading states, and errors.
  • <vts-intersection> - Adds IntersectionObserver to content and provides event callbacks.
  • <vts-loading> - SVG loading icons.
  • <vts-modal> - A modal dialogue.

<vts-drawer>

// Example.vue
<template>
  <div>
    <vts-drawer
      v-model="show"
      transition="slide-right"
      bg-transition="fade"
    >
      My drawer content
    </vts-drawer>

    <button @click="show = !show">Toggle Drawer</button>
  </div>
</template>
<script>
export default {
  data: () => ({
    show: true
  })
}
</script>

<vts-dropdown>

// Example.vue
<template>
  <div>
    <vts-dropdown
      text="Show me what you got!"
      transition="slide-up"
    >
      <p>Here is the dropdown content.
        <br>Why not add a nav?
      </p>
      <nav>
        <ul>
          <li><a href="#">link</a></li>
          <li><a href="#">link</a></li>
          <li><a href="#">link</a></li>
        </ul>
      </nav>
    </vts-dropdown>
  </div>
</template>

<vts-fetch>

// Example.vue
<template>
  <div>
    <vts-fetch :url="`https://jsonplaceholder.typicode.com/users/${userId}`">
      <div slot-scope="{ loading, error, response, send }">
        <p v-if="loading">Loading...</p>

        <p v-else-if="error">There was an error</p>

        <template v-else>
          <p>JSON response:</p>
          <code>{ { response } }</code>
          <br>
        </template>

        <button @click="send(`https://jsonplaceholder.typicode.com/users/${userId++}`)">Get next user</button>
        <button @click="send(`https://httpstat.us/500`)">Get a 500 error</button>
      </div>
    </vts-fetch>
  </div>
</template>
<script>
export default {
  data: () => ({
    userId: 1
  })
}
</script>

JSON response:



<vts-intersection>

// Example.vue
<template>
  <div>
    <vts-intersection @enter="consoleLog('@enter fired')" @leave="consoleLog('@leave fired')" @change="consoleLog('@change fired')">
      Check your developer console to see updates.
    </vts-intersection>
  </div>
</template>
<script>
export default {
  methods: {
    consoleLog: console.log
  }
}
</script>
Check your developer console to see updates.

<vts-loading>

// Example.vue
<template>
  <div>
    <div style="max-width: 200px;">
      <label>
        Loading Type:
        <select v-model="loadingType">
          <option v-for="type in loadingTypes" :key="type" :value="type">{ { type } }</option>
        </select>
      </label>
      <br>
      <label>
        Fill Color:
        <select v-model="fill">
          <option v-for="color in colors" :key="color" :value="color">{ { color } }</option>
        </select>
      </label>
      <br>
      <label>
        Stroke Color:
        <select v-model="stroke">
          <option v-for="color in colors" :key="color" :value="color">{ { color } }</option>
        </select>
      </label>
      <vts-loading :name="loadingType" :fill="fill" :stroke="stroke" />
    </div>
  </div>
</template>
<script>
export default {
  data: () => ({
    loadingType: '',
    loadingTypes: [
      'bars',
      'cube',
      'infinity',
      'gear',
      'ring',
      'ripple',
      'spin'
    ],
    stroke: 'currentColor',
    fill: 'none',
    colors: [
      'none',
      'currentColor',
      'red',
      '#bada55',
      'rgba(0, 0, 0, 0.5)'
    ]
  })
}
</script>



<vts-modal>

// Example.vue
<template>
  <div>
    <vts-modal
      v-model="modal"
      transition="slide-up"
      bg-transition="fade"
    >
      This is the modal content.
      <br>
      It traps the user focus.
      <br>
      <button @click="modal = false">Close</button>
    </vts-modal>
    <button @click="modal = !modal">toggle</button>
  </div>
</template>
<script>
export default {
  data: () => ({
    modal: false
  })
}
</script>

NOTE: this library does not include CSS transitions. The transitions on this page were added with the following styles.

<style>
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s;
}

.fade-enter,
.fade-leave-to {
  opacity: 0;
}

.slide-right-enter-active,
.slide-right-leave-active {
  transition: opacity 0.5s, transform 0.5s;
}

.slide-right-enter,
.slide-right-leave-to {
  opacity: 0;
  transform: translateX(-100%);
}

.slide-up-enter-active,
.slide-up-leave-active {
  transform: translateY(0);
  transition: opacity 0.5s, transform 0.5s;
}

.slide-up-enter,
.slide-up-leave-to {
  opacity: 0;
  transform: translateY(10px);
}
</style>