- Build reusable UI components for Ruby on Rails applications.
- Develop Ruby on Rails applications using the
BEM
methodology.
IMPORTANT. Using the BEM
methodology is optional.
Additional resources:
- Habr article in Russian - Переиспользуемые UI компоненты в приложениях на Ruby on Rails.
bemer-simple_form
- Add theBEM
methodology to yourSimpleForm
forms.bemer-bootstrap
- Reusable UI components ofBootstrap
.- Ruby on Rails application using
bemer
andbemer-bootstrap
.
Add it to your Gemfile:
gem 'bemer'
Run the following command to install it:
$ bundle
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
# 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
# ...
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
| | | └── ...
| | └── ...
| └── ...
└── ...
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
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/
| | | └── ...
| | └── ...
| └── ...
└── ...
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'
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
/ 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
- File naming and folder structure
- Configuration
- Creating and using UI components
- Helpers for UI components
- Additional helpers for the BEM methodology
- BEMHTML
- BEM methodology - https://bem.info/methodology/
- Minimal stack for coding client-side JavaScript and templating - https://github.com/bem/bem-core
- Declarative template engine for the browser and server with regular JS syntax - https://github.com/bem/bem-xjst
- BEM Forum - https://bem.info/forum/
Copyright (c) 2017-2023 Alexander Grigorev. See LICENSE.txt for further details.