Skip to content

Latest commit

 

History

History
296 lines (252 loc) · 12 KB

README.md

File metadata and controls

296 lines (252 loc) · 12 KB

Bemer

  1. Build reusable UI components for Ruby on Rails applications.
  2. Develop Ruby on Rails applications using the BEM methodology.

IMPORTANT. Using the BEM methodology is optional.

Additional resources:

  1. Habr article in Russian - Переиспользуемые UI компоненты в приложениях на Ruby on Rails.
  2. bemer-simple_form - Add the BEM methodology to your SimpleForm forms.
  3. bemer-bootstrap - Reusable UI components of Bootstrap.
  4. Ruby on Rails application using bemer and bemer-bootstrap.

Installation

Add it to your Gemfile:

gem 'bemer'

Run the following command to install it:

$ bundle

Configuration

See configuration documentation for details.

# config/initializers/bemer.rb

Bemer.setup do |config|
  config.bem                     = true
  config.modifier_name_separator = '--'
  config.path                    = 'app/frontend/components' # or Webpacker.config.source_path
  # config.default_path_prefix     = lambda { |path, view|
  #   view.controller.class.name.split('::')[0].underscore
  # }
end

Integrations

Webpacker

# config/webpacker.yml

default: &default
  source_path: app/frontend/components
  source_entry_path: ../packs
  public_output_path: frontend/assets
  # ...

development:
  <<: *default
  # ...

test:
  <<: *default
  # ...

production:
  <<: *default
  # ...

File naming and folder structure

See file naming and folder structure documentation for details.

app/
  ├── frontend/
  |     ├── components/
  |     |     ├── common/
  |     |     |     ├── carousel/
  |     |     |     |     ├── index.slim
  |     |     |     |     ├── bemhtml.slim
  |     |     |     |     ├── index.js
  |     |     |     |     ├── index.scss
  |     |     |     |     └── ...
  |     |     |     ├── form/
  |     |     |     |     ├── error_messages_elem/
  |     |     |     |     |     ├── index.slim
  |     |     |     |     |     ├── index.js
  |     |     |     |     |     ├── index.scss
  |     |     |     |     |     └── ...
  |     |     |     |     ├── locales/
  |     |     |     |     |     ├── en.yml
  |     |     |     |     |     └── ...
  |     |     |     |     ├── index.slim
  |     |     |     |     ├── base.rb
  |     |     |     |     ├── index.js
  |     |     |     |     ├── index.scss
  |     |     |     |     └── ...
  |     |     |     └── ...
  |     |     ├── admin_panel/
  |     |     |     └── ...
  |     |     ├── landing/
  |     |     |     └── ...
  |     |     ├── user_panel/
  |     |     |     └── ...
  |     |     └── ...
  |     ├── packs/
  |     |     ├── admin_panel/
  |     |     |     ├── application.js
  |     |     |     └── ...
  |     |     ├── landing/
  |     |     |     ├── application.js
  |     |     |     └── ...
  |     |     ├── user_panel/
  |     |     |     ├── application.js
  |     |     |     └── ...
  |     |     └── ...
  |     └── ...
  └── ...

Sprockets

You do not need to do anything, but add additional assets to the asset load path if necessary:

# config/initializers/bemer.rb

Bemer.setup do |config|
  config.asset_paths << Rails.root.join('some/asset/path')
end

File naming and folder structure

See file naming and folder structure documentation for details.

app/
  ├── assets/
  |     ├── javascripts/
  |     |     ├── admin_panel/
  |     |     |     ├── application.js
  |     |     |     └── ...
  |     |     ├── landing/
  |     |     |     ├── application.js
  |     |     |     └── ...
  |     |     ├── user_panel/
  |     |     |     ├── application.js
  |     |     |     └── ...
  |     |     └── ...
  |     ├── stylesheets/
  |     |     ├── admin_panel/
  |     |     |     ├── application.scss
  |     |     |     └── ...
  |     |     ├── landing/
  |     |     |     ├── application.scss
  |     |     |     └── ...
  |     |     ├── user_panel/
  |     |     |     ├── application.scss
  |     |     |     └── ...
  |     |     └── ...
  |     └── ...
  ├── frontend/
  |     ├── components/
  |     |     ├── common/
  |     |     |     ├── carousel/
  |     |     |     |     ├── index.slim
  |     |     |     |     ├── bemhtml.slim
  |     |     |     |     ├── index.js
  |     |     |     |     ├── index.scss
  |     |     |     |     └── ...
  |     |     |     ├── form/
  |     |     |     |     ├── error_messages_elem/
  |     |     |     |     |     ├── index.slim
  |     |     |     |     |     ├── index.js
  |     |     |     |     |     ├── index.scss
  |     |     |     |     |     └── ...
  |     |     |     |     ├── locales/
  |     |     |     |     |     ├── en.yml
  |     |     |     |     |     └── ...
  |     |     |     |     ├── index.slim
  |     |     |     |     ├── base.rb
  |     |     |     |     ├── index.js
  |     |     |     |     ├── index.scss
  |     |     |     |     └── ...
  |     |     |     └── ...
  |     |     ├── admin_panel/
  |     |     |     └── ...
  |     |     ├── landing/
  |     |     |     └── ...
  |     |     ├── user_panel/
  |     |     |     └── ...
  |     |     └── ...
  |     └── ...
  └── ...

