Convert 7 components to BEM class naming convention

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-12-19 02:18:39 +00:00
parent 9e7269e4fc
commit 2c57b9ffbe

View File

@@ -0,0 +1,315 @@
BEM CLASS NAMING - MIGRATION GUIDE
Date: 2024-12-19
SUMMARY
RSX components should use BEM (Block Element Modifier) naming convention for
CSS class names. This ensures that HTML class names match the compiled SCSS
selectors and that styles apply correctly.
The key insight: SCSS nested selectors like `.Component_Name { &__element {} }`
compile to `.Component_Name__element`. If HTML uses a different class name
(like `component-name__element` or `component__element`), the styles won't
apply. This migration standardizes all component child class names to use
the exact PascalCase component prefix.
A code quality rule (JQHTML-CLASS-01) now detects BEM naming violations at
manifest-time, providing immediate feedback when HTML classes don't match
the expected SCSS-compiled selectors.
DESIGN PRINCIPLES
1. BEM Naming Convention
Block: Component_Name (the component's root class, auto-added by jqhtml)
Element: Component_Name__element-name (child elements, double underscore)
Modifier: Component_Name--modifier-name (state variations, double hyphen)
2. PascalCase Component Prefix
Components use PascalCase with underscores (e.g., My_Component). BEM child
classes MUST use the exact same prefix, NOT kebab-case or lowercase.
CORRECT: My_Component__header, My_Component__item-list
WRONG: my-component__header, my_component__header
3. SCSS Nesting Compiles to BEM
SCSS:
.My_Component {
&__header { color: blue; }
&__item { padding: 10px; }
&--active { background: green; }
}
Compiles to:
.My_Component__header { color: blue; }
.My_Component__item { padding: 10px; }
.My_Component--active { background: green; }
HTML must use these exact class names for styles to apply.
AFFECTED FILES
Any component with child element classes that use:
- kebab-case prefix (e.g., my-component__element)
- lowercase prefix (e.g., my_component__element)
- generic class names (e.g., .header, .item, .content)
Framework components already migrated:
rsx/theme/components/navigation/sidebar/sidebar_nav.*
rsx/theme/components/datagrid/datagrid_abstract.*
rsx/theme/components/datagrid/datagrid_body.*
rsx/theme/components/feedback/errors/php_exception_error_page_component.*
rsx/theme/components/feedback/errors/generic_error_page_component.*
rsx/theme/components/forms/pin_verification_form.*
rsx/theme/components/page/breadcrumb_nav.*
rsx/app/frontend/Frontend_Spa_Layout.*
rsx/app/frontend/frontend_spa_layout.scss
IDENTIFYING CANDIDATES FOR CONVERSION
Step 1: Search for generic class names in SCSS files
-------------------------------------------------------------------------
Look for SCSS files with nested class selectors that don't use &__ syntax:
grep -rn "^\s*\." rsx/app rsx/theme/components --include="*.scss" | \
grep -v "&__" | grep -v "&--" | grep -v "^\s*\.\$"
Common patterns to look for:
- .component-name .child-element { } (nested selector, not BEM)
- .my-component__element { } (kebab-case prefix instead of PascalCase)
- .generic-class-name { } (standalone classes that should be scoped)
Step 2: Find SCSS files with potential BEM candidates
-------------------------------------------------------------------------
Search for hyphenated class names that suggest component children:
grep -rE "\.[a-z]+-[a-z]+" rsx/app rsx/theme/components --include="*.scss" | \
grep -v "bootstrap" | grep -v "bi-" | grep -v "btn-" | grep -v "form-"
This finds classes like:
- .sidebar-brand, .nav-link, .page-content
- .error-icon, .loading-row, .empty-state
Step 3: Check corresponding jqhtml templates
-------------------------------------------------------------------------
For each SCSS file with candidates, check the matching jqhtml file:
# Example: if datagrid_abstract.scss has candidates
cat rsx/theme/components/datagrid/datagrid_abstract.jqhtml | \
grep -oE 'class="[^"]*"'
Step 4: Verify the component structure
-------------------------------------------------------------------------
A good candidate for BEM conversion has:
- A component root class (from <Define:Component_Name>)
- Child elements with generic or kebab-case class names
- Styles that only make sense within that component's context
CONVERSION PROCESS
1. Update SCSS to use BEM nesting
-------------------------------------------------------------------------
Convert nested selectors to use &__ syntax:
Before:
.My_Component {
.header { ... }
.item-list { ... }
.item { ... }
}
After:
.My_Component {
&__header { ... }
&__item-list { ... }
&__item { ... }
}
Or for flat selectors:
Before:
.My_Component {
// styles
}
.my-component__header {
// styles
}
After:
.My_Component {
// styles
&__header {
// styles
}
}
2. Update jqhtml template class names
-------------------------------------------------------------------------
Change class attributes to use the BEM naming:
Before:
<div class="header">...</div>
<ul class="item-list">...</ul>
<li class="item">...</li>
After:
<div class="My_Component__header">...</div>
<ul class="My_Component__item-list">...</ul>
<li class="My_Component__item">...</li>
3. Update JavaScript selectors
-------------------------------------------------------------------------
If the component has a .js file, update any jQuery selectors:
Before:
that.$.find('.header')
that.$.find('.item-list .item')
$element.addClass('loading')
After:
that.$.find('.My_Component__header')
that.$.find('.My_Component__item-list .My_Component__item')
$element.addClass('My_Component--loading')
4. Update dynamically generated class names
-------------------------------------------------------------------------
If JavaScript dynamically creates elements with classes:
Before:
$('<a>', { class: 'row-link', href: url })
After:
$('<a>', { class: 'DataGrid_Abstract__row-link', href: url })
COMMON PATTERNS
Generic Classes to Convert
-------------------------------------------------------------------------
These patterns commonly appear and should be converted:
.icon → Component_Name__icon
.header → Component_Name__header
.title → Component_Name__title
.subtitle → Component_Name__subtitle
.content → Component_Name__content
.body → Component_Name__body
.footer → Component_Name__footer
.item → Component_Name__item
.list → Component_Name__list
.message → Component_Name__message
.actions → Component_Name__actions
.loading → Component_Name__loading or Component_Name--loading
.empty → Component_Name__empty or Component_Name--empty
State Modifiers (use -- not __)
-------------------------------------------------------------------------
.active → Component_Name--active
.disabled → Component_Name--disabled
.loading → Component_Name--loading (if state, not container)
.expanded → Component_Name--expanded
.collapsed → Component_Name--collapsed
.error → Component_Name--error
.success → Component_Name--success
Layout Specific Classes
-------------------------------------------------------------------------
Layout components like Frontend_Spa_Layout typically have:
.app-sidebar → Layout_Name__sidebar
.app-content → Layout_Name__content
.app-header → Layout_Name__header
.page-content → Layout_Name__page-content
.sidebar-brand → Layout_Name__sidebar-brand
PRESERVING BOOTSTRAP CLASSES
Do NOT convert Bootstrap utility or component classes:
Keep as-is:
.btn, .btn-primary, .btn-sm
.form-control, .form-label
.d-flex, .d-none, .d-lg-block
.text-center, .text-muted
.mb-3, .py-5, .px-4
.card, .card-body, .card-header
.dropdown, .dropdown-menu, .dropdown-item
.navbar, .navbar-brand
.breadcrumb, .breadcrumb-item
Only convert custom classes that are component-specific.
CONFIGURATION
No configuration required.
The JQHTML-CLASS-01 code quality rule automatically detects:
- Component names that don't start with uppercase
- Redundant class attributes on Define tags
- BEM child classes using kebab-case or lowercase prefix
VERIFICATION
1. Run code quality check:
php artisan rsx:check
Any BEM naming violations will be reported with suggestions.
2. Search for unconverted patterns:
grep -rE "class=\"[^\"]*[a-z]+-[a-z]+__" rsx/app rsx/theme --include="*.jqhtml"
This finds remaining kebab-case__element patterns.
3. Compile bundles and check for SCSS errors:
php artisan rsx:bundle:compile Frontend_Bundle
4. Visually inspect pages to ensure styles still apply:
- Check components render correctly
- Verify hover states, active states work
- Test responsive behavior
EXAMPLE MIGRATION
Complete example: Converting Sidebar_Nav component
sidebar_nav.scss (before):
.Sidebar_Nav {
.nav-section { margin-bottom: 24px; }
.nav-section-title { font-size: 12px; }
.nav-link { padding: 12px 16px; }
.nav-submenu { padding-left: 32px; }
}
sidebar_nav.scss (after):
.Sidebar_Nav {
&__section { margin-bottom: $nav-section-margin; }
&__section-title { font-size: $font-size-xs; }
&__link { padding: $nav-link-padding; }
&__submenu { padding-left: $nav-submenu-indent; }
}
sidebar_nav.jqhtml (before):
<div class="nav-section">
<div class="nav-section-title"><%= section.title %></div>
<a href="..." class="nav-link">...</a>
<div class="nav-submenu">...</div>
</div>
sidebar_nav.jqhtml (after):
<div class="Sidebar_Nav__section">
<div class="Sidebar_Nav__section-title"><%= section.title %></div>
<a href="..." class="Sidebar_Nav__link">...</a>
<div class="Sidebar_Nav__submenu">...</div>
</div>
sidebar_nav.js (before):
that.$.find('.nav-link').on('click', ...)
$parent.find('.nav-submenu').slideDown()
sidebar_nav.js (after):
that.$.find('.Sidebar_Nav__link').on('click', ...)
$parent.find('.Sidebar_Nav__submenu').slideDown()
REFERENCE
rsx/theme/CLAUDE.md - SCSS guidelines including BEM
php artisan rsx:man scss - SCSS organization conventions
php artisan rsx:man jqhtml - Component template documentation