Categories
Buefy

Buefy — Icons and Images

Buefy is a UI framework that’s based on Bulma.

In this article, we’ll look at how to use Buefy in our Vue app.

Icons

We can add icons with the b-icon component.

To do that, we add our icon CSS:

<link
      rel="stylesheet"
      href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
      integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN"
      crossorigin="anonymous"
    />

into our head tag of the public/index.html file.

Then in our component, we write:

<template>
  <div id="app">
    <b-icon icon="address-book" pack="fa" size="is-small"></b-icon>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

pack sets the icon pack to use.

'fa' sets it to Font Awesome.

icon is the icon name that we use.

size sets the size.

We can add the type ptop to set the style:

<template>
  <div id="app">
    <b-icon type="is-success" icon="address-book" pack="fa" size="is-small"></b-icon>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

We can also write it as an object:

<template>
  <div id="app">
    <b-icon :type="{ 'is-success': true }" icon="address-book" pack="fa" size="is-small"></b-icon>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

This lets us set the style conditionally.

Image

Buefy comes with the b-image component to let us add images.

For example, we can write:

<template>
  <div id="app">
    <b-image src="https://picsum.photos/600/400" alt="image" ratio="6by4" rounded></b-image>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

alt sets the text description for the image.

src has the URL of the image.

rounded makes the image rounded.

ratio is the aspect ratio.

We can also add WebP images with b-image :

<template>
  <div id="app">
    <b-image
      src="https://picsum.photos/id/237/800/450.webp"
      webp-fallback="https://picsum.photos/id/1025/800/450.jpg"
      alt="image"
      ratio="6by4"
      rounded
    ></b-image>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

webp-fallback has the URL for the fallback image in case WebP images aren’t supported in your browser.

We can add srcset props to show different images when the screen is different sizes:

<template>
  <div id="app">
    <b-image
      src="https://picsum.photos/id/1074/1600/800"
      :srcset-sizes="[400, 800, 1600]"
      :srcset-formatter="this.formatSrcset"
      alt="image"
      ratio="6by4"
    ></b-image>
  </div>
</template>

<script>
export default {
  name: "App",
  methods: {
    formatSrcset(src, size) {
      return `https://picsum.photos/id/1000/${size}/${size / 2}`;
    }
  }
};
</script>

Also, we can listen to the load event and run an event handler when it loads:

<template>
  <div id="app">
    <b-image src="https://picsum.photos/id/1074/1600/800" alt="image" ratio="6by4" @load="onLoad"></b-image>
  </div>
</template>

<script>
export default {
  name: "App",
  methods: {
    onLoad(event, src) {
      console.log(src);
    }
  }
};
</script>

onLoad is run when the load event is emitted.

We can hamdle errors by listening to the error event and add a fallback image:

<template>
  <div id="app">
    <b-image
      src="https://picsum.photos/id/error/600/400"
      src-fallback="https://picsum.photos/id/237/600/400"
      ratio="6by4"
      @error="onError"
    ></b-image>
  </div>
</template>

<script>
export default {
  name: "App",
  methods: {
    onError(event, src) {
      console.log(`${src} fails to load`);
    }
  }
};
</script>

The onError method is run when the image set in the src attribute fails to load.

Conclusion

We can display icons and images easily with Buefy.

Categories
Buefy

Buefy — Time Picker and File Input

Buefy is a UI framework that’s based on Bulma.

In this article, we’ll look at how to use Buefy in our Vue app.

Time Picker

Buefy has a time picker component.

We can add the b-timepicker component to use it.

For example, we can write;

<template>
  <section>
    <b-field>
      <b-timepicker
        rounded
        placeholder="Click to select..."
        enable-seconds
        hour-format="12"
        locale="en"
      ></b-timepicker>
    </b-field>
  </section>
</template>

<script>
export default {
  data() {
    return {};
  }
};
</script>

The component takes a few props.

rounded makes the input box have round corners.

placeholder has the placeholder.

enable-seconds has a dropdown to pick the seconds.

hour-format sets the hour format.

locale sets the locale.

We can make the time picker editable with the editable prop:

<template>
  <section>
    <b-field>
      <b-timepicker
        rounded
        placeholder="Click to select..."
        enable-seconds
        hour-format="12"
        locale="en"
        editable
      ></b-timepicker>
    </b-field>
  </section>
</template>

<script>
export default {
  data() {
    return {};
  }
};
</script>

The range of allowed values can be set with the min-time and max-time props:

