Skip to content

fix(element-ng): migrate internal list-group usages to element list - #2746

Open
kfenner wants to merge 1 commit into
kaspar-fenner-cards-with-listsfrom
kaspar-fenner-migrate-internal-list-group
Open

fix(element-ng): migrate internal list-group usages to element list#2746
kfenner wants to merge 1 commit into
kaspar-fenner-cards-with-listsfrom
kaspar-fenner-migrate-internal-list-group

Conversation

@kfenner

@kfenner kfenner commented Sep 8, 2026

Copy link
Copy Markdown
Member

Layer 3 of 3 — migrate remaining internal list-group usages

Top layer of the list-group deprecation stack. Base branch is kaspar-fenner-cards-with-lists (layer 2), not main.

This is not a class rename. .list-group-item is display: block; .list-item is a CSS grid with named slots (.list-item-title, .list-item-action, …) plus > * { grid-column: 3 / -1 }. Each component was restructured into those slots rather than having the class swapped.

Per-component changes

si-about (projects/element-ng/about/)

  • The single .list-group was doing two unrelated jobs. Split into:
    • a plain branding block <div class="about-branding"> (icon/image, heading, subheadings, copyright notice), styled directly in SCSS; and
    • a real list <ul class="list list-divider"> whose rows are the external links.
  • Each link row is now <li><a class="list-item list-item-action text-primary" …><span class="list-item-title">…</span></a></li>.
  • text-primary is kept intentionally: it carries a load-bearing !important that beats .list-item-action's color: inherit, so link colour is unchanged.
  • SCSS: .list-group-item (and a dead .with-border) replaced by .about-branding (padding + bottom border).
  • Spec: 3 assertions re-targeted from .list-group-item:first-of-type to .about-branding.

si-empty-state (projects/element-ng/empty-state/)

  • Pure private-class rename: root .list-group-item-empty.empty-state-content in both HTML and SCSS. It was never a real list row (single element, no list semantics). Zero visual change.

drag-drop example (src/app/examples/drag-drop/)

  • Both <ul class="list-group list-group-flush"><ul class="list list-divider">; items → <li class="list-item list-item-action"><span class="list-item-title">…</span></li>.
  • All cdkDrag / cdkListbox / cdkOption / cdkDropList / cdkContextMenu bindings and template refs preserved.

Descoped (report only — deliberately left on list-group)

The dashboard widget families do not map cleanly and would need a design-system decision, so per the "you're allowed to descope" instruction they are left untouched:

  • si-widget-catalog (projects/dashboards-ng/… — html/scss/spec)
  • si-list-widget-body / si-list-widget-item (projects/element-ng/dashboard/widgets/si-list-widget/…)
  • custom-widget-catalog (dashboards-demo/…)

Both gaps below are tracked in #2748 ("Element list: add selected state and preserve link colour on .list-item-action anchors"), framed as what blocks completing the list-group migration for these widgets.

Headline reason: the Element list has no selected / current-item state. These widgets rely on a highlighted "selected" row (catalog selection, active list item). .list-item only exposes &:active; there is no .active/selected equivalent, so a faithful migration would need a new design-system affordance rather than a markup change.

Secondary gap: .list-item-action on an <a> defaults to color: inherit, so link-coloured rows need an explicit colour class (as done for si-about via text-primary, whose load-bearing !important beats that inherit). Both are captured in #2748 as prerequisites before these widgets migrate.

Consumer-visible DOM change

This PR changes the rendered DOM of shipped components (si-about, si-empty-state), so it is typed fix (not refactorrefactor is hidden in commit-config.js and would produce no release/changelog entry). The commit carries a NOTE: footer telling consumers to re-target any custom CSS/tests from .list-group-item to the new markup (ul.list.list-divider > li > a.list-item.list-item-action for si-about links; .about-branding for the branding block; .empty-state-content for si-empty-state). Public inputs/outputs are unchanged, so this is not typed BREAKING CHANGE.

Accessibility

Layer 2's card focus-ring bug (item background painting over the inset focus ring) was checked here and does not occur: in every migrated list the focusable element owns its own background (the <a> in si-about, the <li> in drag-drop), so its inset outline paints above it. Verified visually — focus ring unbroken at rest and with the first row hovered. No local z-index fix needed.

VRT snapshots

Docker was unavailable in this environment, so VRT snapshots could not be regenerated. si-about renders differently and its snapshots will need updating:

  • projects/element-ng/…/playwright/snapshots/si-about.spec.ts-snapshots/* (light + dark)
  • static examples si-about--si-about-api*, si-about--si-about-text*

si-empty-state (private class rename) and drag-drop are not expected to change visually. Please regenerate si-about snapshots with ./e2e-local.sh update si-about on a Docker-capable machine before merge.

Verification run (mirrors CI verification job)

  • npx prettier --check on all touched files — clean.
  • pnpm run lint:scss — pass.
  • ng lint element-ng + ng lint element-examples — pass (full lint:ng OOMs on unrelated dashboards-demo-mfe, a pre-existing env issue).
  • Unit tests: si-about + si-empty-state specs — 11/11 pass.

Replace the deprecated Bootstrap-derived list group (.list-group /
.list-group-item) with the Element list (.list / .list-item) in the
si-about and si-empty-state library components and in the drag-drop
example. Final layer of the list-group deprecation stack (#2742, #2745).

This re-renders the internal DOM of these shipped components. In
si-about the link rows are now `ul.list.list-divider > li >
a.list-item.list-item-action` and the branding block (icon, app name,
subheadings, copyright) is a plain card block rather than a list row.
si-empty-state's private wrapper class `.list-group-item-empty` is
renamed to `.empty-state-content`. Public component inputs and outputs
are unchanged.

Typed `fix` rather than `refactor` on design drift: the deprecated
list-group CSS no longer receives design-system updates, so components
left on it diverge visually over time. `refactor` is also hidden from
the changelog and triggers no release, so consumers would never see
this note.

NOTE: The internal markup of si-about and si-empty-state changed. Consumers with custom CSS or tests targeting `.list-group-item` inside these components must re-target: si-about link rows are now `ul.list.list-divider > li > a.list-item.list-item-action` (the branding area is now a plain card block, not a list row), and si-empty-state's wrapper element is `.empty-state-content`. Public inputs and outputs are unchanged.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
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