feat(group-subs): polish invite-links UX in My Account#4719
Conversation
There was a problem hiding this comment.
Pull request overview
This PR refines the Group Subscription invite-links experience in My Account (v1), focusing on clearer copy, improved tab UI, and more polished interaction feedback for invite-link actions.
Changes:
- Replaces the Members/Invitations tabs with a Newspack UI segmented control and introduces badge-variant syncing for the counts.
- Adds subtle “enter” animation for newly revealed invite-link controls and enforces a minimum spinner duration for invite-link REST actions.
- Improves modal and snackbar copy, and introduces a backend helper to render the email-invite expiration window as a human-readable label.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/my-account/v1/group-subscriptions.js |
Updates tab badge behavior and adds animation + minimum spinner duration around invite-link actions. |
src/my-account/v1/_group-subscriptions.scss |
Removes old tab styling, adds segmented-control tweaks and an enter animation keyframe. |
includes/plugins/woocommerce/my-account/templates/v1/group-subscription-members.php |
Switches markup to segmented control, updates modal copy, and shows the configured invite expiration label in the email-invite modal. |
includes/plugins/woocommerce/my-account/class-my-account-ui-v1.php |
Updates localized snackbar strings for regenerate/disable outcomes. |
includes/plugins/woocommerce-subscriptions/group-subscription/class-group-subscription-invite.php |
Adds get_expiration_label() helper to format the invite expiration window for UI copy. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
tests/unit-tests/content-gate/group-subscriptions.php:2484
- The expiration-time filter is removed after the assertion; if the assertion fails, the filter will remain active for later tests. Use a try/finally (or remove_filter before asserting) to guarantee cleanup.
$callback = function () {
return 0;
};
add_filter( 'newspack_group_subscription_invite_expiration_time', $callback );
$this->assertSame( '1 minute', Group_Subscription_Invite::get_expiration_label() );
remove_filter( 'newspack_group_subscription_invite_expiration_time', $callback );
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
src/my-account/v1/group-subscriptions.js:119
- The new 500ms minimum-loading logic is only applied to the REST-backed regenerate/disable flows; the “Copy invite link” path (when a link already exists) still copies instantly with no loading state. This doesn’t match the PR description (“500ms minimum spinner duration on Copy…”) and makes the UX inconsistent—consider applying the same loading class + minimum duration to the copy-only case too.
// Minimum loading duration so the spinner reads as "system thinking" even when the API is instant.
const MIN_LOADING_MS = 500;
const waitForMinLoading = start => {
const elapsed = performance.now() - start;
return elapsed < MIN_LOADING_MS ? new Promise( resolve => setTimeout( resolve, MIN_LOADING_MS - elapsed ) ) : Promise.resolve();
};
dkoo
left a comment
There was a problem hiding this comment.
@thomasguillot The design changes look much better, thanks! Claude surfaced one blocking comment and several non-blocking nits/suggestions. I also made a couple of very subjective non-blocking suggestions about the wording of the new copy—feel free to ignore if you disagree. All feedback in inline comments below.
dkoo
left a comment
There was a problem hiding this comment.
@thomasguillot thanks for the changes! All review feedback addressed and most looks 👍 to me. Just one bit of feedback on the the thread about addressing the scenario where the navigator.clipboard.writeText fails—I don't think we need to go as far as the solution you implemented.
dkoo
left a comment
There was a problem hiding this comment.
@thomasguillot thanks for that last revision!
|
Hey @thomasguillot, good job getting this PR merged! 🎉 Now, the Please check if this PR needs to be included in the "Upcoming Changes" and "Release Notes" doc. If it doesn't, simply remove the label. If it does, please add an entry to our shared document, with screenshots and testing instructions if applicable, then remove the label. Thank you! ❤️ |
* feat(group-subs): polish invite-links UX in My Account * fix(group-subs): align empty-state row height in invite tables * fix(group-subs): address review feedback on invite-links polish * fix(group-subs): floor sub-minute expiration to avoid overstating * fix(group-subs): no-JS panel fallback and i18n number formatting * test(group-subs): guard expiration-label tests with try/finally * fix(group-subs): reduced-motion support and performance.now fallback * fix(ui): add ARIA tab semantics and keyboard nav to segmented-control * fix(group-subs): address invite-links review feedback * test(group-subs): cover negative and i18n cases for expiration label * refactor(group-subs): simplify clipboard failure to a plain snackbar
# [6.40.0-alpha.4](v6.40.0-alpha.3...v6.40.0-alpha.4) (2026-05-14) ### Features * **group-subs:** polish invite-links UX in My Account ([#4719](#4719)) ([4044541](4044541))
Summary
Visual and UX polish on the Group Subscription invite-links UI introduced in #4704.
--outline(unselected) and--secondary(selected) via JS so the literal classes flip with state.Group_Subscription_Invite::get_expiration_label()so it follows whatever thenewspack_group_subscription_invite_expiration_timefilter is set to (e.g. "30 days", "1 hour", "2 weeks").::after+var(--newspack-ui-spacer-7)pattern the rest of the table uses.Screenshots
Test plan
--outlineand--secondary.add_filter( 'newspack_group_subscription_invite_expiration_time', fn() => HOUR_IN_SECONDS );to confirm the label updates to "1 hour".