Skip to content

Discovery task: First draft on temporary siginedin preview for guest users - #14310

Draft
vdeksne wants to merge 1 commit into
bbc:latestfrom
vdeksne:viktorija/pr-14307-followup
Draft

Discovery task: First draft on temporary siginedin preview for guest users#14310
vdeksne wants to merge 1 commit into
bbc:latestfrom
vdeksne:viktorija/pr-14307-followup

Conversation

@vdeksne

@vdeksne vdeksne commented Aug 12, 2026

Copy link
Copy Markdown

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

Copilot AI lite review requested due to automatic review settings August 12, 2026 07:10
@vdeksne
vdeksne marked this pull request as draft August 12, 2026 07:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 useTemporarySavedArticles hook 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

  • clearAll clears stored data but leaves hasExpired untouched. If the hook ever enters an expired state, callers can’t recover by clearing data because hasExpired stays true. Reset hasExpired when 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',
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants