Discovery task: First draft on temporary siginedin preview for guest users - #14310
Draft
vdeksne wants to merge 1 commit into
Draft
Discovery task: First draft on temporary siginedin preview for guest users#14310vdeksne wants to merge 1 commit into
vdeksne wants to merge 1 commit into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Implements a proof-of-concept “temporary signed-in preview” for guest users: guests can temporarily save articles (via localStorage) and see a temporary My News view prompting sign-in/register, to test whether this increases BBC account registrations.
Changes:
- Add a guest “save article” preview flow (tooltip + confirmation + localStorage persistence) and enable it on Article pages.
- Add a
useTemporarySavedArticleshook to persist guest-saved items with a 2‑day expiry. - Add a Temporary My News page and update My News routing to show it for signed-out users who have temporary saves.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| ws-nextjs-app/pages/[service]/my-news/MyNewsPage/MyNewsPageTemporary/index.tsx | New temporary My News view that renders guest-saved articles and sign-in/register CTAs. |
| ws-nextjs-app/pages/[service]/my-news/MyNewsPage/index.tsx | Chooses between authenticated, guest, and temporary guest My News experiences. |
| src/app/pages/ArticlePage/ArticlePage.tsx | Enables the guest preview save experience on Article pages. |
| src/app/hooks/useTemporarySavedArticles/index.ts | New hook to store/retrieve temporary guest-saved articles with expiry. |
| src/app/components/SaveArticleButton/SaveArticleButtonGuestWithPreview/SaveButtonTooltip.tsx | New tooltip shown for the guest preview save button. |
| src/app/components/SaveArticleButton/SaveArticleButtonGuestWithPreview/SaveArticleConfirmation.tsx | New confirmation UI after guest saves, linking to My News. |
| src/app/components/SaveArticleButton/SaveArticleButtonGuestWithPreview/index.tsx | New guest “save” implementation wired to temporary storage + tracking. |
| src/app/components/SaveArticleButton/index.tsx | Adds enableGuestPreview prop and routes guest users to the preview variant when enabled. |
| POC-GUEST-PREVIEW-README.md | Documents the POC behaviour and manual testing steps. |
Suppressed comments (3)
src/app/components/SaveArticleButton/SaveArticleButtonGuestWithPreview/SaveArticleConfirmation.tsx:70
- The confirmation copy and the close button aria-label are hard-coded in English. These should be sourced from translations to avoid non-English services showing English UI and to keep accessibility labels localized.
const confirmationText = 'Article saved to My News';
const linkText = 'View My News';
const myNewsPath = `/${service}/my-news`;
src/app/hooks/useTemporarySavedArticles/index.ts:110
- When the last temporary saved article is removed, the expiry key is left behind. This can keep an old expiry window around and prevent a fresh 2-day period from being set on a later save. Clear the expiry (and storage key) when the list becomes empty.
setSavedArticles(prev => {
const updated = prev.filter(a => a.id !== articleId);
localStorage.setItem(STORAGE_KEY, JSON.stringify(updated));
return updated;
});
src/app/hooks/useTemporarySavedArticles/index.ts:127
clearAllclears stored data but leaveshasExpireduntouched. If the hook ever enters an expired state, callers can’t recover by clearing data becausehasExpiredstays true. ResethasExpiredwhen clearing.
localStorage.removeItem(STORAGE_KEY);
localStorage.removeItem(EXPIRY_KEY);
setSavedArticles([]);
setExpiryDate(null);
}, []);
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+83
to
+86
| visualLabel={label ?? ''} | ||
| hoverVisualLabel={hoverLabel} | ||
| accessibleLabel={label ?? ''} | ||
| testId="save-article-btn-guest-preview" |
Comment on lines
+79
to
+100
| return ( | ||
| <div style={{ position: 'relative', display: 'inline-block' }}> | ||
| <SaveButton | ||
| onClick={handleClick} | ||
| visualLabel={label ?? ''} | ||
| hoverVisualLabel={hoverLabel} | ||
| accessibleLabel={label ?? ''} | ||
| testId="save-article-btn-guest-preview" | ||
| isLoading={!isHydrated} | ||
| isSaved={isSaved} | ||
| onMouseEnter={() => setShowTooltip(true)} | ||
| onMouseLeave={() => setShowTooltip(false)} | ||
| onFocus={() => setShowTooltip(true)} | ||
| onBlur={() => setShowTooltip(false)} | ||
| {...viewTracker} | ||
| /> | ||
| {showTooltip && <SaveButtonTooltip isSaved={isSaved} />} | ||
| {showConfirmation && ( | ||
| <SaveArticleConfirmation onClose={() => setShowConfirmation(false)} /> | ||
| )} | ||
| </div> | ||
| ); |
Comment on lines
+51
to
+56
| const SaveButtonTooltip = ({ isSaved = false }: SaveButtonTooltipProps) => { | ||
| const unsavedText = | ||
| 'Save this article for later. It will appear in your My News page.'; | ||
| const savedText = 'This article is saved temporarily in your My News page.'; | ||
|
|
||
| const tooltipText = isSaved ? savedText : unsavedText; |
Comment on lines
+43
to
+57
| if (storedExpiry) { | ||
| const expiry = new Date(parseInt(storedExpiry, 10)); | ||
| setExpiryDate(expiry); | ||
|
|
||
| // Check if expired | ||
| if (new Date() > expiry) { | ||
| setHasExpired(true); | ||
| // Clear expired data | ||
| localStorage.removeItem(STORAGE_KEY); | ||
| localStorage.removeItem(EXPIRY_KEY); | ||
| setSavedArticles([]); | ||
| setExpiryDate(null); | ||
| return; | ||
| } | ||
| } |
Comment on lines
+46
to
+56
| const formatExpiryDate = (date: Date) => { | ||
| const now = new Date(); | ||
| const diff = date.getTime() - now.getTime(); | ||
| const hours = Math.floor(diff / (1000 * 60 * 60)); | ||
| const days = Math.floor(hours / 24); | ||
|
|
||
| if (days > 0) { | ||
| return `${days} day${days > 1 ? 's' : ''}`; | ||
| } | ||
| return `${hours} hour${hours > 1 ? 's' : ''}`; | ||
| }; |
Comment on lines
26
to
+41
| @@ -29,6 +34,12 @@ const MyNewsPage = ({ page }: MyNewsPageProps) => { | |||
|
|
|||
| if (!isPersonalizationAvailable || !translations?.myNews) return null; | |||
|
|
|||
| // Determine which view to show | |||
| const shouldShowTemporary = | |||
| !isPersonalizationEnabled && hasTemporarySavedArticles; | |||
| const shouldShowGuest = | |||
| !isPersonalizationEnabled && !hasTemporarySavedArticles; | |||
Comment on lines
+25
to
+28
| const GuestButton = enableGuestPreview | ||
| ? SaveArticleButtonGuestWithPreview | ||
| : SaveArticleButtonGuest; | ||
|
|
Comment on lines
37
to
+63
| @@ -47,11 +58,9 @@ const MyNewsPage = ({ page }: MyNewsPageProps) => { | |||
| </div> | |||
| </noscript> | |||
| <div css={styles.innerContent}> | |||
| {isPersonalizationEnabled ? ( | |||
| <MyNewsPageContent page={page} /> | |||
| ) : ( | |||
| <MyNewsPageGuest /> | |||
| )} | |||
| {isPersonalizationEnabled && <MyNewsPageContent page={page} />} | |||
| {shouldShowTemporary && <MyNewsPageTemporary />} | |||
| {shouldShowGuest && <MyNewsPageGuest />} | |||
Comment on lines
+32
to
+36
| ### 4. Integration Points | ||
| - **Article Pages**: Save button now uses `enableGuestPreview` prop to activate POC | ||
| - **My News Page**: Automatically shows temporary view when user has saved articles but isn't signed in | ||
| - **Smooth transition**: When user signs in, they see their temporary saves migrate to permanent storage | ||
|
|
Comment on lines
+6
to
+10
| import { css } from '@emotion/react'; | ||
|
|
||
| const styles = { | ||
| overlay: css({ | ||
| position: 'absolute', |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves JIRA: NEON Discovery week task
This POC implements a temporary signed-in preview experience for guest users to test the hypothesis that allowing non-registered users to build a temporary My News experience will increase BBC account registrations.
More details : https://miro.com/app/board/uXjVH12Hyyc=/?moveToWidget=3458764680478618402&cot=14
password: worldservice