Agile Web Development with Rails, Edition 5

27.4 Devise 25.2 Slim

25.3 CSS with Webpack

mkdir app/javascript/packs/css
mv app/assets/stylesheets/application.scss app/javascript/packs
mv app/assets/stylesheets/*.scss app/javascript/packs/css
edit app/javascript/packs/application.scss
/*
 * This is a manifest file that'll be compiled into application.css, which will
 * include all the files listed below.
 * 
 * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any
 * plugin's vendor/assets/stylesheets directory can be referenced here using a
 * relative path.
 * 
 * You're free to add application-wide styles to this file and they'll appear
 * at the bottom of the compiled file so the styles you add here take
 * precedence over styles defined in any other CSS/SCSS files in this
 * directory. Styles in this file should be added after the last require_*
 * statement. It is generally better to create a new file per style scope.
 * 
 *= require_tree .
 *= require_self
 */
 
 
@import "css/orders.scss";
@import "css/sessions.scss";
@import "css/scaffolds.scss";
@import "css/store.scss";
@import "css/products.scss";
@import "css/users.scss";
@import "css/line_items.scss";
@import "css/carts.scss";
@import "css/admin.scss";
body {
  margin: 0;
  padding: 0;
}
header.main {
  text-align: center; // center on mobile
  @media (min-width: 30em) {
    text-align: left; // left align on desktop
  }
  background: #282;
  margin: 0;
  h1 {
    display: none;
  }
}
 
.notice, #notice {
  background: #ffb;
  border-radius: 0.5em;
  border: solid 0.177em #882;
  color: #882;
  font-weight: bold;
  margin-bottom: 1em;
  padding: 1em 1.414em;
  text-align: center;
}
.content {
  margin: 0;
  padding: 0;
 
  display: flex;
  display: -webkit-flex;
  flex-direction: column; // mobile is horizontally laid out
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
 
  @media (min-width: 30em) {
    flex-direction: row;  // desktop is vertically laid out
    -webkit-box-orient: horizontal;
  }
 
  nav {
    padding-bottom: 1em;
    background: #141;
    text-align: center;  // mobile has centered nav
    @media (min-width: 30em) {
      text-align: left; // desktop nav is left-aligned
      padding: 1em;     // and needs more padding
    }
 
    #cart {
      article {
        h2 {
          margin-top: 0;
        }
        background: white;
        border-radius: 0.5em;
        margin: 1em;
        padding: 1.414em;
        @media (min-width: 30em) {
          margin: 0; // desktop doesn't need this margin
        }
      }
    }
 
// START: logged_in_nav
nav.logged_in_nav {
  border-top: solid thin #bfb;
  padding: 0.354em 0;
  margin-top: 0.354em;
  input[type="submit"] {
    // Make the logout button look like a
    // link, so it matches the nav style
    background: none;
    border: none;
    color: #bfb;
    font-size: 1em;
    letter-spacing: 0.354em;
    margin: 0;
    padding: 0;
    text-transform: uppercase;
  }
  input[type="submit"]:hover {
    color: white;
  }
}
// END: logged_in_nav
 
    ul {
      list-style: none;
      margin: 0;
      padding: 0;
      @media (min-width: 30em) {
        padding-right: 1em; // give desktop some extra space
      }
      li {
        margin: 0;
        padding: 0.5em;
        text-transform: uppercase;
        letter-spacing: 0.354em;
        a {
          color: #bfb;
          text-decoration: none;
        }
        a:hover {
          background: none;
          color: white;
        }
      }
    }
  }
  main {
    padding: 0.5em;
  }
}
 
.depot_form {
  padding: 0 1em;
  h1 {
    font-size: 1.99em;
    line-height: 1.41em;
    margin-bottom: 0.5em;
    padding: 0;
  }
  .field, .actions {
    margin-bottom: 0.5em;
    padding: 0;
  }
  .actions {
    text-align: right;
    padding: 1em 0;
  }
  input, textarea, select, option {
    border: solid thin #888;
    box-sizing: border-box;
    font-size: 1em;
    padding: 0.5em;
    width: 100%;
  }
  label {
    padding: 0.5em 0;
  }
  input[type="submit"] {
    background-color: #bfb;
    border-radius: 0.354em;
    border: solid thin #888;
    color: black;
    font-size: 1.41em;
    font-weight: bold;
    padding: 0.354em 1em;
  }
  input[type="submit"]:hover {
    background-color: #9d9;
  }
  // Also, clean up the error styling
  #error_explanation {
    background-color: white;
    border-radius: 1em;
    border: solid thin red;
    margin-bottom: 0.5em;
    padding: 0.5em;
    width: 100%;
    h2 {
      background: none;
      color: red;
      font-size: 1.41em;
      line-height: 1.41em;
      padding: 1em;
    }
    ul {
      margin-top: 0;
      li {
        color: red;
        font-size: 1em;
      }
    }
  }
  .field_with_errors {
    background: none;
    color: red;
    width: 100%;
    label {
      font-weight: bold;
    }
    label::before {
      content: "! ";
    }
    input,textarea {
      background: pink;
    }
  }
}
 
