Categories
Buefy

Getting Started with Buefy for Vue.js

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

In this article, we’ll look at how to install Buefy and use it.

Installation

We can install Buefy with NPM or Yarn.

To install it, we run:

npm install buefy

Then we add it to our Vue project’s main.js file:

import Vue from "vue";
import App from "./App.vue";
import Buefy from "buefy";
import "buefy/dist/buefy.css";

Vue.use(Buefy);
Vue.config.productionTip = false;

new Vue({
  render: (h) => h(App)
}).$mount("#app");

We can also add the CSS and JS files in our HTML file directly with:

<link rel="stylesheet" href="https://unpkg.com/buefy/dist/buefy.min.css">
<script src="https://unpkg.com/buefy/dist/buefy.min.js"></script>

Constructor Options

Buefy takes a few options for to configure it.

For example, we can write:

import Vue from "vue";
import App from "./App.vue";
import Buefy from "buefy";
import "buefy/dist/buefy.css";

Vue.use(Buefy, {
  defaultIconPack: "fas",
  defaultContainerElement: "#content"
  // ...
});
Vue.config.productionTip = false;

new Vue({
  render: (h) => h(App)
}).$mount("#app");

defaultIconPack has the icons package name.

defaultIconcomponent has the container element to render the icon.

There are also many other properties listed at https://buefy.org/documentation/constructor-options.

Button

We can add a button with the b-button component.

For example, we can use it by writing:

<template>
  <section>
    <b-button @click="clickMe">Click Me</b-button>
  </section>
</template>

<script>
export default {
  methods: {
    clickMe() {
      this.$buefy.notification.open("Clicked!!");
    }
  }
};
</script>

We have the clickMe method to show a notification when the button is clicked.

Button Types and States

We can set the type prop to set the button color.

For example, we can write:

<template>
  <section>
    <b-button type="is-primary">Primary</b-button>
    <b-button type="is-primary is-light">Primary Light</b-button>
  </section>
</template>

<script>
export default {};
</script>

is-primary changed the color to purple.

And is-light makes it lighter.

Other type values include is-success , is-danger , is-info , and is-link .

We can also add other props to a button.

disabled disables the button.

loading displays a loading spinner in the button.

focused makes it focused.

rounded makes it more rounded.

selected makes the button selected.

active makes it display as an active button.

For example, we can write:

<template>
  <section>
    <b-button focused>Primary</b-button>
  </section>
</template>

<script>
export default {};
</script>

to make the button focused.

Button Sizes

We can change the button size with the size prop.

For example, we can write:

<template>
  <section>
    <div class="buttons">
      <b-button size="is-small">Small</b-button>
      <b-button>Default</b-button>
      <b-button size="is-medium">Medium</b-button>
      <b-button size="is-large">Large</b-button>
    </div>
  </section>
</template>

<script>
export default {};
</script>

to set the button to various sizes.

Button Icons

We can add button icons to our buttons.

For example, we can use Font Awesome 4.7.0 icons by adding the CSS file into the head tag of main.html :

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

Then we can add our icon by writing:

<template>
  <section>
    <div class="buttons">
      <b-button size="is-small" icon-left="address-book">Add</b-button>
      <b-button icon-left="address-book">Add</b-button>
      <b-button size="is-medium" icon-left="address-book">Add</b-button>
      <b-button size="is-large" icon-left="address-book">Add</b-button>
    </div>
  </section>
</template>

<script>
export default {};
</script>

in main.js , we write:

import Vue from "vue";
import App from "./App.vue";
import Buefy from "buefy";
import "buefy/dist/buefy.css";

Vue.use(Buefy, {
  defaultIconPack: "fa"
});
Vue.config.productionTip = false;

new Vue({
  render: (h) => h(App)
}).$mount("#app");

We add the icon-left prop with the icon name without the fa prefix.

The defaultIconPack is set to 'fa' to set the prefix.

Conclusion

Buefy is a useful UI library for Vue. We can add buttons easily with it.

Categories
Buefy

Buefy — Collapse Component

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.

Collapse

The collapse component is a component that lets us toggle items on and off.

