Skip to content

BEM Refactor - #75

Merged
thomasgallagher merged 11 commits into
mainfrom
badge-bem-base-class
May 10, 2026
Merged

BEM Refactor#75
thomasgallagher merged 11 commits into
mainfrom
badge-bem-base-class

Conversation

@thomasgallagher

Copy link
Copy Markdown
Collaborator

No description provided.

Modifiers no longer re-apply shared badge styles; markup must combine
.l-ui-badge with a colour/shape modifier, matching strict BEM.
Following audits/bem/2026-05-10:

- Rename `l-ui-page--{vertically-centered,width-constrained}` to
  `__vertically-centered`/`__width-constrained` (used as inner elements
  of the page block, not modifiers).
- Rename `l-ui-label--checkbox` to `l-ui-checkbox-container__label`
  (semantically a child of checkbox-container, not a label variant).
- Rename `l-ui-stream-fade-word` to `l-ui-stream-fade__word`.
- Rename `l-ui-select-wrapper` to `l-ui-select-container` for
  consistency with other `*-container` classes.
- Promote `l-ui-table__action` to a real element so `--danger` has a
  real base; descendant fallback retained for backwards compatibility.
- Add `l-ui-tabs` block class so `__list`/`__tab`/`__panel` have a parent.
- Replace runtime state classes `.open` and `.hidden` (which collided
  with Tailwind's `.hidden` utility) with namespaced BEM modifiers:
  `--open` for navigation/backdrop/panel containers and `--hidden`
  for the panel button. Stimulus controllers updated to toggle the
  new class names.
- Add base classes alongside `l-ui-form__group--large-gap` and
  `l-ui-message--sent` in markup so modifiers are paired with their base.
- Document migration in UPGRADING.md.
Following audits/bem/2026-05-10 (Codex), the public surface had four
classes that were emitted or documented without matching CSS rules.

- Promote `l-ui-checkbox`: replace the descendant selector
  `.l-ui-checkbox-container input[type="checkbox"]` with an explicit
  `.l-ui-checkbox` rule. Add the class to bare checkbox markup in
  devise/sessions and dummy form examples.
- Document `l-ui-navigation__section--collapsible` and
  `l-ui-table__header-cell--sortable` in CSS.md as marker classes
  (no engine styles; host-app/JS hooks).
- Remove `l-ui-text--subtle` from the dummy posts/_title_cell partial
  and replace with Tailwind utilities; the class had no engine CSS
  and was used only in this one demo.

UPGRADING.md updated.
The `--panel-close` modifier named another block (`panel`) inside the
button namespace. The styling (a panel-flush negative margin) is
panel-specific positioning, so promote it to a panel element class.
Markup composes with the button block:
`class="l-ui-button l-ui-button--icon l-ui-panel__close-button"`.
Address reviewer feedback: badge had been simplified to a plain
.l-ui-badge class while seven other components (label, page,
navigation__item, button, surface, tabs__tab, table-cell-padding)
kept the @Utility foo { ... } + .l-ui-foo { @apply foo; } pattern
despite being applied in only one place each. The indirection earns
its keep only when @Utility is reused; for one consumer it is just
an alias.

Inline each single-use @Utility into its consumer class. Retain
@Utility for entries with real reuse: focus-ring (composition
primitive), heading (markdown headings), notice (base + form
errors), form__field (field + composer input), and the pagination
family (base + Pagy series-nav).
- Add `l-ui-page--with-navigation` to the search-and-replace table
  (was only mentioned in prose).
- Extend the offender-finder grep regex to include `form__group` and
  `message`, matching the modifiers listed in the migration table.
- Move `l-ui-button--panel-close` out of the prepend-base table into
  the Renamed Classes table only - it's a rename, not a base prepend.
Skill docs and one dummy code sample still referenced the
pre-cleanup BEM names or used modifiers without their base:

- SKILL.md: rename `--vertically-centered`/`--width-constrained`
  to the new `__` element form, replace the phantom
  `l-ui-surface--active` with the real modifiers, and add the
  `l-ui-tabs` block to the tabs row.
- CONTROLLERS.md: add `l-ui-button` base to the modal close
  button example; add the `l-ui-tabs` block class to the tabs
  example.
- HELPERS.md: add `l-ui-button` base to two example snippets
  using `l-ui-button--primary`.
- dummy tabs.html.erb: the escaped code sample inside the View
  Code modal still showed `<div data-controller="l-ui--tabs">`
  without the new `l-ui-tabs` class; now matches the live demo.
Active tab lost all base styling because the controller toggled the base
class off when applying --active; now that --active is a true modifier
the base class must stay. _field_input also dropped the engine-supplied
class whenever a config passed extras[:class], leaving inputs unstyled
under strict BEM.

Merge extras[:class] with the engine base via token_list so string,
array, and conditional-hash class values all flow through, and pass it
to hidden fields too.
- Drop the `[class*="l-ui-button--"]:disabled` substring selector; rely on
  `.l-ui-button:disabled` now that the base class is mandatory.
- Class-first action cell: remove the `& button, & a` descendant rule from
  `.l-ui-table__cell--action`. `l-ui-table__action` is now required on every
  action element. Updated the helper docstring, dummy docs, and UPGRADING.md
  note (no longer "retained for backwards compatibility").
- Rename pagination `@utility` shims to neutral hyphenated names
  (`pagination-base`, `pagination-item`, `pagination-item-active`,
  `pagination-item-disabled`, `pagination-gap`) so they no longer read as
  un-namespaced BEM classes; added a header comment explaining they are
  mixin-only helpers shared with the pagy adapter rules.
- Document the `*-container` shell convention and the bare-link
  `:not([class*="l-ui-"])` rule in CSS.md so future contributors do not
  "fix" them into BEM elements.
@thomasgallagher
thomasgallagher merged commit d644a63 into main May 10, 2026
8 checks passed
@claude

claude Bot commented May 10, 2026

Copy link
Copy Markdown

Review

Project-wide BEM tightening: every component modifier is now a true delta (no longer re-applies base styles via @apply), unprefixed runtime state classes (.open, .hidden) are replaced with namespaced BEM modifiers, several misclassified modifiers are renamed to elements or moved to the correct block, and a comprehensive UPGRADING.md is added.

No issues found.

Ship - The refactor is internally consistent, all engine views and helpers have been updated in lock-step, the JS controllers match the new CSS selectors, and the migration path is clearly documented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant