Content
View differences
Updated by Alexander Coles 12 days ago
## Summary
Migrates Migrate list-shaped `Primer::Beta::BorderBox` / `border_box_container` usages to `OpenProject::Common::BorderBoxListComponent`, and extend the shared `OpenProject::Common::BorderBoxListComponent`. Shipped component API where the remaining migrations needed legitimate header flexibility.
Implementation was drafted in the monolithic PR https://github.com/opf/openproject/pull/23812 (closed, superseded) and now ships as a stacked PR train, one child each slice paired with its own implementation child: #DREAM-801 shared header API (https://github.com/opf/openproject/pull/24643), #DREAM-802 phase definitions + export templates — gates #DREAM-789 (https://github.com/opf/openproject/pull/24644), #DREAM-803 wiki, OAuth and project settings lists (https://github.com/opf/openproject/pull/24645), and #DREAM-804 meetings, costs and work package per slice: #DREAM-801 (shared API), <mention class="mention" data-id="78249" data-type="work_package" data-text="#DREAM-802" data-display-id="DREAM-802">#DREAM-802</mention> , <mention class="mention" data-id="78250" data-type="work_package" data-text="#DREAM-803" data-display-id="DREAM-803">#DREAM-803</mention> , <mention class="mention" data-id="78251" data-type="work_package" data-text="#DREAM-804" data-display-id="DREAM-804">#DREAM-804</mention> . tab lists (https://github.com/opf/openproject/pull/24646).
The label-action deprecation drafted in the monolith was dropped: #DREAM-780 superseded it with the standalone status-label slot, which the stack builds on.
## Implemented so far
### Shared component API changes
All exist solely to let the remaining consumers migrate — nothing more:
* - Added `header.with_title` — for linked or composed title content while still rendering inside the configured heading element.
*
- Added `header.with_action_icon_button` — for icon-only header actions.
* Header/row
- Reworked header/row menus via `BorderBoxListComponent::Menu` — through `BorderBoxListComponent::Menu`, keeping the default kebab trigger automatic kebab trigger, customisable via while allowing `button_arguments:` or a caller-provided `menu.with_show_button`.
* `empty_state_behavior:` policy — `:static` (default) renders the declared or generic blankslate only while a list is empty; `:none` suppresses it (grouped surfaces); `:dynamic` shows it client-side
- Added default empty-state rendering for itemless lists when filtering or drag-and-drop empties callers do not provide a list.
* Headers keep a stable height when filtering hides their action buttons.
## Screens updated (in merge order) custom `with_empty_state` slot.
- Updated Lookbook docs, previews, preview specs, and component specs for the new public API.
* #DREAM-802: project ### Migrated consumers
Distributed across the stack: #DREAM-802 carries the phase definitions (admin), PDF and export templates (type settings).
* #DREAM-803: wiki page links (work package tab), portfolios, OAuth applications (admin), template lists; #DREAM-803 the wiki, portfolio, OAuth, life-cycle, project life cycle settings, project attributes settings (+ creation wizard), My account notifications.
* #DREAM-804: work package meetings tab, departments (admin), work package and notifications surfaces; #DREAM-804 the meetings, costs, departments, relations tab, meeting participants, cost types settings, tab and resource allocations.
* Landed allocation surfaces.
- `Wikis::CollapsiblePageLinksComponent`
- `Wikis::RelationPageLinksComponent`
- `Portfolios::IndexComponent`
- `OAuth::Applications::IndexComponent`
- `Settings::ProjectPhaseDefinitions::IndexComponent`
- `Projects::Settings::LifeCycle::IndexComponent`
- `Projects::Settings::ProjectCustomFieldSections::ShowComponent`
- `Projects::Settings::CreationWizard::ProjectCustomFieldSections::ShowComponent`
- `Workflows::TypeListComponent`, renamed from `Workflows::TableComponent` (landed on dev independently)
- `WorkPackageTypes::ExportTemplateListComponent`
- `My::Notifications::ShowPageComponent`
- `WorkPackageMeetingsTab::MeetingComponent`
- `Admin::Departments::DetailComponent`
- `WorkPackageRelationsTab::IndexComponent`
- `Admin::Enumerations::IndexComponent` (landed on dev independently earlier: enumerations (admin), workflows type list.
via the #DREAM-688 line)
- `Meetings::Participants::ListComponent`
- `Projects::Settings::CostTypes::IndexComponent`
- `ResourceAllocations::ListComponent`
Existing Backlogs bucket/sprint menu callers were also updated to the new `button_arguments:` API.
## Hints Review and commit structure
The stack is ordered for QA
* Migrated screens should look unchanged apart linear review: the shared API slice first, then one consumer batch per PR. Each consumer migration is a focused vertical-slice commit with its component spec, and the API slice separates the header/menu rework from consistent header/menu styling the default empty state so both can be evaluated independently. Every `[DREAM-697]` commit has a one-line detail and links back to this work package.
## Verification
- Component and preview specs pass per slice: #DREAM-801 96 examples, #DREAM-802 26, #DREAM-803 56, #DREAM-804 59 — 0 failures each.
- `bin/dirty-rubocop` and `erb_lint` clean on each slice's changed files.
- The export-template drag/toggle feature spec runs in CI on the empty-state behavior below.
* Filtering #DREAM-802 slice.
## Remaining migration candidates
Triaged by row shape. Gating rule: rows with multiple data columns belong on a list to future BorderBoxTable / DataTable, not BorderBoxListComponent; rich headers (multiple menus plus a dialog) are out of scope until handled separately, with no matches (Project attributes, Project life cycle settings, admin phase definitions) shows header-API extension.
### Still a blankslate inside the box — BorderBoxList candidate
| Component | Features | Notes |
|---|---|---|
| `MeetingAgendaItems::ListComponent` | new-item form, no header | Lowest fit; not yet done. |
### Reclassified to BorderBoxTable (multiple data columns)
| Component | Notes |
|---|---|
| `Documents::Admin::DocumentTypes::IndexComponent` | name / type / updated columns. PR https://github.com/opf/openproject/pull/23485 (#DREAM-688, closed unmerged) previously covered it. |
| `Storages::Admin::StorageListComponent` | name / creator / provider / time columns. |
| `Wikis::Admin::WikiProviderListComponent` | name / provider / time columns. |
| `Documents::ListComponent` | name / type / updated columns. |
### Deferred -- rich header / invasive (no header-API extension)
| Component | Notes |
|---|---|
| `Settings::ProjectCustomFieldSections::ShowComponent` | Admin section header has a bare box or drag handle, a floating "No items found" line.
* Administration → Work packages → Types: type groups without variants no longer show single-select position menu, a blankslate row per group.
* Headers with "Enable all / Disable all"-style kebab actions keep their height while filtering hides menu, and an edit dialog -- beyond the actions.
* Backlogs sprint/backlog lists still show their drop-target blankslate immediately when list header slot. Not a clone of the last card is dragged out.
migrated `Projects::Settings::ProjectCustomFieldSections::ShowComponent` twin (which has only a title and two action buttons). |
| `WorkPackageTypes::FormConfiguration::GroupComponent` | Nested group + attribute drag, group-level kebab menu and drag handle. |
| `MeetingSections::ShowComponent` | Nested drag targets; pending API / behaviour review. |
## Remaining and out Out of scope (not list-shaped)
* `MeetingAgendaItems::ListComponent` Detail / single boxes: activities journal `ItemComponent` and `RevisionComponent`. Wizards / accordions: SAML and OpenID Connect provider views, Storages `StorageViewComponent`, Wikis `WikiProviderViewComponent`, Jira import wizard. Other: date-picker dialog, creation-wizard blank slate, manage-shares (dynamic JS rows), custom-field hierarchy items (tree), filter form, health-reports dashboard.
### Coordination with DREAM-671
#DREAM-786 is merged, so the only remaining BorderBoxList candidate.
* Multi-column lists (document types, storages, wiki providers, documents) wait for a future BorderBoxTable/DataTable.
* Rich-header surfaces (admin project attributes sections, #DREAM-671 dependency on this effort is #DREAM-789, which follows #DREAM-802 (the phase definitions and export template markup it builds on). The former parent-level Blocks relation was replaced by that precise Follows relation.
The rich-header admin Project attributes, form-configuration groups, group, and meeting sections) belong to section components remain outside #DREAM-697's scope. Their markup and DnD contract are handled inside the corresponding #DREAM-671 migration line — no further header-API growth cluster; they must not drive another broad BorderBoxList header API expansion here.
* #DREAM-789 follows #DREAM-802 (the only remaining #DREAM-671 dependency on this effort).
Migrates
Implementation was drafted in the monolithic PR https://github.com/opf/openproject/pull/23812 (closed, superseded) and now ships
### Shared component
All exist solely to let the remaining consumers migrate — nothing more:
*
*
- Added
* Header/row
- Reworked header/row
* `empty_state_behavior:` policy — `:static` (default) renders the declared or generic blankslate only while a list is empty; `:none` suppresses it (grouped surfaces); `:dynamic` shows it client-side
- Added default empty-state rendering for itemless lists
* Headers keep a stable height when filtering hides their action buttons.
## Screens updated (in merge order)
- Updated Lookbook docs, previews, preview specs, and component specs for the new public API.
* #DREAM-802: project
Distributed across the stack: #DREAM-802 carries the
* #DREAM-803: wiki page links (work package tab), portfolios, OAuth applications (admin),
* #DREAM-804: work package meetings tab, departments (admin), work package
* Landed
- `Wikis::CollapsiblePageLinksComponent`
- `Wikis::RelationPageLinksComponent`
- `Portfolios::IndexComponent`
- `OAuth::Applications::IndexComponent`
- `Settings::ProjectPhaseDefinitions::IndexComponent`
- `Projects::Settings::LifeCycle::IndexComponent`
- `Projects::Settings::ProjectCustomFieldSections::ShowComponent`
- `Projects::Settings::CreationWizard::ProjectCustomFieldSections::ShowComponent`
- `Workflows::TypeListComponent`, renamed from `Workflows::TableComponent` (landed on dev independently)
- `WorkPackageTypes::ExportTemplateListComponent`
- `My::Notifications::ShowPageComponent`
- `WorkPackageMeetingsTab::MeetingComponent`
- `Admin::Departments::DetailComponent`
- `WorkPackageRelationsTab::IndexComponent`
- `Admin::Enumerations::IndexComponent` (landed on dev
- `Meetings::Participants::ListComponent`
- `Projects::Settings::CostTypes::IndexComponent`
- `ResourceAllocations::ListComponent`
Existing Backlogs bucket/sprint menu callers were also updated to the new `button_arguments:` API.
The stack is ordered
* Migrated screens should look unchanged apart
## Verification
- Component and preview specs pass per slice: #DREAM-801 96 examples, #DREAM-802 26, #DREAM-803 56, #DREAM-804 59 — 0 failures each.
- `bin/dirty-rubocop` and `erb_lint` clean on each slice's changed files.
- The export-template drag/toggle feature spec runs in CI on
* Filtering
## Remaining migration candidates
Triaged by row shape. Gating rule: rows with multiple data columns belong on
### Still
| Component | Features | Notes |
|---|---|---|
| `MeetingAgendaItems::ListComponent` | new-item form, no header | Lowest fit; not yet done. |
### Reclassified to BorderBoxTable (multiple data columns)
| Component | Notes |
|---|---|
| `Documents::Admin::DocumentTypes::IndexComponent` | name / type / updated columns. PR https://github.com/opf/openproject/pull/23485 (#DREAM-688, closed unmerged)
| `Storages::Admin::StorageListComponent` | name / creator / provider / time columns. |
| `Wikis::Admin::WikiProviderListComponent` | name / provider / time columns. |
| `Documents::ListComponent` | name / type / updated columns. |
### Deferred -- rich header / invasive (no header-API extension)
| Component | Notes |
|---|---|
| `Settings::ProjectCustomFieldSections::ShowComponent` | Admin section header has
* Administration → Work packages → Types: type groups without variants no longer show
* Headers with "Enable all / Disable all"-style
* Backlogs sprint/backlog lists still show their drop-target blankslate immediately when
| `WorkPackageTypes::FormConfiguration::GroupComponent` | Nested group + attribute drag, group-level kebab menu and drag handle. |
| `MeetingSections::ShowComponent` | Nested drag targets; pending API / behaviour review. |
* `MeetingAgendaItems::ListComponent`
### Coordination with DREAM-671
#DREAM-786
* Multi-column lists (document types, storages, wiki providers, documents) wait for a future BorderBoxTable/DataTable.
* Rich-header surfaces (admin project attributes sections,
The rich-header admin Project attributes,
* #DREAM-789 follows #DREAM-802 (the only remaining #DREAM-671 dependency on this effort).