.locale {
  float: right;
  margin: 1em;
}
edit app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>Pragprog Books Online Store</title>
    <%= csrf_meta_tags %>
 
    
 
    <%= stylesheet_pack_tag "application" %>
    
    
    <%= javascript_include_tag 'application',
                               'data-turbolinks-track': 'reload' %>
    <script type="text/javascript">
      I18n.defaultLocale = "<%= I18n.default_locale %>";
      I18n.locale        = "<%= I18n.locale %>";
    </script>
 
 
  </head>
 
  <body>
    <header class="main">
      <aside>
        <%= form_tag store_index_path, class: 'locale' do %>
          <%= select_tag 'set_locale', 
            options_for_select(LANGUAGES, I18n.locale.to_s),
            onchange: 'this.form.submit()' %>
          <%= submit_tag 'submit', id: "submit_locale_change" %>
        <% end %>
      </aside>
      <%= image_tag 'logo.svg', alt: 'The Pragmatic Bookshelf' %>
      <h1><%= @page_title %></h1>
    </header>
    <section class="content">
      <nav class="side_nav">
 
        <div id="cart" class="carts">
 
          <%= render_if @cart && @cart.line_items.any?, @cart %>
        </div>
 
      <%= render Order.find(session[:order_id]) if session[:order_id] -%>
 
        <ul>
          <li><a href="/"><%= t('.home') %></a></li>
          <li><a href="/questions"><%= t('.questions') %></a></li>
          <li><a href="/news"><%= t('.news') %></a></li>
          <li><a href="/contact"><%= t('.contact') %></a></li>
        </ul>
 
        <% if session[:user_id] %>
          <nav class="logged_in_nav">
            <ul>
              <li><%= link_to 'Orders',   orders_path   %></li>
              <li><%= link_to 'Products', products_path %></li>
              <li><%= link_to 'Users',    users_path    %></li>
              <li><%= button_to 'Logout', logout_path, method: :delete   %></li>
            </ul>
          </nav>
        <% end %>
      </nav>
      <main class='<%= controller.controller_name %>'>
        <%= yield %>
      </main>
    </section>
  </body>
</html>
yarn add postcss-cssnext
yarn add v1.3.2
[1/4] Resolving packages...
[2/4] Fetching packages...
info fsevents@1.1.3: The platform "linux" is incompatible with this module.
info "fsevents@1.1.3" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning " > postcss-cssnext@3.0.2" has unmet peer dependency "caniuse-lite@^1.0.30000697".
warning " > webpack-dev-server@2.9.4" has unmet peer dependency "webpack@^2.2.0 || ^3.0.0".
warning "webpack-dev-server > webpack-dev-middleware@1.12.0" has unmet peer dependency "webpack@^1.0.0 || ^2.0.0 || ^3.0.0".
[4/4] Building fresh packages...
success Saved 1 new dependency.
└─ postcss-cssnext@3.0.2
Done in 3.24s.
edit .postcssrc.yml
#<IndexError: regexp not matched>
  /home/rubys/git/gorp/lib/gorp/edit.rb:150:in `[]='
  /home/rubys/git/gorp/lib/gorp/edit.rb:150:in `msub'
  makedepot.rb:5303:in `block (2 levels) in <main>'
  /home/rubys/git/gorp/lib/gorp/edit.rb:173:in `instance_exec'
  /home/rubys/git/gorp/lib/gorp/edit.rb:173:in `edit'
  makedepot.rb:5302:in `block in <main>'
  /home/rubys/git/gorp/lib/gorp/output.rb:59:in `block (4 levels) in <top (required)>'
  /home/rubys/git/gorp/lib/gorp/output.rb:49:in `each'
  /home/rubys/git/gorp/lib/gorp/output.rb:49:in `block (3 levels) in <top (required)>'
  /home/rubys/.rvm/gems/ruby-2.4.1/gems/builder-3.2.3/lib/builder/xmlbase.rb:175:in `_nested_structures'
  /home/rubys/.rvm/gems/ruby-2.4.1/gems/builder-3.2.3/lib/builder/xmlbase.rb:68:in `tag!'
  /home/rubys/.rvm/gems/ruby-2.4.1/gems/builder-3.2.3/lib/builder/xmlbase.rb:93:in `method_missing'
  /home/rubys/git/gorp/lib/gorp/output.rb:22:in `block (2 levels) in <top (required)>'
  /home/rubys/.rvm/gems/ruby-2.4.1/gems/builder-3.2.3/lib/builder/xmlbase.rb:175:in `_nested_structures'
  /home/rubys/.rvm/gems/ruby-2.4.1/gems/builder-3.2.3/lib/builder/xmlbase.rb:68:in `tag!'
  /home/rubys/.rvm/gems/ruby-2.4.1/gems/builder-3.2.3/lib/builder/xmlbase.rb:93:in `method_missing'
  /home/rubys/git/gorp/lib/gorp/output.rb:11:in `block in <top (required)>'
    
plugins:
  postcss-smart-import: {}
  postcss-cssnext: {}
edit app/javascript/packs/css/store.scss
// Place all the styles related to the Store controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
 
 
.store {
  max-width: 80em;
  ul.catalog {
    
    border-top: solid 0.250em gray(50%);
 
 
    list-style: none;
    padding: 0;
    margin: 0;
    li {
      padding: 1em;
      margin: 0;
      border-bottom: solid thin #ddd;
 
      // This makes sure our <li> has enough height
      // to hold the entire image, since it's floated
      &::after {
        clear: both;
        content: " ";
        display: block;
      }
      img {
        float: left;
        padding: 1em;
        margin-right: 1em;
        margin-bottom: 1em;
        box-shadow: 0.176em 0.176em 0.354em 0px rgba(0,0,0,0.75);
      }
      .price {
        font-size: 1.414em;
      }
 
      form, div {
        display: inline;
      }
      input[type="submit"] {
        background-color: #282;
        border-radius: 0.354em;
        border: solid thin #141;
        color: white;
        font-size: 1em;
        padding: 0.354em 1em;
      }
      input[type="submit"]:hover {
        background-color: #141;
      } 
    }
  }
}

Restart the server.

27.4 Devise 25.2 Slim