Skip to content

feat: create reusable Hero component#4215

Open
DavideIadeluca wants to merge 11 commits intoflarum:2.xfrom
glowingblue:di/reusable-hero-component
Open

feat: create reusable Hero component#4215
DavideIadeluca wants to merge 11 commits intoflarum:2.xfrom
glowingblue:di/reusable-hero-component

Conversation

@DavideIadeluca
Copy link
Contributor

@DavideIadeluca DavideIadeluca commented May 21, 2025

Fixes #4202

Changes proposed in this pull request:

  • Create new reusable hero component to streamline the implementation of each variation

Reviewers should focus on:

  • Tried to keep the core abstract implementation as lightweight as possible
  • Perhaps some methods or the new class itself could be named better
  • Does this change need to be documented?
  • Are there any other Hero implementations i've missed?

Screenshot
DOM / UI should stay the same

Necessity

  • Has the problem that is being solved here been clearly explained?
  • If applicable, have various options for solving this problem been considered?
  • For core PRs, does this need to be in core, or could it be in an extension?
  • Are we willing to maintain this for years / potentially forever?

Confirmed

  • Frontend changes: tested on a local Flarum installation.
  • Backend changes: tests are green (run composer test).
  • Core developer confirmed locally this works as intended.
  • Tests have been added, or are not appropriate here.

Required changes:

  • Related documentation PR: (Remove if irrelevant)

@DavideIadeluca DavideIadeluca marked this pull request as ready for review May 22, 2025 09:12
@DavideIadeluca DavideIadeluca requested a review from a team as a code owner May 22, 2025 09:12
@imorland imorland changed the title feat: create reusable Hero component [2.x] feat: create reusable Hero component Nov 2, 2025
@DavideIadeluca DavideIadeluca changed the title [2.x] feat: create reusable Hero component feat(core, tags): create reusable Hero component Nov 8, 2025
@DavideIadeluca DavideIadeluca changed the title feat(core, tags): create reusable Hero component feat: create reusable Hero component Nov 8, 2025
@DavideIadeluca
Copy link
Contributor Author

FYI @imorland I just made a minor change I've had in mind. This PR is now good to go from my side

@imorland imorland added this to the 2.0.0-beta.4 milestone Nov 9, 2025
@imorland imorland modified the milestones: 2.0.0-beta.4, 2.0.0-beta.5 Nov 24, 2025
@imorland imorland modified the milestones: 2.0.0-beta.5, 2.0.0-beta.6 Dec 20, 2025
@imorland imorland modified the milestones: 2.0.0-beta.6, 2.0.0-beta.7 Jan 24, 2026
Copy link
Member

@imorland imorland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this — the design is solid and consistent with the existing Modal pattern. This PR has been open for a while but I checked: the Laravel upgrade, LESS 5.x upgrade, and webpack changes that landed since opening do not affect any of this, so it is not stale. A few things to address before merge.

Summary of required changes:

  • Add import './components/Hero' to forum.ts — explicit registration is the established convention and important for discoverability as a first-class extension point
  • Add JSDoc to viewItems() — it is the primary structural extension point but has no documentation
  • Remove ?? undefined from style={} in Hero.view() — redundant since style() already returns undefined, not null
  • Fix Hero.view() return type from Mithril.Vnode | null to JSX.Element — the base never returns null
  • Document the viewItems()bodyItems() rename as a breaking change in the PR description and upgrade guide
  • Add a note about UserPage's UserHero (via UserCard) being intentionally excluded

Also worth considering:

  • The TagHero.className() approach of returning a space-separated string passed to classList() works with clsx 1.x but would silently break on a future upgrade to clsx 2.x, which does not split strings. See inline comment.
  • Tests: the checklist item is unchecked. Snapshot/render tests confirming HTML structure is preserved would be valuable given the inheritance chain changes.


export interface IWelcomeHeroAttrs {}
export interface IWelcomeHeroAttrs extends IHeroAttrs {}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Breaking change notice needed. The current published dist-typings/forum/components/WelcomeHero.d.ts exposes viewItems() as a public method. Any third-party extension using extend(WelcomeHero.prototype, 'viewItems', ...) will silently stop firing after this rename.

Same applies to TagHero — its dist-typings also expose viewItems().

For a 2.x pre-release this is acceptable, but please:

  1. Add an explicit note to the PR description calling this out
  2. Ensure it is captured in the upgrade guide

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

viewItems() is moved to the abstract class and can technically continue to be consumed the same way. In the grand scheme of things, this is a minuscule, non breaking change. Created a documentation PR for this anyways at flarum/docs#500


import type Mithril from 'mithril';

export interface IMessagesPageHeroAttrs extends IHeroAttrs {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty interface extending another is fine for extensibility, but a brief comment would help clarify the intent to readers:

// Intentionally empty — extend this interface to add attrs for extensions.
export interface IMessagesPageHeroAttrs extends IHeroAttrs {}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's pretty common across the codebase to have empty interfaces like this — none of which have comments like this. If you would like we can follow up in a separate PR to streamline & create JSDoc's for interfaces

@imorland imorland modified the milestones: 2.0.0-beta.7, 2.0.0-beta.8 Feb 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create Reusable Hero Component

2 participants