Content
View differences
Updated by Alexander Coles 2 days ago
## Summary
Migrate list-shaped `Primer::Beta::BorderBox` / `border_box_container` usages to `OpenProject::Common::BorderBoxListComponent`, and extend the shared component API where the remaining migrations needed legitimate header flexibility.
Implementation is tracked in PR opf/openproject#23812.
## Implemented so far
### Shared component API
- 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.
- Reworked header/row menus through `BorderBoxListComponent::Menu`, keeping the default kebab trigger automatic while allowing `button_arguments:` or a caller-provided `menu.with_show_button`.
- Added default empty-state rendering for itemless lists when callers do not provide a custom `with_empty_state` slot.
- Updated Lookbook docs, previews, preview specs, and component specs for the new public API.
### Migrated consumers
- `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`
- `WorkPackageTypes::ExportTemplateListComponent`
- `My::Notifications::ShowPageComponent`
- `WorkPackageMeetingsTab::MeetingComponent`
- `Admin::Departments::DetailComponent`
- `WorkPackageRelationsTab::IndexComponent`
- `Admin::Enumerations::IndexComponent` (implemented here, guided by PR opf/openproject#23485)
- `Meetings::Participants::ListComponent`
- `Projects::Settings::CostTypes::IndexComponent`
- `ResourceAllocations::ListComponent`
Existing Backlogs bucket/sprint menu callers were also updated to the new `button_arguments:` API.
## Review and commit structure
The branch was regrouped for reviewability:
- the shared API change is now the first commit;
- each consumer migration is committed as a focused vertical slice;
- follow-up review fixes were folded into their owning commits rather than left as a trailing cleanup commit;
- every `[DREAM-697]` commit has a one-line detail and links back to this work package.
## Verification
- Component specs for the shared component and migrated consumers pass; the four most recent migrations add 38 consumers: 195 examples, 0 failures.
- Feature specs for workflow accessibility and export-template drag/toggle behavior: 4 examples, 0 failures.
- `bin/dirty-rubocop --against origin/dev`: 27 files, no offenses.
- `erb_lint` on changed ERB files: no errors.
- `git diff --check origin/dev..HEAD`: clean.
## Remaining migration candidates
Triaged Ranked by row shape. Gating rule: rows with multiple data columns belong on a future BorderBoxTable / DataTable, not BorderBoxListComponent; rich headers (multiple menus plus a dialog) are out of scope until handled separately, with no header-API extension. fit (list-shaped BorderBox usages targeting BorderBoxListComponent).
### Still a BorderBoxList candidate
| # | Component | Features | Notes |
|---|---|---| |---|-----------|----------|-------|
| `MeetingAgendaItems::ListComponent` 1 | new-item form, no `Admin::Enumerations::IndexComponent` | header / drag / empty | Lowest fit; not yet done. Cherry-pick from PR opf/openproject#23485 (DREAM-688, WP#74940). Shares a class hierarchy with #2. |
### Reclassified to BorderBoxTable (multiple data columns)
| Component 2 | Notes |
|---|---|
| `Documents::Admin::DocumentTypes::IndexComponent` | name header / type drag / updated columns. Also empty | Coupled to #1; also covered by PR opf/openproject#23485 (DREAM-688). opf/openproject#23485. |
| `Storages::Admin::StorageListComponent` 3 | name `Settings::ProjectCustomFieldSections::ShowComponent` | header / creator menu / provider drag / time columns. empty | Near-clone of the migrated `Projects::Settings::ProjectCustomFieldSections::ShowComponent`; high spec reuse. |
| `Wikis::Admin::WikiProviderListComponent` 4 | name `Storages::Admin::StorageListComponent` | header / provider / time columns. empty | |
| `Documents::ListComponent` 5 | name `Wikis::Admin::WikiProviderListComponent` | header / type / updated columns. empty |
### Deferred -- rich |
| 6 | `Meetings::Participants::ListComponent` | header / invasive (no header-API extension)
empty | Component | Notes |
|---|---|
| `Settings::ProjectCustomFieldSections::ShowComponent` 7 | Admin section `Documents::ListComponent` | header has / empty | Pagination row maps to a drag handle, a single-select position menu, a kebab actions menu, and an edit dialog -- beyond the list header footer slot. Not a clone of the migrated `Projects::Settings::ProjectCustomFieldSections::ShowComponent` twin (which has only a title and two action buttons). |
| `WorkPackageTypes::FormConfiguration::GroupComponent` 8 | `MeetingSections::ShowComponent` | header / drag / empty | Nested group + attribute drag, group-level kebab menu and drag handle. targets (harder). |
| `MeetingSections::ShowComponent` 9 | Nested `WorkPackageTypes::FormConfiguration::GroupComponent` | header / drag targets; pending API / behaviour review. empty | |
| 10 | `Projects::Settings::CostTypes::IndexComponent` | toggle list / empty | Same shape as migrated life-cycle / export-template lists. |
| 11 | `ResourceAllocations::ListComponent` | headerless list | Same shape as migrated Portfolios. |
| 12 | `MeetingAgendaItems::ListComponent` | new-item form | No header; lowest fit. |
Note: PR opf/openproject#23485 also adds `spec/support/shared/components/border_box_list_component.rb`, which this branch already introduces -- coordinate to avoid expect a conflict on that file. file when integrating either way.
## Out of scope (not list-shaped)
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.
Migrate list-shaped `Primer::Beta::BorderBox` / `border_box_container` usages to `OpenProject::Common::BorderBoxListComponent`, and extend the shared component API where the remaining migrations needed legitimate header flexibility.
Implementation is tracked in PR opf/openproject#23812.
## Implemented so far
### Shared component API
- 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.
- Reworked header/row menus through `BorderBoxListComponent::Menu`, keeping the default kebab trigger automatic while allowing `button_arguments:` or a caller-provided `menu.with_show_button`.
- Added default empty-state rendering for itemless lists when callers do not provide a custom `with_empty_state` slot.
- Updated Lookbook docs, previews, preview specs, and component specs for the new public API.
### Migrated consumers
- `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`
- `WorkPackageTypes::ExportTemplateListComponent`
- `My::Notifications::ShowPageComponent`
- `WorkPackageMeetingsTab::MeetingComponent`
- `Admin::Departments::DetailComponent`
- `WorkPackageRelationsTab::IndexComponent`
- `Admin::Enumerations::IndexComponent` (implemented here, guided by PR opf/openproject#23485)
- `Meetings::Participants::ListComponent`
- `Projects::Settings::CostTypes::IndexComponent`
- `ResourceAllocations::ListComponent`
Existing Backlogs bucket/sprint menu callers were also updated to the new `button_arguments:` API.
## Review and commit structure
The branch was regrouped for reviewability:
- the shared API change is
- each consumer migration is committed as a focused vertical slice;
- follow-up review fixes were folded into their owning commits rather than left as a trailing cleanup commit;
- every `[DREAM-697]` commit has a one-line detail and links back to this work package.
## Verification
- Component specs for the shared component and migrated consumers pass; the four most recent migrations add 38
- Feature specs for workflow accessibility and export-template drag/toggle behavior: 4 examples, 0 failures.
- `bin/dirty-rubocop --against origin/dev`:
- `erb_lint` on changed ERB files: no errors.
- `git diff --check origin/dev..HEAD`: clean.
## Remaining migration candidates
Triaged
### Still a BorderBoxList candidate
|
|---|---|---|
| `MeetingAgendaItems::ListComponent`
### Reclassified to BorderBoxTable (multiple data columns)
|---|---|
| `Documents::Admin::DocumentTypes::IndexComponent` | name
| `Storages::Admin::StorageListComponent`
| `Wikis::Admin::WikiProviderListComponent`
| `Documents::ListComponent`
### Deferred -- rich
| 6 | `Meetings::Participants::ListComponent` |
|---|---|
| `Settings::ProjectCustomFieldSections::ShowComponent`
| `WorkPackageTypes::FormConfiguration::GroupComponent`
| `MeetingSections::ShowComponent`
| 10 | `Projects::Settings::CostTypes::IndexComponent` | toggle list / empty | Same shape as migrated life-cycle / export-template lists. |
| 11 | `ResourceAllocations::ListComponent` | headerless list | Same shape as migrated Portfolios. |
| 12 | `MeetingAgendaItems::ListComponent` | new-item form | No header; lowest fit. |
Note: PR opf/openproject#23485 also adds `spec/support/shared/components/border_box_list_component.rb`, which this branch already introduces -- coordinate to avoid
## Out of scope (not list-shaped)
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.