Skip to content

[73968, 73089] Extend and improve design of WorkPackageCardComponent#23175

Open
HDinger wants to merge 1 commit into
devfrom
feature/73089-restyled-work-package-card-in-backlogs-and-sprints-view
Open

[73968, 73089] Extend and improve design of WorkPackageCardComponent#23175
HDinger wants to merge 1 commit into
devfrom
feature/73089-restyled-work-package-card-in-backlogs-and-sprints-view

Conversation

@HDinger
Copy link
Copy Markdown
Contributor

@HDinger HDinger commented May 12, 2026

Ticket

https://community.openproject.org/wp/73968
https://community.openproject.org/wp/73089

What are you trying to accomplish?

Layout & Structure

  • Card uses a consistent 3-row layout: metadata row, subject row, optional footer row
    • Footer row is only rendered when it has content (parent link or bottom line slot)
    • Drag handle became optional

Metadata Row (Row 1)

  • Always shows: type, work package ID, status, and actions menu
  • Optional: assignee avatar + name (show_assignee)
  • Optional: priority badge (show_priority)
  • Optional: numeric metric e.g. story points (with_metric slot)
  • Optional: custom actions menu replacing the default (with_menu slot)

Status Display

  • Default scheme renders status as a color-highlighted badge
  • Secondary scheme renders status as a neutral label

Footer Row (Row 3)

  • Optional link to the parent work package (show_parent_link) - only rendered when a parent exists
  • Optional arbitrary content via with_bottom_line slot (e.g. time tracking, custom metadata)
  • Both can coexist in the same footer row

Lookbook Documentation

  • Documentation page and previews added

Mobile behaviour

  • The card reacts to different container sizes
    • Priority and assignee hide their text labels

Screenshots

Bildschirmfoto 2026-05-12 um 15 11 56

@HDinger HDinger added this to the 17.5.x milestone May 12, 2026
@HDinger HDinger force-pushed the feature/73089-restyled-work-package-card-in-backlogs-and-sprints-view branch from 25d8a87 to add05fb Compare May 13, 2026 06:48
@HDinger HDinger force-pushed the feature/73089-restyled-work-package-card-in-backlogs-and-sprints-view branch from add05fb to 91de331 Compare May 13, 2026 06:51
@HDinger HDinger marked this pull request as ready for review May 13, 2026 06:55
@HDinger HDinger changed the title [73968, 73089] Extend and improve desing of WorkPackageCardComponent [73968, 73089] Extend and improve design of WorkPackageCardComponent May 13, 2026
@myabc myabc requested review from Copilot and myabc May 16, 2026 15:41
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR extends the shared work package card component with richer metadata, footer support, status styling variants, and Lookbook documentation/previews, then applies the enhanced card presentation to Backlogs.

Changes:

  • Adds card options for assignee, priority, drag handle, parent footer link, bottom-line slot, custom metric/menu placement, and status scheme.
  • Updates Backlogs to render the enhanced card with assignee, priority, parent link, and secondary status style.
  • Adds Lookbook documentation/previews and supporting locale/style updates.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
app/components/open_project/common/work_package_card_component.rb Adds new card options and bottom-line slot.
app/components/open_project/common/work_package_card_component.html.erb Renders the new metadata/action/footer layout.
app/components/open_project/common/work_package_card_component.sass Updates grid layout, responsive behavior, and action/footer styling.
app/components/open_project/common/work_package_card_component/menu.html.erb Makes the menu button small.
app/components/work_packages/info_line_component.rb Adds a status scheme option.
app/components/work_packages/info_line_component.html.erb Passes the status scheme to the status badge.
app/components/work_packages/status_badge_component.rb Adjusts highlight-class behavior when a Primer label scheme is provided.
modules/backlogs/app/components/backlogs/work_package_card_component.rb Enables enhanced card metadata/footer options for Backlogs.
frontend/src/global_styles/layout/_colors.sass Adds a small inline highlight dot variant.
config/locales/en.yml Adds card labels for drag handle and parent.
lookbook/docs/components/work-packages/card.md.erb Adds WorkPackageCard documentation.
lookbook/previews/open_project/common/work_package_card_component_preview.rb Adds and updates component previews.
lookbook/previews/open_project/common/work_package_card_component_preview/playground.html.erb Adds interactive playground rendering.
lookbook/previews/open_project/common/work_package_card_component_preview/with_bottom_line.html.erb Adds bottom-line slot preview rendering.

if @show_status
flex.with_column(ml: 2) do
render WorkPackages::StatusBadgeComponent.new(status: @work_package.status)
render WorkPackages::StatusBadgeComponent.new(status: @work_package.status, scheme: @status_scheme)
Comment on lines +91 to +101
<% if show_parent_link && work_package.parent.present? %>
<% flex.with_row do %>
<%= render(
Primer::Beta::Link.new(
href: work_package_path(work_package.parent),
underline: false,
color: :default
)
) do %>
<%= render(Primer::Beta::Text.new(color: :subtle)) { "#{t('.parent')}: " } %>
<%= work_package.parent.subject %>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

True (I think).. I missed this one.

Comment on lines +60 to +62
show_assignee: true,
show_priority: true,
show_parent_link: true,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We will need to discuss implications in Agile stream - @ulferts and @dombesz have been particularly diligent about avoiding n+1 queries.

) do |grid| %>
<% if show_drag_handle %>
<% grid.with_area(:drag_handle) do %>
<%= render(Primer::Beta::Octicon.new(icon: :grabber, "aria-label": t(".drag_handle.label"))) %>
Copy link
Copy Markdown
Contributor

@myabc myabc May 16, 2026

Choose a reason for hiding this comment

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

⚠️ Why not use Primer::OpenProject::DragHandle?

This was what was used prior to prior to #22838 being merged (e.g. here)