Usage

Component to which BEMHTML templates cannot be applied

HTML structure of the Carousel component from Bootstrap:

/ app/frontend/components/common/carousel/index.slim

.carousel.slide data-ride="carousel" class=local_assigns[:cls]
  ol.carousel-indicators
    - image_urls.size.times do |i|
      li data-target=".carousel" class=(:active if i.zero?) data-slide-to=i
  .carousel-inner
    - image_urls.each_with_index do |image_url, i|
      .carousel-item class=(:active if i.zero?)
        = image_tag image_url, class: 'd-block w-100'
  a.carousel-control-prev data-slide="prev" data-target='.carousel' role="button"
    span.carousel-control-prev-icon aria-hidden="true"
    span.sr-only Previous
  a.carousel-control-next data-slide="next" data-target='.carousel' role="button"
    span.carousel-control-next-icon aria-hidden="true"
    span.sr-only Next

Rendering the carousel component in any view or other UI components:

= render_component :carousel, prefix: :common, image_urls: image_urls, cls: 'carousel-fade'

Component to which BEMHTML templates can be applied

Tree structure of the Carousel component from Bootstrap:

/ app/frontend/components/common/carousel/index.slim

= define_component do |component|
  = component.block :carousel, 'data-ride': :carousel, 'data-interval': false, cls: :slide do |carousel|
    = carousel.elem :indicators, tag: :ol, cls: 'carousel-indicators'
      - image_urls.size.times do |i|
        = carousel.elem :indicator, tag: :li, 'data-slide-to': i, mods: (:active if i.zero?), 'data-target': '.carousel'
    = carousel.elem :inner, cls: 'carousel-inner'
      - image_urls.each_with_index do |image_url, i|
        = carousel.elem :item, cls: 'carousel-item', mods: (:active if i.zero?)
          = carousel.elem :image, tag: :img, cls: 'd-block w-100', src: image_url
    = carousel.elem :control_prev, tag: :a, cls: 'carousel-control-prev', 'data-slide': :prev, role: :button, 'data-target': '.carousel'
      span.carousel-control-prev-icon aria-hidden="true"
      span.sr-only Previous
    = carousel.elem :control_next, tag: :a, cls: 'carousel-control-next', 'data-slide': :next, role: :button, 'data-target': '.carousel'
      span.carousel-control-next-icon aria-hidden="true"
      span.sr-only Next

Default template:

/ app/frontend/components/common/carousel/bemhtml.slim

= define_templates do |template|
  = template.elem(mods: :active).add_cls :active

Rendering the carousel component in any view or other UI components using BEMHTML templates:

= render_component :carousel, prefix: :common, image_urls: image_urls do |template|
  = template.block(:carousel).add_mix :carousel_fade

Documentation in Russian

  1. File naming and folder structure
  2. Configuration
  3. Creating and using UI components
  4. Helpers for UI components
    1. define_component
    2. define_templates
    3. render_component
    4. refine_component
    5. component_pack
    6. component_asset_path
    7. component_partial_path
  5. Additional helpers for the BEM methodology
    1. bem_attrs_for
    2. bem_mix
    3. bem_mods
    4. block_tag
    5. elem_tag
  6. BEMHTML
    1. Templates
    2. Node
    3. Predicates
    4. Modes

Links

  1. BEM methodology - https://bem.info/methodology/
  2. Minimal stack for coding client-side JavaScript and templating - https://github.com/bem/bem-core
  3. Declarative template engine for the browser and server with regular JS syntax - https://github.com/bem/bem-xjst
  4. BEM Forum - https://bem.info/forum/

License

Copyright (c) 2017-2023 Alexander Grigorev. See LICENSE.txt for further details.