Analytics & Reports
Analytics

Customizing components

You can customize all components, including the rendering and adding custom hooks.

Example - Making a Modal

This example assumes you have already followed the steps in configuring StoreFront, and importing the library to your build process.

We will build a modal tag - a small set of content that can be shown or hidden with a click.

The modal tag will hold both the button for show/hide, and the modal itself.

This means that we’ll need to have a way to:

  1. Create and include the new tag
  2. Store the show/hide state of the modal within the tag

The steps are:

  1. Create the basic HTML tag
  2. Create the Javascript tag
  3. Insert the new tag where you want it to be used
  4. Extend the HTML tag with new functionality
  5. Add an alias so that this component can communicate with others
  6. Add styling
  7. Done! Look at it all together

Step 1: Make the HTML

To start out, create a modal.html file with the following content.

<!-- modal.html -->
<div>
  <p>I'm a modal!</p>
</div>

This is just a simple HTML file to start out, so that you can be sure that your content is loaded on the page.

Step 2: Write the Javascript

Next, make a modal.js file, which you will include in your Webpack bundle or other build process:

// modal.js
import { tag } from '@storefront/core';

@tag('my-modal', require('/gb-docs/modal.html'))
class Modal {

  init() {
    console.log('modal on');
  }

}

export default Modal;

You may have noticed the import of the tag member. This is a method that takes two parameters, a tag name and an html template, and registers a StoreFront component with that name and structure. As a StoreFront component, the Modal class will have access to the init function, which runs on mount.

Step 3: Insert the tag

In your index.html or whatever main html file you are using to load your page, add your modal component:

<!-- index.html -->
<my-modal></my-modal>

If you open that file in a browser (or run it on a server), you should now see your paragraph content. Opening developer tools, you should also see a console log statement printed in the console.

Step 4: Extending the tag

Extending the HTML

Next, this modal needs a clickable button, which can be done using the gb-button component. Change your modal.html file so that it uses this tag rather than a simple div.

<!-- modal.html -->
<gb-button onclick="{ onClick }">
  <p>I'm a modal!</p>
</gb-button>

Extending the Javascript

Now back in to your modal.js file, add a method called onClick to run when the gb-button tag is clicked. Below your init function in your Modal class, add the following function:

// modal.js
init() { ... }

onClick() {
  console.log('ouch you clicked me!');
}

In the browser, clicking on the gb-button tag causes the console to output the message.

Step 5: Providing an alias

Next, you’ll need to provide an alias so that you state from this component will be available from a child component that consumes its alias. You’ll need to add a property to state which lets the component know whether the modal should be visible. At the top of modal.js right above the call to @tag add a call to @provide, passing in a string which will be used as the name of your alias. You will also need to import provide from @storefront/core.

// modal.js
import { provide, tag } from '@storefront/core';

@provide('modal')
@tag('my-modal', require('/gb-docs/modal.html'))

Now you can access properties on $modal from within a consuming child component. To determine whether to display the modal content, you can add a visible property to the modal’s state using set, setting it to false initially to indicate that the modal is not yet visible. In your init function, remove the console.log call, and add the following:

// modal.js
init() {
  this.set({ visible: false });
}

This call to set, which is a function available on all StoreFront components, will create a property called visible available on the component’s state and in the alias $modal on all consuming child components. Next, make a call to set in the onClick that will toggle the visible boolean attribute.

// modal.js
onClick() {
  this.set({ visible: !this.state.visible });
}

Step 6: Adding styling

To see this toggle in action, you need to modify the modal.html file, by adding a second paragraph tag and some CSS. You will also have to make the button component consume the modal alias so that the visible property can be accessed from within its scope in $modal.

<!-- modal.html -->
<gb-button onclick="{ onClick }" _consumes="modal">
  <p class="{ modal___invisible: $modal.visible }">Click for modal</p>
  <p class="{ modal__invisible: !$modal.visible }">I'm a modal!</p>
</gb-button>

This will apply the modal__invisible CSS class to the first paragraph tag when the modal should be visible, and remove it otherwise (and vice-versa for the second paragraph tag).

Add a CSS file with the following rule, so that when an element has the modal__invisible class on it, it is no longer displayed on the page:

/* styles.css */
.modal__invisible {
  display: none;
}

Step 7: All done

If you run your main html file, you should now see the text in the button change as you click and toggle the visible attribute. This is all the JavaScript you need to make your modal functional. Finally, adding some additional HTML structure and CSS rules, you can make this component look and feel like a true modal!

Complete code examples

Your final file composition should look like the following:

Javascript

// modal.js
import { provide, tag, Events, Selectors } from '@storefront/core';

@provide('modal')
@tag('my-modal', require('/gb-docs/modal.html'))
class Modal {

  init() {
    this.set({ visible: false });
  }

  onClick() {
    this.set({ visible: !this.state.visible });
  }
}

export default Modal;

HTML

<!-- modal.html -->
<gb-button onclick="{ onClick }" _consumes="modal" class="{ modal__visible: state.visible }">
  <div class="{ modal__invisible: $modal.visible }">
    <p>
      Click for modal
    </p>
  </div>
  <div class="{ modal__invisible: !$modal.visible } modal">
    <div class="modal-content">
      <p>
        I'm a modal!
      </p>
    </div>
  </div>
</gb-button>

CSS

/* styles.css */
.modal {
  position: fixed;
  z-index: 1;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: auto;
  background-color: rgb(0,0,0);
  background-color: rgba(0,0,0,0.4);
}

.modal-content {
  background-color: #fefefe;
  margin: 15% auto;
  padding: 20px;
  border: 1px solid #888;
  width: 80%;
}

.modal__invisible {
  display: none;
}

gb-button button {
  border: none;
}

gb-button.modal__visible button {
  background-color: white;
}

gb-button.modal__visible button:focus {
  outline: none;
}