<template>
  <section>
    <b-field>
      <b-timepicker placeholder="Click to select..." :min-time="minTime" :max-time="maxTime"></b-timepicker>
    </b-field>
  </section>
</template>

<script>
export default {
  data() {
    const min = new Date();
    min.setHours(0);
    min.setMinutes(0);
    const max = new Date();
    max.setHours(2);
    max.setMinutes(0);
    return {
      minTime: min,
      maxTime: max
    };
  }
};
</script>

The footer can be changed by populating the default slot:

<template>
  <section>
    <b-field>
      <b-timepicker v-model="time" placeholder="Click to select...">
        <button class="button is-primary" @click="time = new Date()">
          <span>Now</span>
        </button>

        <button class="button is-danger" @click="time = null">
          <span>Clear</span>
        </button>
      </b-timepicker>
    </b-field>
  </section>
</template>

<script>
export default {
  data() {
    return {
      time: new Date()
    };
  }
};
</script>

We added 2 buttons into the default slot and they’ll be displayed below the time picker.

Also, we can make it inline with the inline prop:

<template>
  <section>
    <b-field>
      <b-timepicker v-model="time" inline></b-timepicker>
    </b-field>
  </section>
</template>

<script>
export default {
  data() {
    return {
      time: new Date()
    };
  }
};
</script>

The increments of the dropdown can be set with the incrementMinutes and incrementHours props:

<template>
  <section>
    <b-field>
      <b-timepicker v-model="time" :incrementMinutes="5" :incrementHours="2"></b-timepicker>
    </b-field>
  </section>
</template>

<script>
export default {
  data() {
    return {
      time: new Date()
    };
  }
};
</script>

File Upload Input

The b-upload component is the file upload input.

For example, we can write:

<template>
  <b-field class="file is-primary" :class="{'has-name': !!file}">
    <b-upload v-model="file">
      <span class="file-cta">
        <span>Click to upload</span>
      </span>
      <span class="file-name" v-if="file">{{ file.name }}</span>
    </b-upload>
  </b-field>
</template>

<script>
export default {
  data() {
    return {
      file: null
    };
  }
};
</script>

to add it.

The file-cta class makes the input display as a button.

v-model binds the selected file to the file state.

We can make the file input appears as a drop zone with the drag-drop prop:

<template>
  <b-field class="file is-primary" :class="{'has-name': !!file}">
    <b-upload v-model="file" drag-drop>
      <section class="section">
        <div class="content has-text-centered">
          <p>Drop your files here or click to upload</p>
        </div>
      </section>
    </b-upload>
  </b-field>
</template>

<script>
export default {
  data() {
    return {
      file: null
    };
  }
};
</script>

The expanded prop makes the button longer:

<template>
  <b-field class="file">
    <b-upload v-model="file" expanded>
      <a class="button is-primary is-fullwidth">
        <span>{{ file && file.name || "Click to upload"}}</span>
      </a>
    </b-upload>
  </b-field>
</template>

<script>
export default {
  data() {
    return {
      file: null
    };
  }
};
</script>

Conclusion

We can add a time picker and file upload input with Buefy.

Categories
Buefy

Buefy — Customize Tag Input

Buefy is a UI framework that’s based on Bulma.

In this article, we’ll look at how to use Buefy in our Vue app.

Customize Tag Input

We can customize our tag input in various ways.

We can limit the number of tags we can add and the number of characters each can have.

The maxlength prop limits the number of characters in a tag.

The maxtags prop limits the number of tags we can enter.

For example, we can write:

<template>
  <section>
    <div class="field">
      <b-taginput v-model="tags" maxlength="10" placeholder="Add a tag"></b-taginput>
      {{tags}}
    </div>
  </section>
</template>

<script>
export default {
  data() {
    return { tags: [] };
  }
};
</script>

to limit the number of characters of each tag to 10 max.

And we can write:

<template>
  <section>
    <div class="field">
      <b-taginput v-model="tags" maxtags="5" placeholder="Add a tag"></b-taginput>
      {{tags}}
    </div>
  </section>
</template>

<script>
export default {
  data() {
    return { tags: [] };
  }
};
</script>

to limit the max number of tags to 5.

We can change the outline color with the type prop on the b-field:

<template>
  <section>
    <b-field type="is-success">
      <b-taginput v-model="tags" placeholder="Add a tag"></b-taginput>
      {{tags}}
    </b-field>
  </section>
</template>

<script>
export default {
  data() {
    return { tags: [] };
  }
};
</script>

Now the outline is green.

The type prop can be added to the b-taginput to change the background color of the tags:

