Elements
The small parts: avatars with status and stacking, dropdown menus (live — driven by the same Stimulus controller as the topbar), and button groups. All of it composes into tables, headings, and drawers without extra CSS.
Avatars
Sizes
Rounded
Placeholders
Status — top & bottom
Group — first on top
Group — last on top
With text
Alex Rivera
Administrator
<span class="avatar-wrap"> <span class="avatar">AR</span> <span class="avatar-status bg-success-500"></span> </span> <div class="avatar-group"> <span class="avatar">AR</span><span class="avatar">SW</span>… </div>
Dropdowns
live — click to open, Escape or click-away to close
<div class="dropdown" data-controller="dropdown">
<button class="btn btn-secondary" data-dropdown-target="button"
data-action="dropdown#toggle">Options</button>
<div class="dropdown-menu hidden" data-dropdown-target="menu">
<button class="dropdown-item">Edit</button>
<div class="dropdown-divider"></div>
<button class="dropdown-item">Delete</button>
</div>
</div>
User menu
BmsDesign::UserMenuComponent — the topbar identity dropdown, shared across every
BMS app (BMS_APP_CONTRACT §6). Live: click to open.
Plain — no profile, no domain layer
Tenanted — profile, and the extra slot
<%= render BmsDesign::UserMenuComponent.new(
name: Current.user.full_name, email: Current.user.email,
profile_url: profile_path, sign_out_url: session_path) do |menu| %>
<% menu.with_avatar { avatar_for(Current.user) } %> <%# optional — initials otherwise %>
<% menu.with_extra do %> <%# the domain layer: switcher, admin link %>
<%= link_to "Administration", admin_root_path, class: "dropdown-item" %>
<% end %>
<% end %>
Button groups
Basic
Icon only
With stat
With checkbox
With dropdown
<div class="btn-group"> <button class="btn btn-secondary">Years</button> <button class="btn btn-secondary">Months</button> <span class="btn-group-segment">1,024</span> </div>