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:
- Create and include the new tag
- Store the show/hide state of the modal within the tag
The steps are:
- Create the basic HTML tag
- Create the Javascript tag
- Insert the new tag where you want it to be used
- Extend the HTML tag with new functionality
- Add an alias so that this component can communicate with others
- Add styling
- 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;
}