<% grid.with_area(:subject) do %>
<%= render(Primer::Beta::Text.new(font_weight: :semibold)) { work_package.subject } %>
<%= render(Primer::Beta::Link.new(href: work_package_path(work_package), font_weight: :semibold)) { work_package.subject } %>
Copy link
Copy Markdown
Contributor

@myabc myabc May 16, 2026

Choose a reason for hiding this comment

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

Can this link be optional?

I'm not sure what is specified, but for the Backlogs use case (i.e. where the whole card is draggable), I would not want to make the subject a link.

Copy link
Copy Markdown
Contributor

@myabc myabc left a comment

Choose a reason for hiding this comment

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

This looks good overall. It's definitely a massive improvement on the Backlogs page. 💯

I've left lots of comments in line. Most important things IMO to address before merging:

  • menu sizes
  • CSS and slot naming: I'm still working on better suggestions. additional_details might be better than bottom_line however.
  • making subject linking optional

"Nice to haves" would be:

  • a PriorityBadgeComponent rather than inline styling.
  • Lookbook or Yarddocs for InfoLineComponent itself.

<% end %>
<% end %>

<% grid.with_area(:menu) do %>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

To make the as intutitve as possible, I'd like to keep to try to keep the slot names aligned with BorderBoxComponent (#23074). There we have a separate actions and menu slot. If we conflate them, we should do so in both components.

That said, I quite like keeping the menu separate. #23218 now hides the menu slot before generating a drag preview (using a hidden-for-drag-preview class).

hide-when-print might also make sense here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I realise now that was mixing up slot naming and grid area naming. 🤦🏻 .. However, we should probably still try to keep things aligned if possible.

}
) do |grid| %>
<% if show_drag_handle %>
<% grid.with_area(:drag_handle) do %>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
<% grid.with_area(:drag_handle) do %>
<% grid.with_area(:drag_handle, classes: "hide-when-print") do %>

show_project: false,
show_subject: false,
show_status: true,
status_scheme: :default,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Won't this break existing callers? We should document this option on InfoLineComponent too.

"aria-label": button_aria_label || t(".label_actions"),
tooltip_direction: :se
tooltip_direction: :se,
size: :small
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not against doing this in principle, but this will break alignment with BorderBoxListComponent headers.. so we should discuss and/or allow callers to customise size.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Image

Comment on lines +91 to +101
<% if show_parent_link && work_package.parent.present? %>
<% flex.with_row do %>
<%= render(
Primer::Beta::Link.new(
href: work_package_path(work_package.parent),
underline: false,
color: :default
)
) do %>
<%= render(Primer::Beta::Text.new(color: :subtle)) { "#{t('.parent')}: " } %>
<%= work_package.parent.subject %>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

True (I think).. I missed this one.

Comment on lines +60 to +62
show_assignee: true,
show_priority: true,
show_parent_link: true,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We will need to discuss implications in Agile stream - @ulferts and @dombesz have been particularly diligent about avoiding n+1 queries.

Comment on lines +93 to +102
<%= render(
Primer::Beta::Link.new(
href: work_package_path(work_package.parent),
underline: false,
color: :default
)
) do %>
<%= render(Primer::Beta::Text.new(color: :subtle)) { "#{t('.parent')}: " } %>
<%= work_package.parent.subject %>
<% end %>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  1. The font size should be :small / 14px here.
  2. The "Parent: " label should be "muted" colour.
  3. I personally think it looks better if we don't link the "Parent: " label.
Suggested change
<%= render(
Primer::Beta::Link.new(
href: work_package_path(work_package.parent),
underline: false,
color: :default
)
) do %>
<%= render(Primer::Beta::Text.new(color: :subtle)) { "#{t('.parent')}: " } %>
<%= work_package.parent.subject %>
<% end %>
<%= render(Primer::Beta::Text.new(color: :muted, font_size: :small)) do %>
<%= t('.parent') %>
<%= render(
Primer::Beta::Link.new(
href: work_package_path(work_package.parent),
underline: false,
color: :default
)
) do %>
<%= work_package.parent.subject %>
<% end %>
<% end %>

e.g.

Image

Comment on lines +57 to +58
# @param show_parent_link [Boolean] whether to show a link to the parent work package in row 3.
# Only rendered when the work package actually has a parent.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nitpick: could shorten this parameter to just show_parent (but I don't feel strongly about this either).

Comment on lines +89 to +90
.op-work-package-card--actions .__hl_inline__small_dot
font-size: 0
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hmm, I don't like this. I'm not 100% sure of what implications are for accessibility, etc. but it feels "hacky". Without a supporting comment it's unclear to other devs what tis code is meant to be do..

Can we not just apply an explicit class for priority-name and use the same mechanism for hiding as op-work-package-card--assignee-name.

Suggested change
.op-work-package-card--actions .__hl_inline__small_dot
font-size: 0
.op-work-package-card--priority-name
display: none

or - for better accessibility support (/cc @bsatarnejad):

Suggested change
.op-work-package-card--actions .__hl_inline__small_dot
font-size: 0
.op-work-package-card--priority-name
@extend .sr-only

(if you do do the latter though, you'll need to make the parent container position: relative to avoid being bitten by the same issue as in #23143)

tag: :article,
classes: { "op-work-package-card_with-metric": metric? }
classes: {
"op-work-package-card_with-drag-handle": show_drag_handle,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nitpick: you can alias these methods as predicate in WorkPackageCardComponent:

Suggested change
"op-work-package-card_with-drag-handle": show_drag_handle,
"op-work-package-card_with-drag-handle": show_drag_handle?,
alias_method :show_drag_handle?, show_drag_handle

Example here

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

Labels

Development

Successfully merging this pull request may close these issues.

3 participants