To add it, we add the b-collapse component by writing:

<template>
  <section>
    <b-collapse :open="false">
      <button class="button is-primary" slot="trigger">Click me!</button>
      <div class="notification">
        <div class="content">
          <h3>Subtitle</h3>
          <p>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit.
            Nulla accumsan, metus ultrices eleifend gravida, nulla nunc varius lectus, nec rutrum justo nibh eu lectus.
          </p>
        </div>
      </div>
    </b-collapse>
  </section>
</template>

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

We add the b-collapse component with the button being in the trigger slot to use as the trigger for the collapse component.

Then content is anything outside the trigger slot in the b-collapse component.

Collapse Panel

We can add a tab panel by adding an element with the panel-tabs class:

<template>
  <section>
    <div class="block">
      <button class="button is-medium is-primary" [@click](http://twitter.com/click "Twitter profile for @click")="isOpen = !isOpen">Toggle</button>
    </div>

    <b-collapse class="panel" animation="slide" v-model="isOpen">
      <div slot="trigger" class="panel-heading" role="button" aria-controls="contentIdForA11y2">
        <strong>Title</strong>
      </div>
      <p class="panel-tabs">
        <a class="is-active">All</a>
        <a>Public</a>
        <a>Private</a>
      </p>
      <div class="panel-block">Lorem ipsum dolor sit amet, consectetur adipiscing elit.
        <br>Nulla accumsan, metus ultrices eleifend gravida, nulla nunc varius lectus, nec rutrum justo nibh eu lectus.
      </div>
    </b-collapse>
  </section>
</template>

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

We have the b-collapse component with the p element with the panel-tabs class.

And we have the panel-block class on the div to display as the panel content.

Collapse Card

We can make a collapsible card by setting the class attribute of it to card .

The animation has the effect for the toggle.

For example, we can write:

<template>
  <section>
    <b-collapse class="card" animation="slide">
      <div slot="trigger" slot-scope="props" class="card-header" role="button">
        <p class="card-header-title">Component</p>
        <a class="card-header-icon">{{props.open ? '&#x2193;' : '&#x2191;'}}</a>
      </div>
      <div class="card-content">
        <div
          class="content"
        >Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus nec iaculis mauris.</div>
      </div>
      <footer class="card-footer">
        <a class="card-footer-item">OK</a>
        <a class="card-footer-item">Cancel</a>
      </footer>
    </b-collapse>
  </section>
</template>

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

We have the elements with th card-header-title with the title.

card-header-icon has the icon.

And the card-content class is applied to the div with the content.

card-footer has the footer class, and card-footer-item is for the footer items.

props.open indicates whether the collapse component is expanded or not.

Collapse Position

We can place the b-collapse component anywhere we like.

For instance, we can place it inside another element by writing:

<template>
  <section>
    <div class="content">
      <h3>Subtitle</h3>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit.
        Ut vulputate semper dui.
      </p>
    </div>
    <b-collapse :open="false" position="is-bottom">
      <a slot="trigger" slot-scope="props">
        {{ !props.open ? 'All options' : 'Fewer options' }}
        {{props.open ? '&#x2191;': '&#x2193;' }}
      </a>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit.
        Nulla accumsan, metus ultrices eleifend gravida, nulla nunc varius lectus.
      </p>
    </b-collapse>
  </section>
</template>

We add the b-collapse component inside the div instead of keeping it standalone.

Conclusion

We can add a collapse component with Buefy to add a toggleable container to our Vue app.

Categories
Buefy

Buefy — Carousels

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.

Carousel Progress

We can show a progress bar on top of the carousel to indicate its progress.

For example, we can write:

<template>
  <b-carousel progress progressType="is-primary">
    <b-carousel-item v-for="(carousel, i) in carousels" :key="i">
      <section>
        <div class="hero-body has-text-centered">
          <h1 class="title">{{carousel.text}}</h1>
        </div>
      </section>
    </b-carousel-item>
  </b-carousel>
</template>

<script>
export default {
  data() {
    return {
      carousels: [{ text: "Slide 1" }, { text: "Slide 2" }, { text: "Slide 3" }]
    };
  }
};
</script>

to add the progress prop to enable the progress bar.

And progressType styles the progress bar.

Carousel Indicator

The carousel’s slide indicator can also be changed.

For example, we can write:

<template>
  <b-carousel
    :indicator="indicator"
    :indicator-background="indicatorBackground"
    :indicator-inside="indicatorInside"
    :indicator-mode="indicatorMode"
    :indicator-position="indicatorPosition"
    :indicator-style="indicatorStyle"
  >
    <b-carousel-item v-for="(carousel, i) in carousels" :key="i">
      <section>
        <div class="hero-body has-text-centered">
          <h1 class="title">{{carousel.text}}</h1>
        </div>
      </section>
    </b-carousel-item>
  </b-carousel>
</template>

<script>
export default {
  data() {
    return {
      indicator: true,
      indicatorBackground: true,
      indicatorInside: true,
      indicatorMode: "hover",
      indicatorPosition: "is-top",
      indicatorStyle: "is-lines",
      carousels: [{ text: "Slide 1" }, { text: "Slide 2" }, { text: "Slide 3" }]
    };
  }
};
</script>

to add the indicator prop to enable the slide indicator.

indicatorBackground enables the indicator background.

indicatorInside adds the indicator inside the carousel.

indicatorMode sets how to interact with the indicator to change the slides.

indicatorPosition sets the indicator position.

indicatorStyle sets the indicator style.

Custom Carousel Indicators

We can create our own carousel indicator by populating the indicators slot.

For example, we can write:

<template>
  <b-carousel>
    <b-carousel-item v-for="(carousel, i) in carousels" :key="i">
      <section>
        <div class="hero-body has-text-centered">
          <h1 class="title">{{carousel.text}}</h1>
        </div>
      </section>
    </b-carousel-item>
    <template slot="indicators" slot-scope="props">
      <span>{{props.i}}</span>
    </template>
  </b-carousel>
</template>

<script>
export default {
  data() {
    return {
      carousels: [{ text: "Slide 1" }, { text: "Slide 2" }, { text: "Slide 3" }]
    };
  }
};
</script>

to add our own slide indicator by populating the indicators slot.

props.i has the index of the slide.

Custom Carousel With Card

We can add custom carousel with cards.

We can use the b-carousel-list component and populate the item slot with the card.

For example, we can write:

<template>
  <b-carousel-list v-model="test" :data="items" :items-to-show="2">
    <template slot="item" slot-scope="list">
      <div class="card">
        <div class="card-image">
          <figure class="image is-5by4">
            <a @click="info(list.index)">
              <img :src="list.image">
            </a>
          </figure>
          <b-tag type="is-danger" rounded style="position: absolute; top: 0;">
            <b>50%</b>
          </b-tag>
        </div>
        <div class="card-content">
          <div class="content">
            <p class="title is-6">{{ list.title }}</p>
            <p class="subtitle is-7">@abc</p>
            <div class="field is-grouped">
              <p class="control" v-if="list.rating">
                <b-rate :value="list.rating" show-score disabled/>
              </p>
              <p class="control" style="margin-left: auto">
                <button class="button is-small is-danger is-outlined">
                  <b-icon size="is-small" icon="heart"/>
                </button>
              </p>
            </div>
          </div>
        </div>
      </div>
    </template>
  </b-carousel-list>
</template>

<script>
export default {
  data() {
    return {
      items: [
        {
          title: "Slide 1",
          image: "https://buefy.org/static/img/placeholder-1280x960.png",
          rating: 4.5
        },
        {
          title: "Slide 2",
          image: "https://buefy.org/static/img/placeholder-1280x960.png",
          rating: 3.5
        },
        {
          title: "Slide 3",
          image: "https://buefy.org/static/img/placeholder-1280x960.png",
          rating: 5
        }
      ]
    };
  },
  methods: {
    info(value) {
      console.log(value);
    }
  }
};
</script>

We set the data prop to the items array so that we can set the data to the slides.

Inside the item slot, we have the figure with the image.

b-tag has the tag on the top left of the image.

The div with the card-content class has the content below the image.

b-rate has the rating stars.

Conclusion

There’re many ways to customize carousels with Buefy.

Categories
Buefy

Buefy — Buttons and Carousels

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.

Button Tags

We can change the tag of the button with the tag prop.

To use it, we can write:

<template>
  <section>
    <div class="buttons">
      <b-button>Button</b-button>
      <b-button tag="a" href="https://google.com" target="_blank">Anchor</b-button>
      <b-button tag="input" native-type="submit" value="Submit input"/>
    </div>
  </section>
</template>

<script>
export default {};
</script>

We can set tag to 'a' or 'input' to change the tag to those.

Button Router Link

We can also display links as router-links .

For example, we can write:

<template>
  <section>
    <div class="buttons">
      <b-button tag="router-link" to="/documentation" type="is-link">Docs</b-button>
    </div>
  </section>
</template>

<script>
export default {};
</script>

to render the b-button as a router-link component.

Carousel

Buefy comes with a carousel component.

For example, we can write:

<template>
  <b-carousel>
    <b-carousel-item v-for="(carousel, i) in carousels" :key="i">
      <section>
        <div class="hero-body has-text-centered">
          <h1 class="title">{{carousel.text}}</h1>
        </div>
      </section>
    </b-carousel-item>
  </b-carousel>
</template>

<script>
export default {
  data() {
    return {
      carousels: [{ text: "Slide 1" }, { text: "Slide 2" }, { text: "Slide 3" }]
    };
  }
};
</script>

to create a simple carousel with the b-carousel and b-carousel-item components.

b-carousel-item has the carousel items.

We can customize it with various props.

For example, we can write:

<template>
  <b-carousel
    v-model="carousel"
    animated
    has-drag
    autoplay
    pause-hover
    pause-info
    pause-info-type="is-primary"
    :interval="2000"
    repeat
    [@change](http://twitter.com/change "Twitter profile for @change")="info($event)"
  >
    <b-carousel-item v-for="(carousel, i) in carousels" :key="i">
      <section>
        <div class="hero-body has-text-centered">
          <h1 class="title">{{carousel.text}}</h1>
        </div>
      </section>
    </b-carousel-item>
  </b-carousel>
</template>

<script>
export default {
  data() {
    return {
      carousel: 1,
      carousels: [{ text: "Slide 1" }, { text: "Slide 2" }, { text: "Slide 3" }]
    };
  },
  methods: {
    info(e) {
      console.log(e);
    }
  }
};
</script>

to add some props to our b-carousel component to adjust it.

autoplay makes the carousel play automatically.

pause-hover makes it pause on hover.

has-drag makes the slides draggable.

pause-info-type sets the type for when it’s paused.

repeat makes the slides repeat after the loop is done.

v-model has the slide index.

animated adds some animation effect to the carousel.

The @change event handler is run when the slide changes.

Carousel Arrow

We can add the arrow to the carousel.

For example, we can write:

<template>
  <b-carousel
    :arrow="arrow"
    :repeat="arrowBoth"
    :arrow-hover="arrowHover"
    :icon-pack="iconPack"
    :icon-prev="iconPrev"
    :icon-next="iconNext"
    :icon-size="iconSize"
  >
    <b-carousel-item v-for="(carousel, i) in carousels" :key="i">
      <section>
        <div class="hero-body has-text-centered">
          <h1 class="title">{{carousel.text}}</h1>
        </div>
      </section>
    </b-carousel-item>
  </b-carousel>
</template>

<script>
export default {
  data() {
    return {
      arrow: true,
      arrowBoth: false,
      arrowHover: false,
      iconPack: "fa",
      iconPrev: "arrow-left",
      iconNext: "arrow-right",
      iconSize: "10px",
      carousels: [{ text: "Slide 1" }, { text: "Slide 2" }, { text: "Slide 3" }]
    };
  }
};
</script>

to use the arrow icons from Font Awesome 4.7.0 for our icons.

We set the icon class names with the icon-prev and icon-next props.

icon-pack sets the icon pack to use.

In index.html , we add the CSS by adding:

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

to the head tag.

Conclusion

We can render buttons our way and add carousels with Buefy.

Categories
Storybook for React

Storybook for React — Backgrounds and Globals

Storybook lets us prototype components easily with various parameters.

In this article, we’ll look at how to work with globals with Storybook.

Backgrounds

We can set the backgrounds toolbar item to add choices for setting the background.

We can do this globally by adding the options in the .storybook/preview.js file:

export const parameters = {
  backgrounds: {
    default: 'twitter',
    values: [
      {
        name: 'twitter',
        value: '#00aced'
      },
      {
        name: 'facebook',
        value: '#3b5998'
      },
    ],
  }
}

We set the backgrounds property to set the choices for setting the background color.

values has an array of choices that we can set.

name is the name that’s displayed in the dropdown and value is the background color value.

default is the name of the choice to display.

We can also set the choices for one set of stories.

To do that, we write:

src/stories/Button.stories.js

import React from 'react';

import { Button } from './Button';

export default {
  title: 'Example/Button',
  component: Button,
  argTypes: {
    backgroundColor: { control: 'color' },
  },
  parameters: {
    backgrounds: {
      default: 'twitter',
      values: [
        {
          name: 'twitter',
          value: '#00aced'
        },
        {
          name: 'facebook',
          value: '#3b5998'
        },
      ],
    }
  }
};

We set the background color in the Button stories set within the parameters property.

Also, we can set the background color dropdown only for one story.

To do that, we write:

src/stories/Button.stories.js

import React from 'react';

import { Button } from './Button';

export default {
  title: 'Example/Button',
  component: Button,
  argTypes: {
    backgroundColor: { control: 'color' },
  },
};

const Template = (args) => <Button {...args} />;

export const Primary = Template.bind({});
Primary.args = {
  primary: true,
  label: 'Button',
};

Primary.parameters = {
  backgrounds: {
    default: 'twitter',
    values: [
      {
        name: 'twitter',
        value: '#00aced'
      },
      {
        name: 'facebook',
        value: '#3b5998'
      },
    ],
  }
};

The backgrounds can also be disabled with the disable property set to true :

import React from 'react';

import { Button } from './Button';

export default {
  title: 'Example/Button',
  component: Button,
  argTypes: {
    backgroundColor: { control: 'color' },
  },
};

const Template = (args) => <Button {...args} />;

export const Primary = Template.bind({});
Primary.args = {
  primary: true,
  label: 'Button',
};

Primary.parameters = {
  backgrounds: { disable: true }
};

We disable the background dropdown with the Primary story.

Toolbars and Globals

We can create our own Storybook toolbar items to control special global variables.

Globals are non-story-specific inputs to the rendering of the story

They aren’t passed into a story as args.

We can add our own toolbar by putting some properties in the .storybook/preview.js file:

export const globalTypes = {
  theme: {
    name: 'Theme',
    description: 'Global theme for components',
    defaultValue: 'light',
    toolbar: {
      icon: 'circlehollow',
      items: ['light', 'dark'],
    },
  },
};

We have the theme property with some properties.

The toolbar property has the icon property to set the icon for the dropdown choices.

items has an array of items to choose from.

Create a Decorator

We can consume the theme global with a decorator.

For example, we can write:

.storybook/preview.js

import React from 'react';
import { ThemeProvider } from 'styled-components';

export const globalTypes = {
  theme: {
    name: 'Theme',
    description: 'Global theme for components',
    defaultValue: 'palevioletred',
    toolbar: {
      icon: 'circlehollow',
      items: ['palevioletred', 'white'],
    },
  },
};

const withThemeProvider = (Story, context) => {
  return (
    <ThemeProvider theme={{ main: context.globals.theme }}>
      <Story {...context} />
    </ThemeProvider>
  )
}
export const decorators = [withThemeProvider];

We added some theme choices with the toolbar property.

And we get the selected value with the context.globals.theme property.

We wrapped the ThemeProvider around our Story component, which is whatever component we display in the story.

And then we export the withThemeProvider we created which we put in an array.

Now we can set the theme by selecting it from the dropdown.

Conclusion

We can add choices for backgrounds and set globals which we use with decorators.