<template>
  <section>
    <b-field>
      <b-taginput type="is-dark" v-model="tags" placeholder="Add a tag"></b-taginput>
      {{tags}}
    </b-field>
  </section>
</template>

<script>
export default {
  data() {
    return { tags: [] };
  }
};
</script>

The size prop changes the size of the tag input:

<template>
  <section>
    <b-field>
      <b-taginput size="is-large" v-model="tags" placeholder="Add a tag"></b-taginput>
      {{tags}}
    </b-field>
  </section>
</template>

<script>
export default {
  data() {
    return { tags: [] };
  }
};
</script>

The rounded prop makes the tag input round:

<template>
  <section>
    <b-field>
      <b-taginput rounded v-model="tags" placeholder="Add a tag"></b-taginput>
      {{tags}}
    </b-field>
  </section>
</template>

<script>
export default {
  data() {
    return { tags: [] };
  }
};
</script>

The attched prop makes the tags rectangular:

<template>
  <section>
    <b-field>
      <b-taginput attached v-model="tags" placeholder="Add a tag"></b-taginput>
      {{tags}}
    </b-field>
  </section>
</template>

<script>
export default {
  data() {
    return { tags: [] };
  }
};
</script>

We can add validation with the before-adding prop:

<template>
  <section>
    <b-field>
      <b-taginput :before-adding="beforeAdding" v-model="tags" placeholder="Add a tag"></b-taginput>
      {{tags}}
    </b-field>
  </section>
</template>

<script>
export default {
  data() {
    return { tags: [] };
  },
  methods: {
    beforeAdding(tag) {
      return tag.length === 3;
    }
  }
};
</script>

The beforeAdding method will be run before the tag is added.

The tag will only be added if it returns true .

tag has the entered value.

Conclusion

We can customize tag inputs the way we like with Buefy’s tag input.

Categories
Buefy

Buefy — Switch and Tags Input

Buefy is a UI framework that’s based on Bulma.

In this article, we’ll look at how to use Buefy in our Vue app.

Switch

Buefy provides a switch component for us to use.

For example, we can write:

<template>
  <section>
    <div class="field">
      <b-switch>Default</b-switch>
    </div>
  </section>
</template>

<script>
export default {
  data() {
    return {};
  }
};
</script>

We can bind the value withv-model :

<template>
  <section>
    <div class="field">
      <b-switch v-model="isSwitched">{{ isSwitched }}</b-switch>
    </div>
  </section>
</template>

<script>
export default {
  data() {
    return { isSwitched: false };
  }
};
</script>

the type prop lets us change the style:

<template>
  <section>
    <div class="field">
      <b-switch v-model="isSwitched" type="is-success">{{ isSwitched }}</b-switch>
    </div>
  </section>
</template>

<script>
export default {
  data() {
    return { isSwitched: false };
  }
};
</script>

The size prop changes the size:

<template>
  <section>
    <div class="field">
      <b-switch v-model="isSwitched" size="is-large">{{ isSwitched }}</b-switch>
    </div>
  </section>
</template>

<script>
export default {
  data() {
    return { isSwitched: false };
  }
};
</script>

Also, we can set the rounded prop to false to make it square:

<template>
  <section>
    <div class="field">
      <b-switch v-model="isSwitched" :rounded="false">{{ isSwitched }}</b-switch>
    </div>
  </section>
</template>

<script>
export default {
  data() {
    return { isSwitched: false };
  }
};
</script>

The outlined prop makes it outlined:

<template>
  <section>
    <div class="field">
      <b-switch v-model="isSwitched" outlined>{{ isSwitched }}</b-switch>
    </div>
  </section>
</template>

<script>
export default {
  data() {
    return { isSwitched: false };
  }
};
</script>

Tag Input

We can add tag input with the b-taginput component.

For example, we can write:

<template>
  <section>
    <div class="field">
      <b-taginput v-model="tags" ellipsis placeholder="Add a tag"></b-taginput>
      {{tags}}
    </div>
  </section>
</template>

<script>
export default {
  data() {
    return { tags: [] };
  }
};
</script>

We bind the entered tags to an array of strings with v-model .

ellipsis truncates long tag text and adds an ellipsis after it.

Autocomplete

We can add the autocomplete prop to add the autocomplete values:

<template>
  <section>
    <div class="field">
      <b-taginput v-model="tags" :data="filteredTags" autocomplete placeholder="Add a tag"></b-taginput>
      {{tags}}
    </div>
  </section>
</template>

