-
Notifications
You must be signed in to change notification settings - Fork 315
Closed
Labels
P1Medium priorityMedium priorityRolloverIssues which role over to the next sprintIssues which role over to the next sprintType: EnhancementImprovement of an existing featureImprovement of an existing feature
Milestone
Description
Widgets may return certain predefined components to indicate certain states:
ReportError
ReportZero
ActivateModuleCTA
CompleteModuleActivationCTA
The last three of those are module-specific and will result in the same UI for each instance they are displayed in (for the same module). If multiple widgets next to each other return the same of those components (i.e. same component with same props), such components should be aggregated and only displayed once. For example, if the Analytics module is not active, only a single ActivateModuleCTA
for Analytics should be displayed in the "Search Funnel" widget area instead of two, even though it results from two different widgets.
Do not alter or remove anything below. The following sections will be managed by moderators only.
Acceptance criteria
- Multiple instances of
ReportZero
,ActivateModuleCTA
, andCompleteModuleActivationCTA
returned by adjacent widgets in the same row should be combined per the module that they apply to.- The widget widths of widgets combined should be combined. For example, three quarter widgets returning the same component for the same module should result in a single three-quarter width version of that component being rendered.
- For example, if two quarter adjacent widgets return
ReportZero
for Search Console and the next two quarter widgets returnActivateModuleCTA
for Analytics, they should be combined to be one halfReportZero
for Search Console and one halfActivateModuleCTA
for Analytics. - Components should not be combined if they would span across multiple rows. For example, if in the above scenario there was another two quarter widgets returning
ActivateModuleCTA
for Analytics, they should be combined with each other, but not with the previous combination of twoActivateModuleCTA
for Analytics because this would mean they would be combined across rows, which would mess up the UI.
- Widgets should not have to set state for this to work. They should only have to return the specific comments, and those components should internally support handling the necessary details (e.g. via state and
useEffect
or similar). - There should be Storybook coverage for widgets where some of them return certain special state components, some in ways that would be combined etc., to test the behavior. The following stories in particular should be included:
- 4 quarter widgets: Normal,
ReportZeroData
Search Console,ReportZeroData
Analytics,ActivateModuleCTA
AdSense - 4 quarter widgets:
ReportZeroData
Search Console,ReportZeroData
Search Console,ReportZeroData
Analytics,ReportZeroData
Analytics - 4 half widgets:
ReportZeroData
Search Console,ActivateModuleCTA
Analytics,ActivateModuleCTA
Analytics,ActivateModuleCTA
AdSense - 2 half widgets
CompleteModuleActivationCTA
Search Console, 1 quarter widgetCompleteModuleActivationCTA
Search Console, 1 quarter widgetCompleteModuleActivationCTA
Analytics, 1 quarter widget "normal", 1 quarter widgetCompleteModuleActivationCTA
Analytics
- 4 quarter widgets: Normal,
Implementation Brief
- The
core/widgets
datastore should receive a new action:setWidgetState( slug, Component, metadata = {} )
receives theWPComponent
and props that are relevant to indicate "commonalities" (i.e. widgets with the sameComponent
andmetadata
would be combined).unsetWidgetState( slug, Component, metadata = {} )
receives the same parameters assetWidgetState
and will unset the corresponding widget state.
- The
core/widgets
datastore should receive a new selector:getWidgetState( slug )
returns an object withComponent
andmetadata
properties from above.
- New components
WidgetReportZero
,WidgetActivateModuleCTA
, andWidgetCompleteModuleActivationCTA
should be introduced:- They should require a
widgetSlug
prop. - They should require a
moduleSlug
prop and wrap the respective component without theWidget*
prefix. They should also pass on any other props to the child component. - They should rely on
useEffect
to callsetWidgetState
with a cleanup callback to callunsetWidgetState
. - The existing
ActivateModuleCTA
andCompleteModuleActivationCTA
components should be modified to have theirslug
prop renamed tomoduleSlug
so that the signature matches exactly theirWidget*
variants (minus thewidgetSlug
prop). ForReportZero
, the prop is already calledmoduleSlug
.
- They should require a
- Every widget should receive props
WidgetReportZero
,WidgetActivateModuleCTA
, andWidgetCompleteModuleActivationCTA
, which are wrapped/scoped versions of the general components mentioned above - scoped as in that thewidgetSlug
is already internally passed there, so that the widget component that may render them doesn't manually need to pass the slug, which would be error-prone. - Remove
AnalyticsInactiveCTA
and rely onActivateModuleCTA
instead, allowing widgets to consistently use the latter component and without requiring us to implement aWidgetAnalyticsInactiveCTA
which would be overly specific. For now, let's just move the alternative title and description into theActivateModuleCTA
component to still have them centralized. This should be revisited and improved - let's just add a TODO for now, as we shouldn't update the canonical module description etc in this issue. - Modify the existing
getWidgetClassNames()
into agetWidgetLayout()
that does not only return the resulting class names for each widget, but also the final column width for each widget and the row index for each widget (while there's only a singleRow
component in a widget area, widgets may extend beyond the visual row and thus be spread across multiple rows). - Introduce a new
combineWidgets()
function that receives the active widgets, their current widget states, plus the class names, column widths and row indexes fromgetWidgetLayout()
. This function will take care of detecting whether consecutive widgets in the same row have a similar state (i.e. sameComponent
andmetadata
). If so, adjust class names and specify override components (see below) as necessary. - Update
WidgetRenderer
so that it can receive an optionalOverrideComponent
prop. If it is passed, render that one instead of the registered widget component. Technically, still render the actual widget component too but hide it via CSS. This is necessary for the hooks to work. - Update
WidgetAreaRenderer
to usegetWidgetLayout()
and thencombineWidgets()
. Then pass the return values of the latter (i.e. the final CSS class names and the potential override components) toWidgetRenderer
. - Add the Storybook stories from the ACs under
Global/Widgets
. - Merge Combine similar widget CTAs #2538.
Test Coverage
- Add Jest tests for the new
getWidgetLayout
andcombineWidgets
functions. - Add Jest tests for the new
Widget*
-prefixed components.
Visual Regression Changes
- N/A
QA Brief
Regular
- Use a development build.
- Set up Site Kit without any extra module activated.
- Ensure that the CTA to set up Analytics and the CTA to set up PageSpeed Insights look exactly the same for the new widgets API-powered part of the dashboard as it does for the legacy part of the dashboard.
Engineering
- Check the
Global/Widgets/Widget Area\Special combination states
story in Storybook. - Ensure that all 4 stories from the ACs are implemented and that the widgets within them are combined as expected:
- Adjacent widgets of the same special type (
ReportZero
,ActivateModuleCTA
,CompleteModuleActivationCTA
) must be combined as long as they are for the same module. - Any blue box must span the grid column width that all the widgets that it is resulting from would have spanned, had they been rendered regularly (i.e. without a special state).
- Adjacent widgets of the same special type (
Changelog entry
- Implement logic to automatically combine UI for widgets that are in special states, e.g. widgets without sufficient API response data, or widgets that require a specific module to be set up first.
Metadata
Metadata
Assignees
Labels
P1Medium priorityMedium priorityRolloverIssues which role over to the next sprintIssues which role over to the next sprintType: EnhancementImprovement of an existing featureImprovement of an existing feature