Essential Guide 10: Styling and Notifications
Demo: Matestack Demo Github Repo: Matestack Demo Application
Welcome to the tenth part of our tutorial about building a web application with matestack.
Introduction
After introducing Vue.js components in the previous guide, it's time to work on the appearance and user experience of the application.
In this guide, we will
install and set up the popular UI toolkit Bootstrap
add styling to the existing pages and components using bootstrap
cover the best practice for styling custom components
add bootstrap notification badges
finish of the changes by adding a loading spinner for matestack page transitions
Note: This guide uses Rails 6 and Webpack. If you're using the Asset Pipeline in your application, please head to the Asset Pipeline section at the bottom of this page.
This guide is heavily inspired by Ross Kaffenberger's guide on Using Bootstrap with Rails Webpacker.
Prerequisites
We expect you to have successfully finished the previous guide.
Installing Bootstrap
Let's kick it off by running yarn add bootstrap
to install Bootstrap. Then, create a file called custom-bootstrap.scss
in app/javascript/css/
and add the following line
to import it. The only missing part now is importing this file in to the existing app/javascript/packs/application.js
file.
Installing jQuery
Bootstrap requires jQuery and popper.js, so now is a good time to add those dependencies. Install it by runnning yarn add jquery popper.js
.
Afterwards import all JavaScript dependencies of bootstrap and bootstraps own JavaScript in the app/javascript/packs/application.js
by adding the following lines to it.
Starting to style the application
Before we begin putting bootstrap to use, we need to prepare the app/view/layouts/application.html.erb
for responsive use by adding the appropiate meta tag. Therefore we update the <head>
section of our app/views/layouts/application.html.erb
.
Let's save our changes by running
In the next step we arrange and style the contents of our app and pages using bootstrap. We also refactor our app and pages with partials and components where necessary.
app/matestack/demo/app.rb
We extracted our navigation into a partial and added a footer as a partial. Both are styled with bootstrap. Because it is quite complex, we also excluded the navigation toggle button for the responsive navigation into a partial called navbar_button
.
Next we style our person index page. Below you can see the updated file styled with bootstrap.
app/matestack/demo/pages/persons/index.rb
As you see, we added a custom component called jumbotron_header
. It is used on every page with different headlines, or without a headline. Because we reuse it, we extracted it into a custom component defined in app/matestack/components/shared/jumbotron_header.rb
. And registered it in our registry as jumbotron_header: Components::Shared::JumbotronHeader
. We called it jumbotron header because it uses bootstraps jumbotron component.
Quite a simple component. To keep it more readable we extracted the hash argument for the first div into a method jumbotron_options
which returns a hash with the needed classes and styling for a background image.
In order to make our jumbotron and our content looking really good, we need some CSS. We want to overlap our list of person with the jumbotron and add a small shadow in order to make the overflow stand out.
Therefore we add a file called application.scss
in app/javascripts/css/
. We will add some styles to it in order to achieve our overflow effect and some general styles for our app. For example making our footer always appear at the bottom of the page no matter how less content there might be on a page.
Like our custom bootstrap scss file we need to import our application.scss
file in our app/javascript/packs/application.js
file.
Now we can refactor and style all other person pages. Feel free to experiment and style on your own or take a look at the repository to review our changes to the pages.
Overwriting Bootstrap default styles
We only used bootstraps components and therefore just got the well known bootstrap look and feel. In order to make our application really our own we will go on and theme bootstrap accordingly. Learn more about how and what you can theme or customize in bootstrap by reading the bootstrap documentation. In the next step we change the default color scheme of bootstrap by overriding a few CSS variables or maps. Pay attention, all your overrides need to happen before the @import
statement.
app/javascript/css/custom-bootstrap.scss
Styling custom components
We styled our app and pages. The last thing missing is styling of our custom components. As an example we refactor, style and upgrade our disclaimer component. We introduced it a while ago to give an example how we can use .haml
files with components. But because we want to add the functionality to hide the disclaimer by clicking a button and we don't need a custom .haml
file, we will remove it now. Afterwards we update our disclaimer component to contain a bootstrap alert and make it hideable.
app/matestack/components/persons/disclaimer.rb
As you can see, we used the earlier introduced toggle component in order to hide the disclaimer if a user presses the "Hide" button, which emits the appropriate event for the toggle component.
In order to make our disclaimer float over our jumbotron header underneath the navigation we need to style it with some CSS. In order to keep our code clean and create scope-like styles we recommend a best practice for file locations and stylings. First the file location. We recommend to create the SCSS file right next to your component. In the case of the disclaimer component this would be app/matestack/components/persons/disclaimer.scss
. Let's create that file and import it in our custom-bootstrap.scss
with @import '../../matestack/components/persons/disclaimer';
. By adding it below our bootstrap import, we can make use of bootstraps variables, breakpoints and more (like md in @include media-breakpoint-down(md)
).
In order to keep our styles for the disclaimer from affecting other elements, we recommend to add a unique class to the most outer element of your component. In our case we will add a class .disclaimer-component
to the child div
of the toggle
component. The line should now look like this:
In our SCSS file we will only add styles inside of the selector .disclaimer-component
. This will prevent us from overriding styles of other elements by mistake. Now let's style our disclaimer by adding the following content to our SCSS file:
Adding page transition animations
Okay, now that our application is styled and customized we can take a look at the user experience. Using transition
components inside an app increased the user experience already quite a lot by making the website feel more like an app. But what about smooth transitions between pages of our app. Matestack provides us with an easy to use solution to implement subtle animations, for example a loading spinner between page loads.
We simply need to add a loading_state
slot to our yield_page
call in our demo app. The yield_page call now gets passed in slots
as a hash. Inside the hash we set the value of the loading_state
calling a partial. The partial loading_state_element
contains a simple bootstrap spinner.
To better understand what we achieve with this let's take a look at matestacks DOM structure for pages, when you pass in a loading_state
slot.
The .loading-state-element-wrapper
div will only be rendered if a loading_state
slot is defined. It contains the defined element, in our case our bootstrap loading spinner. The .matestack-page-wrapper
div contains the page content. If we now visit the root page, we will see a spinner above our page content. This is because we have not yet added the required rules to hide it unless the page is actually reloading. If a page transition happens and the page is reloaded, all the above elements will get a .loading
class added. We can use this to add a simple page transition animation.
In order to do that, we add another SCSS file in app/javascript/css/page-transition.scss
and import it in our application.js
with import 'css/page-transition'
. Here we will define the default styles for our loading element and page content. Our loading element should normally be invisible and our page content should be visible. If a .loading
class is applied we want to hide the page content and show our loading element. We can achieve this with the following rules and add a smooth animation between the show and hide states.
If you now take a look at your application in the browser and click a transition link, you may see the animation, but only very short or maybe not at all. This is due to the fact that our page is reloaded to fast in order to fully appreciate our animation. To smooth the animation we could add a delay to our transitions with the delay
option. This will delay the reload by a given time in milliseconds, which will give us and the user time to see the animation, preventing unwanted flickering. But be careful, don't choose a big delay, as users might get upset by to long animations.
Recap & outlook
In this guide we learned how to use bootstrap with matestack in order to style an application, how to customize bootstrap, a best practice about styling components and how we can add animations between page transitions.
Going ahead, the next part of this series covers authentication via Devise.
Using the Asset Pipeline instead of Webpack(er)
If you're using the Asset Pipeline in your application, using Bootstrap to style your matestack
pages and components also works very well - you only need to take a slightly different route while setting things up!
Installing Bootstrap and jQuery
Add the following lines to your Gemfile
and run bundle install
. Afterwards, change app/assets/stylesheets/appplciation.css
to app/assets/stylesheets/appplciation.scss
and import Bootstrap by adding the follwing line:
To use jQuery and various Bootstrap JavaScript plugins, add the following lines to your application.js
:
Now, we're good to go concerning the underlying libraries. Further information can be found on the Bootstrap Gem Site.
Styling matestack custom components and pages
Since we want to put the .scss
-files for our custom components right next to the component definition in app/matestack/components/
, we need to update our config/initializers/assets.rb
configuration by adding the following line:
Now, in the app/assets/stylesheets/appplciation.scss
, you can import custom component stylesheets by importing them, respecting potential namespaces. The example from above would look like this:
From our experience, it makes sense to create a app/assets/stylesheets/pages/
directory, containing a .scss
-file for every matestack
page, and then structure app/assets/stylesheets/appplciation.scss
like this:
Last updated