<script>
export default {
  data() {
    return { tags: [], filteredTags: ["foo", "bar", "baz"] };
  }
};
</script>

data has an array of strings with the choices we can choose from.

autocomplete enables the autocomplete dropdown.

Templated Autocomplete

We can populate the default slot to change the template for the autocomplete control:

<template>
  <section>
    <div class="field">
      <b-taginput v-model="tags" :data="filteredTags" autocomplete placeholder="Add a tag">
        <template slot-scope="props">
          <strong>{{props.option}}</strong>
        </template>
        <template slot="empty">There are no items</template>
      </b-taginput>
      {{tags}}
    </div>
  </section>
</template>

<script>
export default {
  data() {
    return { tags: [], filteredTags: ["foo", "bar", "baz"] };
  }
};
</script>

props.option has the item that we can select.

Customize Selected Item

We can customize the selected item by populating the selected slot:

<template>
  <section>
    <div class="field">
      <b-taginput
        ref="tagInput"
        v-model="tags"
        :data="filteredTags"
        autocomplete
        placeholder="Add a tag"
      >
        <template slot="selected" slot-scope="props">
          <b-tag
            v-for="(tag, index) in props.tags"
            :key="index"
            type="is-success"
            rounded
            :tabstop="false"
            ellipsis
            closable
            @close="$refs.tagInput.removeTag(index, $event)"
          >{{tag}}</b-tag>
        </template>
      </b-taginput>
      {{tags}}
    </div>
  </section>
</template>

<script>
export default {
  data() {
    return { tags: [], filteredTags: ["foo", "bar", "baz"] };
  }
};
</script>

We set the type to change the style.

is-success makes the tags green.

closable shows the close button so we can remove it.

The b-tag emits the close event so we can remove the entry when we click the close button.

Conclusion

We can add switches and tag inputs with Buefy.

Categories
Buefy

Buefy — Numeric Slider

Buefy is a UI framework that’s based on Bulma.

In this article, we’ll look at how to use Buefy in our Vue app.

Numeric Slider

We can add a slider to set a numeric value with the b-slider component.

For example, we can write:

<template>
  <section>
    <b-field label="number">
      <b-slider v-model="value"></b-slider>
    </b-field>
  </section>
</template>

<script>
export default {
  data() {
    return {
      value: 5
    };
  }
};
</script>

We add v-model to bind the value to a state.

We can disable it with the disabled prop.

The size can be changed with the size prop:

<template>
  <section>
    <b-field label="number">
      <b-slider size="is-large" :value="20"></b-slider>
    </b-field>
  </section>
</template>

<script>
export default {
  data() {
    return {};
  }
};
</script>

The style can be changed with the type prop:

<template>
  <section>
    <b-field label="number">
      <b-slider type="is-success" :value="20"></b-slider>
    </b-field>
  </section>
</template>

<script>
export default {
  data() {
    return {};
  }
};
</script>

We can customize the label with the custom-formatter prop:

<template>
  <section>
    <b-field label="number">
      <b-slider type="is-success" :custom-formatter="val => `${val}%`"></b-slider>
    </b-field>
  </section>
</template>

<script>
export default {
  data() {
    return {};
  }
};
</script>

now the tooltip shows the % symbol after the number since we set the custom-formatter prop to our own function.

Tick and Label

We can add ticks by populating the default slot with the b-slider-tick component:

<template>
  <section>
    <b-field label="Custom tick and label">
      <b-slider size="is-medium" :min="0" :max="10">
        <template v-for="val in [2,4,6,8]">
          <b-slider-tick :value="val" :key="val">{{ val }}</b-slider-tick>
        </template>
      </b-slider>
    </b-field>
  </section>
</template>

<script>
export default {
  data() {
    return {};
  }
};
</script>

Range Slider

We can add a range slider with the min and max props to restrict the range that we can select.

Then the value we bound to v-model would be an array with the min and max values:

<template>
  <section>
    <b-field>
      <b-slider v-model="numbers" :min="0" :max="15" :step="0.5"></b-slider>
    </b-field>
  </section>
</template>

<script>
export default {
  data() {
    return {
      numbers: [1, 5]
    };
  }
};
</script>

Lazy Update

We can add the lazy prop to update the v-model value only when dragging is done:

<template>
  <section>
    <b-field>
      <b-slider v-model="value" lazy></b-slider>
    </b-field>
    {{value}}
  </section>
</template>

<script>
export default {
  data() {
    return {
      value: 20
    };
  }
};
</script>

Conclusion

Buefy’s b-slider component is a useful slider component for Vue.