Repository: Automattic/wp-calypso
Pull request #101314: Reader: Update interests Modal
Author: login: ntsekouras
Labels: name: [Feature] Signup & Site Onboarding
name: [Feature Group] Reader
Created: 2025-03-13T13:43:50Z | Merged: 2025-03-20T07:25:28Z

Part of: https://github.com/Automattic/wp-calypso/issues/100211

This PR updates the interests Modal shown to users that visit the Reader for the first time.

The linked issue also suggests making some copy changes to some [subtitles](https://github.com/Automattic/wp-calypso/issues/100211#issuecomment-2681677257) and introduce a new header at the sidebar. 

We can explore this here or in a follow up to land this one faster.



## Testing Instructions
1. Visit the Reader (`/reader`) as if it was for the first time. I'm not sure if there is an easier way to do this, but I changed [this condition](https://github.com/Automattic/wp-calypso/blob/trunk/client/reader/following/main.tsx#L33) to `if ( true )`.
2. Observe the updated Modal
3. To see the new subtitles navigate to `Likes, Conversations and Discover` respectively. Noting that for `Discover` there are way more subtitles based on the tab selection below

Before     | After
:-------------------------:|:-------------------------:
<img width="1221" alt="before" src="https://github.com/user-attachments/assets/21201bdd-4ccb-4a78-a6f5-54635e745c97" /> | <img width="1221" alt="after" src="https://github.com/user-attachments/assets/f2241984-f77c-4ffc-97de-d6544f4f7e53" />


Before     | After
:-------------------------:|:-------------------------:
<img width="931" alt="disc before" src="https://github.com/user-attachments/assets/cc2fec02-bb15-4cf9-aca4-84bd5128068e" /> | <img width="931" alt="disc after" src="https://github.com/user-attachments/assets/68a402e7-63ed-4c22-b977-77a8b2b0185f" />


Before     | After
:-------------------------:|:-------------------------:
<img width="1221" alt="disc spli bef" src="https://github.com/user-attachments/assets/291ada20-5fb6-40bd-a50e-2d8654af77fc" /> | <img width="1221" alt="disc spli after" src="https://github.com/user-attachments/assets/1b36a2aa-50dd-405f-8874-452a4784d220" />



## Pre-merge Checklist

<!--
Complete applicable items on this checklist **before** merging into trunk. Inapplicable items can be left unchecked.

Both the PR author and reviewer are responsible for ensuring the checklist is completed.
-->

- [ ] Has the general commit checklist been followed? (PCYsg-hS-p2)
- [ ] [Have you written new tests](https://wpcalypso.wordpress.com/devdocs/docs/testing/index.md) for your changes?
- [ ] Have you tested the feature in Simple (P9HQHe-k8-p2), Atomic (P9HQHe-jW-p2), and self-hosted Jetpack sites (PCYsg-g6b-p2)?
- [ ] Have you checked for TypeScript, React or other console errors?
- [ ] Have you used memoizing on expensive computations? More info in [Memoizing with create-selector](https://github.com/Automattic/wp-calypso/blob/trunk/packages/state-utils/src/create-selector/README.md) and [Using memoizing selectors](https://react-redux.js.org/api/hooks#using-memoizing-selectors) and [Our Approach to Data](https://github.com/Automattic/wp-calypso/blob/trunk/docs/our-approach-to-data.md)
- [ ] Have we added the "[Status] String Freeze" label as soon as any new strings were ready for translation (p4TIVU-5Jq-p2)?
    - [ ] For UI changes, have we tested the change in various languages (for example, ES, PT, FR, or DE)? The length of text and words vary significantly between languages. 
- [ ] For changes affecting Jetpack: Have we added the "[Status] Needs Privacy Updates" label if this pull request changes what data or activity we track or use (p4TIVU-aUh-p2)?



Diff:
diff --git a/client/reader/conversations/stream.js b/client/reader/conversations/stream.js
index 26c42e5a554d..280e26960c2c 100644
--- a/client/reader/conversations/stream.js
+++ b/client/reader/conversations/stream.js
@@ -1,4 +1,4 @@
-import { useTranslate } from 'i18n-calypso';
+import { useTranslate, fixMe } from 'i18n-calypso';
 import { get } from 'lodash';
 import ConversationsEmptyContent from 'calypso/blocks/conversations/empty';
 import DocumentHead from 'calypso/components/data/document-head';
@@ -41,7 +41,11 @@ export default function ( props ) {
 				<ConversationTitle title={ props.title } />
 				<NavigationHeader
 					title={ translate( 'Conversations' ) }
-					subtitle={ translate( 'Monitor all of your ongoing discussions.' ) }
+					subtitle={ fixMe( {
+						text: 'Check in on your open discussions.',
+						newCopy: translate( 'Check in on your open discussions.' ),
+						oldCopy: translate( 'Monitor all of your ongoing discussions.' ),
+					} ) }
 					className="conversations__header"
 				/>
 			</Stream>
diff --git a/client/reader/following/main.tsx b/client/reader/following/main.tsx
index 4193978db0a2..2dc5bc3572e9 100644
--- a/client/reader/following/main.tsx
+++ b/client/reader/following/main.tsx
@@ -1,7 +1,7 @@
 import config from '@automattic/calypso-config';
 import { FoldableCard } from '@automattic/components';
 import clsx from 'clsx';
-import { translate } from 'i18n-calypso';
+import { translate, fixMe } from 'i18n-calypso';
 import { useEffect } from 'react';
 import AsyncLoad from 'calypso/components/async-load';
 import BloganuaryHeader from 'calypso/components/bloganuary-header';
@@ -58,7 +58,11 @@ function FollowingStream( { ...props } ) {
 					<BloganuaryHeader />
 					<NavigationHeader
 						title={ translate( 'Recent' ) }
-						subtitle={ translate( "Stay current with the blogs you've subscribed to." ) }
+						subtitle={ fixMe( {
+							text: 'Fresh content from blogs you follow.',
+							newCopy: translate( 'Fresh content from blogs you follow.' ),
+							oldCopy: translate( "Stay current with the blogs you've subscribed to." ),
+						} ) }
 						className={ clsx( 'following-stream-header', {
 							'reader-dual-column': props.width > WIDE_DISPLAY_CUTOFF,
 						} ) }
diff --git a/client/reader/liked-stream/main.jsx b/client/reader/liked-stream/main.jsx
index 5fc338a61086..d3f2d478ed43 100644
--- a/client/reader/liked-stream/main.jsx
+++ b/client/reader/liked-stream/main.jsx
@@ -1,4 +1,4 @@
-import { translate } from 'i18n-calypso';
+import { translate, fixMe } from 'i18n-calypso';
 import { Component } from 'react';
 import DocumentHead from 'calypso/components/data/document-head';
 import NavigationHeader from 'calypso/components/navigation-header';
@@ -26,7 +26,11 @@ class LikedStream extends Component {
 					<DocumentHead title={ documentTitle } />
 					<NavigationHeader
 						title={ translate( 'Likes' ) }
-						subtitle={ translate( 'Rediscover content that you liked.' ) }
+						subtitle={ fixMe( {
+							text: 'Revisit the posts and comments you liked.',
+							newCopy: translate( 'Revisit the posts and comments you liked.' ),
+							oldCopy: translate( 'Rediscover content that you liked.' ),
+						} ) }
 						className="liked-stream-header"
 					/>
 				</Stream>
diff --git a/client/reader/onboarding/interests-modal/index.tsx b/client/reader/onboarding/interests-modal/index.tsx
index 4f3f610b48e9..5dcd571bfae6 100644
--- a/client/reader/onboarding/interests-modal/index.tsx
+++ b/client/reader/onboarding/interests-modal/index.tsx
@@ -1,7 +1,13 @@
 import { recordTracksEvent } from '@automattic/calypso-analytics';
 import { SelectCardCheckbox } from '@automattic/onboarding';
-import { Modal, Button } from '@wordpress/components';
+import {
+	Modal,
+	Button,
+	__experimentalVStack as VStack,
+	__experimentalHStack as HStack,
+} from '@wordpress/components';
 import { __ } from '@wordpress/i18n';
+import { fixMe } from 'i18n-calypso';
 import React, { useState, useEffect } from 'react';
 import { useSelector, useDispatch, useStore } from 'react-redux';
 import { READER_ONBOARDING_TRACKS_EVENT_PREFIX } from 'calypso/reader/onboarding/constants';
@@ -45,7 +51,7 @@ const InterestsModal: React.FC< InterestsModalProps > = ( { isOpen, onClose, onC
 		}
 	}, [ followedTagsFromState, processingTags ] );
 
-	const isContinueDisabled = followedTags.length < 3;
+	const isContinueDisabled = followedTags.length < 4;
 
 	const handleTopicChange = ( checked: boolean, tag: string ) => {
 		// If the tag is already being processed, do nothing.
@@ -185,33 +191,27 @@ const InterestsModal: React.FC< InterestsModalProps > = ( { isOpen, onClose, onC
 		},
 	];
 
-	const headerActions = (
-		<>
-			<Button onClick={ onClose } variant="link">
-				{ __( 'Cancel' ) }
-			</Button>
-			<Button onClick={ handleContinue } variant="primary" disabled={ isContinueDisabled }>
-				{ __( 'Continue' ) }
-			</Button>
-		</>
-	);
-
 	return (
 		isOpen && (
-			<Modal
-				onRequestClose={ onClose }
-				isFullScreen
-				headerActions={ headerActions }
-				isDismissible={ false }
-				className="interests-modal"
-			>
-				<div className="interests-modal__content">
-					<h2 className="interests-modal__title">{ __( 'What topics interest you?' ) }</h2>
-					<p className="interests-modal__subtitle">
-						{ __( 'Follow at least 3 topics to personalize your Reader feed.' ) }
-					</p>
+			<Modal onRequestClose={ onClose } size="fill" className="interests-modal">
+				<VStack spacing={ 8 } className="interests-modal__content">
+					<VStack spacing={ 0 }>
+						<h2 className="interests-modal__title">{ __( 'What topics interest you?' ) }</h2>
+						<p className="interests-modal__subtitle">
+							{ __(
+								'​​Stay up-to-date with your favorite blogs and discover new voices—all from one place.'
+							) }
+						</p>
+						<p className="interests-modal__subtitle">
+							{ fixMe( {
+								text: 'Follow at least 3 topics to personalize your feed.',
+								newCopy: __( 'Follow at least 3 topics to personalize your feed.' ),
+								oldCopy: __( 'Follow at least 3 topics to personalize your Reader feed.' ),
+							} ) }
+						</p>
+					</VStack>
 					{ categories.map( ( category ) => (
-						<div key={ category.name } className="interests-modal__category">
+						<div key={ category.name }>
 							<h3 className="interests-modal__section-header">{ category.name }</h3>
 							<div className="interests-modal__topics-list">
 								{ category.topics.map( ( topic ) => (
@@ -230,7 +230,23 @@ const InterestsModal: React.FC< InterestsModalProps > = ( { isOpen, onClose, onC
 							</div>
 						</div>
 					) ) }
-				</div>
+					<div className="reader-onboarding-modal__footer">
+						<HStack justify="right" className="reader-onboarding-modal__footer-actions">
+							<Button __next40pxDefaultSize variant="tertiary" onClick={ onClose }>
+								{ __( 'Cancel' ) }
+							</Button>
+							<Button
+								__next40pxDefaultSize
+								onClick={ handleContinue }
+								variant="primary"
+								disabled={ isContinueDisabled }
+								accessibleWhenDisabled
+							>
+								{ __( 'Continue' ) }
+							</Button>
+						</HStack>
+					</div>
+				</VStack>
 			</Modal>
 		)
 	);
diff --git a/client/reader/onboarding/interests-modal/style.scss b/client/reader/onboarding/interests-modal/style.scss
index 992dead3f3ed..b648e0c53c6a 100644
--- a/client/reader/onboarding/interests-modal/style.scss
+++ b/client/reader/onboarding/interests-modal/style.scss
@@ -1,13 +1,16 @@
 @import '@wordpress/base-styles/breakpoints';
 @import '@wordpress/base-styles/mixins';
 
+$actions-height: 64px;
+
 .interests-modal {
 	&__content {
-		padding: 24px;
-
-		@media ( max-width: $break-medium ) {
-			padding: 0;
-		}
+		// Since the actions container is positioned absolutely,
+		// this padding bottom ensures that the content wrapper will properly
+		// detect overflowing content and start showing scrollbars at the right
+		// moment. Without this padding, the content would render under the actions
+		// bar without causing the wrapper to show a scrollbar.
+		padding-bottom: $actions-height;
 	}
 
 	&__title {
@@ -23,11 +26,7 @@
 
 	&__subtitle {
 		text-align: center;
-	}
-
-	&__category {
-		max-width: 1200px;
-		margin: 0 auto 32px auto;
+		margin: 0;
 	}
 
 	&__section-header {
@@ -47,16 +46,4 @@
 			grid-template-columns: repeat( 3, 1fr );
 		}
 	}
-
-	.components-modal__header {
-		.components-button {
-			&.is-link {
-				margin-right: auto;
-			}
-
-			&.is-primary {
-				margin-left: 16px;
-			}
-		}
-	}
 }
diff --git a/client/reader/onboarding/style.scss b/client/reader/onboarding/style.scss
index 161d9552e499..428c77c61e42 100644
--- a/client/reader/onboarding/style.scss
+++ b/client/reader/onboarding/style.scss
@@ -15,3 +15,22 @@
 		margin: 5px 5px 5px 10px;
 	}
 }
+
+$actions-height: 64px;
+
+.reader-onboarding-modal__footer {
+	height: $actions-height;
+	position: absolute;
+	bottom: 0;
+	width: 100%;
+	background-color: #fff;
+	margin-left: -32px; // $grid-unit-40
+	margin-right: -32px;
+	padding-left: 32px;
+	padding-right: 32px;
+	border-top: 1px solid #ddd; //$gray-300;
+
+	.reader-onboarding-modal__footer-actions {
+		height: 100%;
+	}
+}
diff --git a/client/reader/onboarding/subscribe-modal/index.tsx b/client/reader/onboarding/subscribe-modal/index.tsx
index 07271d7670fa..96a31b27d035 100644
--- a/client/reader/onboarding/subscribe-modal/index.tsx
+++ b/client/reader/onboarding/subscribe-modal/index.tsx
@@ -1,7 +1,7 @@
 import { recordTracksEvent } from '@automattic/calypso-analytics';
 import { LoadingPlaceholder } from '@automattic/components';
 import { useQuery, useQueryClient } from '@tanstack/react-query';
-import { Modal, Button } from '@wordpress/components';
+import { Modal, Button, __experimentalHStack as HStack } from '@wordpress/components';
 import { __ } from '@wordpress/i18n';
 import clsx from 'clsx';
 import { getLocaleSlug } from 'i18n-calypso';
@@ -290,27 +290,14 @@ const SubscribeModal: React.FC< SubscribeModalProps > = ( { isOpen, onClose } )
 		handleClose();
 	}, [ dispatch, handleClose, queryClient ] );
 
-	const headerActions = (
-		<>
-			<Button onClick={ handleClose } variant="link">
-				{ __( 'Cancel' ) }
-			</Button>
-			<Button onClick={ handleContinue } variant="primary" disabled={ promptVerification }>
-				{ __( 'Continue' ) }
-			</Button>
-		</>
-	);
-
 	return (
 		isOpen && (
 			<Modal
 				onRequestClose={ handleClose }
-				isFullScreen
+				size="fill"
 				className={ clsx( 'subscribe-modal', {
 					'is-disabled': promptVerification,
 				} ) }
-				headerActions={ headerActions }
-				isDismissible={ false }
 			>
 				<div className="subscribe-modal__container">
 					{ promptVerification && <SubscribeVerificationNudge /> }
@@ -382,6 +369,22 @@ const SubscribeModal: React.FC< SubscribeModalProps > = ( { isOpen, onClose } )
 								) }
 							</div>
 						</div>
+						<div className="reader-onboarding-modal__footer">
+							<HStack justify="right" className="reader-onboarding-modal__footer-actions">
+								<Button __next40pxDefaultSize variant="tertiary" onClick={ handleClose }>
+									{ __( 'Cancel' ) }
+								</Button>
+								<Button
+									__next40pxDefaultSize
+									onClick={ handleContinue }
+									variant="primary"
+									disabled={ promptVerification }
+									accessibleWhenDisabled
+								>
+									{ __( 'Continue' ) }
+								</Button>
+							</HStack>
+						</div>
 					</div>
 				</div>
 			</Modal>
diff --git a/client/reader/onboarding/subscribe-modal/style.scss b/client/reader/onboarding/subscribe-modal/style.scss
index cc3a6305a2ae..e0c980298577 100644
--- a/client/reader/onboarding/subscribe-modal/style.scss
+++ b/client/reader/onboarding/subscribe-modal/style.scss
@@ -14,6 +14,8 @@ body.is-reader-page .subscribe-modal__preview-column .reader__card.card.is-place
 	}
 }
 
+$actions-height: 64px;
+
 .subscribe-modal {
 	&__title {
 		font-family: Recoleta, sans-serif;
@@ -29,6 +31,13 @@ body.is-reader-page .subscribe-modal__preview-column .reader__card.card.is-place
 	}
 
 	&__content {
+		// Since the actions container is positioned absolutely,
+		// this padding bottom ensures that the content wrapper will properly
+		// detect overflowing content and start showing scrollbars at the right
+		// moment. Without this padding, the content would render under the actions
+		// bar without causing the wrapper to show a scrollbar.
+		padding-bottom: $actions-height;
+
 		display: flex;
 		flex-direction: column;
 		height: calc( 100vh - 200px );


Reviews:
user: login: ntsekouras
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-14T09:29:47Z
user: login: ntsekouras
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-14T12:47:46Z
user: login: Addison-Stavlo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-14T13:07:32Z
user: login: Addison-Stavlo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-14T13:13:53Z
user: login: davemart-in
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-14T20:29:12Z
user: login: ntsekouras
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T11:14:55Z
user: login: jasmussen
body: Would appreciate Addie's review, but 👍 👍
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-19T08:52:38Z
user: login: Addison-Stavlo
body: Just a minor note on how we can improve the translations/string changes, but other than that the code is looking good!
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-19T11:35:07Z
user: login: Addison-Stavlo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-19T11:56:24Z
user: login: michaelpick
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-19T15:27:08Z
user: login: michaelpick
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-19T15:31:04Z
user: login: michaelpick
body: LGTM! Left a couple of tiny comments, but nothing blocking.
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-19T15:31:41Z
user: login: ntsekouras
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-19T15:50:43Z
user: login: ntsekouras
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-19T16:03:31Z

Review comments:
diff_hunk: @@ -185,33 +190,28 @@ const InterestsModal: React.FC< InterestsModalProps > = ( { isOpen, onClose, onC
 		},
 	];
 
-	const headerActions = (
-		<>
-			<Button onClick={ onClose } variant="link">
-				{ __( 'Cancel' ) }
-			</Button>
-			<Button onClick={ handleContinue } variant="primary" disabled={ isContinueDisabled }>
-				{ __( 'Continue' ) }
-			</Button>
-		</>
-	);
-
 	return (
 		isOpen && (
 			<Modal
 				onRequestClose={ onClose }
-				isFullScreen
-				headerActions={ headerActions }
-				isDismissible={ false }
+				size="large"
 				className="interests-modal"
+				overlayClassName="interests-modal__overlay"
path: client/reader/onboarding/interests-modal/index.tsx
user: login: ntsekouras
body: ```suggestion
```
created_at: 2025-03-14T09:29:46Z
author_association: MEMBER
diff_hunk: @@ -185,33 +190,23 @@ const InterestsModal: React.FC< InterestsModalProps > = ( { isOpen, onClose, onC
 		},
 	];
 
-	const headerActions = (
-		<>
-			<Button onClick={ onClose } variant="link">
-				{ __( 'Cancel' ) }
-			</Button>
-			<Button onClick={ handleContinue } variant="primary" disabled={ isContinueDisabled }>
-				{ __( 'Continue' ) }
-			</Button>
-		</>
-	);
-
 	return (
 		isOpen && (
-			<Modal
-				onRequestClose={ onClose }
-				isFullScreen
-				headerActions={ headerActions }
-				isDismissible={ false }
-				className="interests-modal"
-			>
-				<div className="interests-modal__content">
-					<h2 className="interests-modal__title">{ __( 'What topics interest you?' ) }</h2>
-					<p className="interests-modal__subtitle">
-						{ __( 'Follow at least 3 topics to personalize your Reader feed.' ) }
-					</p>
+			<Modal onRequestClose={ onClose } size="large" className="interests-modal">
+				<VStack spacing={ 8 } className="interests-modal__content">
+					<VStack spacing={ 0 }>
+						<h2 className="interests-modal__title">{ __( 'What topics interest you?' ) }</h2>
+						<p className="interests-modal__subtitle">
+							{ __(
+								'​​Stay up-to-date with your favorite blogs and discover new voices—all from one place.'
+							) }
+						</p>
+						<p className="interests-modal__subtitle">
+							{ __( 'Follow at least 3 topics to personalize your feed.' ) }
path: client/reader/onboarding/interests-modal/index.tsx
user: login: ntsekouras
body: I noticed that the button to continue requires only `2` topics and not `3` as it mentions here, in order to become enabled and clickable.

Should we update the check in the code or the message?
created_at: 2025-03-14T12:47:46Z
author_association: MEMBER
diff_hunk: @@ -185,33 +190,23 @@ const InterestsModal: React.FC< InterestsModalProps > = ( { isOpen, onClose, onC
 		},
 	];
 
-	const headerActions = (
-		<>
-			<Button onClick={ onClose } variant="link">
-				{ __( 'Cancel' ) }
-			</Button>
-			<Button onClick={ handleContinue } variant="primary" disabled={ isContinueDisabled }>
-				{ __( 'Continue' ) }
-			</Button>
-		</>
-	);
-
 	return (
 		isOpen && (
-			<Modal
-				onRequestClose={ onClose }
-				isFullScreen
-				headerActions={ headerActions }
-				isDismissible={ false }
-				className="interests-modal"
-			>
-				<div className="interests-modal__content">
-					<h2 className="interests-modal__title">{ __( 'What topics interest you?' ) }</h2>
-					<p className="interests-modal__subtitle">
-						{ __( 'Follow at least 3 topics to personalize your Reader feed.' ) }
-					</p>
+			<Modal onRequestClose={ onClose } size="large" className="interests-modal">
+				<VStack spacing={ 8 } className="interests-modal__content">
+					<VStack spacing={ 0 }>
+						<h2 className="interests-modal__title">{ __( 'What topics interest you?' ) }</h2>
+						<p className="interests-modal__subtitle">
+							{ __(
+								'​​Stay up-to-date with your favorite blogs and discover new voices—all from one place.'
+							) }
+						</p>
+						<p className="interests-modal__subtitle">
+							{ __( 'Follow at least 3 topics to personalize your feed.' ) }
path: client/reader/onboarding/interests-modal/index.tsx
user: login: Addison-Stavlo
body: Ohhh that is interesting.

It looks like new accounts automatically have the `dailyprompt` tag followed. So when they open the interests modal they only need to select 2 more to meet the condition of having at least 3 tags followed. 🤔 

Perhaps one solution could be to make the copy contextual to how many tags are followed? ( "3 more...", "2 more", "1 more", etc.) ?

cc @davemart-in 
created_at: 2025-03-14T13:07:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -185,33 +190,23 @@ const InterestsModal: React.FC< InterestsModalProps > = ( { isOpen, onClose, onC
 		},
 	];
 
-	const headerActions = (
-		<>
-			<Button onClick={ onClose } variant="link">
-				{ __( 'Cancel' ) }
-			</Button>
-			<Button onClick={ handleContinue } variant="primary" disabled={ isContinueDisabled }>
-				{ __( 'Continue' ) }
-			</Button>
-		</>
-	);
-
 	return (
 		isOpen && (
-			<Modal
-				onRequestClose={ onClose }
-				isFullScreen
-				headerActions={ headerActions }
-				isDismissible={ false }
-				className="interests-modal"
-			>
-				<div className="interests-modal__content">
-					<h2 className="interests-modal__title">{ __( 'What topics interest you?' ) }</h2>
-					<p className="interests-modal__subtitle">
-						{ __( 'Follow at least 3 topics to personalize your Reader feed.' ) }
-					</p>
+			<Modal onRequestClose={ onClose } size="large" className="interests-modal">
+				<VStack spacing={ 8 } className="interests-modal__content">
+					<VStack spacing={ 0 }>
+						<h2 className="interests-modal__title">{ __( 'What topics interest you?' ) }</h2>
+						<p className="interests-modal__subtitle">
+							{ __(
+								'​​Stay up-to-date with your favorite blogs and discover new voices—all from one place.'
+							) }
+						</p>
+						<p className="interests-modal__subtitle">
+							{ __( 'Follow at least 3 topics to personalize your feed.' ) }
path: client/reader/onboarding/interests-modal/index.tsx
user: login: Addison-Stavlo
body: In addition to the above, I wonder if we should increase the number required here by 1, or if we should reconsider the dailyprompt default now.
created_at: 2025-03-14T13:13:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -185,33 +190,23 @@ const InterestsModal: React.FC< InterestsModalProps > = ( { isOpen, onClose, onC
 		},
 	];
 
-	const headerActions = (
-		<>
-			<Button onClick={ onClose } variant="link">
-				{ __( 'Cancel' ) }
-			</Button>
-			<Button onClick={ handleContinue } variant="primary" disabled={ isContinueDisabled }>
-				{ __( 'Continue' ) }
-			</Button>
-		</>
-	);
-
 	return (
 		isOpen && (
-			<Modal
-				onRequestClose={ onClose }
-				isFullScreen
-				headerActions={ headerActions }
-				isDismissible={ false }
-				className="interests-modal"
-			>
-				<div className="interests-modal__content">
-					<h2 className="interests-modal__title">{ __( 'What topics interest you?' ) }</h2>
-					<p className="interests-modal__subtitle">
-						{ __( 'Follow at least 3 topics to personalize your Reader feed.' ) }
-					</p>
+			<Modal onRequestClose={ onClose } size="large" className="interests-modal">
+				<VStack spacing={ 8 } className="interests-modal__content">
+					<VStack spacing={ 0 }>
+						<h2 className="interests-modal__title">{ __( 'What topics interest you?' ) }</h2>
+						<p className="interests-modal__subtitle">
+							{ __(
+								'​​Stay up-to-date with your favorite blogs and discover new voices—all from one place.'
+							) }
+						</p>
+						<p className="interests-modal__subtitle">
+							{ __( 'Follow at least 3 topics to personalize your feed.' ) }
path: client/reader/onboarding/interests-modal/index.tsx
user: login: davemart-in
body: Thanks for the ping. I don't have a strong opinion here. I'd say just go with whatever feels the best to you.
created_at: 2025-03-14T20:29:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -185,33 +190,23 @@ const InterestsModal: React.FC< InterestsModalProps > = ( { isOpen, onClose, onC
 		},
 	];
 
-	const headerActions = (
-		<>
-			<Button onClick={ onClose } variant="link">
-				{ __( 'Cancel' ) }
-			</Button>
-			<Button onClick={ handleContinue } variant="primary" disabled={ isContinueDisabled }>
-				{ __( 'Continue' ) }
-			</Button>
-		</>
-	);
-
 	return (
 		isOpen && (
-			<Modal
-				onRequestClose={ onClose }
-				isFullScreen
-				headerActions={ headerActions }
-				isDismissible={ false }
-				className="interests-modal"
-			>
-				<div className="interests-modal__content">
-					<h2 className="interests-modal__title">{ __( 'What topics interest you?' ) }</h2>
-					<p className="interests-modal__subtitle">
-						{ __( 'Follow at least 3 topics to personalize your Reader feed.' ) }
-					</p>
+			<Modal onRequestClose={ onClose } size="large" className="interests-modal">
+				<VStack spacing={ 8 } className="interests-modal__content">
+					<VStack spacing={ 0 }>
+						<h2 className="interests-modal__title">{ __( 'What topics interest you?' ) }</h2>
+						<p className="interests-modal__subtitle">
+							{ __(
+								'​​Stay up-to-date with your favorite blogs and discover new voices—all from one place.'
+							) }
+						</p>
+						<p className="interests-modal__subtitle">
+							{ __( 'Follow at least 3 topics to personalize your feed.' ) }
path: client/reader/onboarding/interests-modal/index.tsx
user: login: ntsekouras
body: For now I increased the number in the check and kept the same copy. So while in practice the user would start with four tags, I think it's fine to add a default tag (`dailyprompt`) and not make the copy a lot bigger to try to explain this. 

It's an easy change though to go any other way like the suggestions above..
created_at: 2025-03-17T11:14:55Z
author_association: MEMBER
diff_hunk: @@ -41,7 +41,7 @@ export default function ( props ) {
 				<ConversationTitle title={ props.title } />
 				<NavigationHeader
 					title={ translate( 'Conversations' ) }
-					subtitle={ translate( 'Monitor all of your ongoing discussions.' ) }
+					subtitle={ translate( 'Check in on your comments.' ) }
path: client/reader/conversations/stream.js
user: login: Addison-Stavlo
body: For these copy changes, we could supply the old strings as translation fallbacks. It is likely not all of these new stings are fully translated in mag-16, so as is we would either ship and have translation gaps infront of users, or hold merging this on the string-freeze label to wait for the new translations. But with fallbacks, we can ship immediately and cover the gaps by having the old translations continue appear until the new copy is translated for that specific locale.

Previously we had to do something like ` hasTranslation( newCopy ) ? translate( newCopy ) : translate( oldCopy )`, but I think more recently there is a `fixMe` helper added to `i18n-calypso`. I haven't gotten the chance to use it in calypso yet but I think this might be a good place to use it.
created_at: 2025-03-19T11:21:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,6 +1,11 @@
 import { recordTracksEvent } from '@automattic/calypso-analytics';
 import { SelectCardCheckbox } from '@automattic/onboarding';
-import { Modal, Button } from '@wordpress/components';
+import {
+	Modal,
+	Button,
+	__experimentalVStack as VStack,
+	__experimentalHStack as HStack,
path: client/reader/onboarding/interests-modal/index.tsx
user: login: Addison-Stavlo
body: These seem good and helpful! Do you have a sense how "experimental" (or stable) these are?
created_at: 2025-03-19T11:33:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -41,7 +41,7 @@ export default function ( props ) {
 				<ConversationTitle title={ props.title } />
 				<NavigationHeader
 					title={ translate( 'Conversations' ) }
-					subtitle={ translate( 'Monitor all of your ongoing discussions.' ) }
+					subtitle={ translate( 'Check in on your comments.' ) }
path: client/reader/conversations/stream.js
user: login: Addison-Stavlo
body: I also just wanted to note I find this specific new copy for comments maybe a little odd. The welcome card mentions the area as:

> WordPress posts you've written, followed, or commented on will appear here when they have new comments. Posts with the most recent comments appear on top.

Given that, I don't think half the things here to check on are necessarily "my comments". They could be posts I followed getting comments, or posts I commented on getting new comments from others, etc. The "ongoing discussions" verbage seems maybe a little more accurate.

That said, that welcome card exists for a reason and supplies the more detailed description so this may all be fine and I don't mean it as a blocker in any way.
created_at: 2025-03-19T11:56:24Z
author_association: CONTRIBUTOR
diff_hunk: @@ -41,7 +41,7 @@ export default function ( props ) {
 				<ConversationTitle title={ props.title } />
 				<NavigationHeader
 					title={ translate( 'Conversations' ) }
-					subtitle={ translate( 'Monitor all of your ongoing discussions.' ) }
+					subtitle={ translate( 'Check in on your comments.' ) }
path: client/reader/conversations/stream.js
user: login: michaelpick
body: Good call, @Addison-Stavlo. 

How about 'Check in on your open discussions.'?
created_at: 2025-03-19T15:27:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -185,33 +190,23 @@ const InterestsModal: React.FC< InterestsModalProps > = ( { isOpen, onClose, onC
 		},
 	];
 
-	const headerActions = (
-		<>
-			<Button onClick={ onClose } variant="link">
-				{ __( 'Cancel' ) }
-			</Button>
-			<Button onClick={ handleContinue } variant="primary" disabled={ isContinueDisabled }>
-				{ __( 'Continue' ) }
-			</Button>
-		</>
-	);
-
 	return (
 		isOpen && (
-			<Modal
-				onRequestClose={ onClose }
-				isFullScreen
-				headerActions={ headerActions }
-				isDismissible={ false }
-				className="interests-modal"
-			>
-				<div className="interests-modal__content">
-					<h2 className="interests-modal__title">{ __( 'What topics interest you?' ) }</h2>
-					<p className="interests-modal__subtitle">
-						{ __( 'Follow at least 3 topics to personalize your Reader feed.' ) }
-					</p>
+			<Modal onRequestClose={ onClose } size="large" className="interests-modal">
+				<VStack spacing={ 8 } className="interests-modal__content">
+					<VStack spacing={ 0 }>
+						<h2 className="interests-modal__title">{ __( 'What topics interest you?' ) }</h2>
+						<p className="interests-modal__subtitle">
+							{ __(
+								'​​Stay up-to-date with your favorite blogs and discover new voices—all from one place.'
+							) }
+						</p>
+						<p className="interests-modal__subtitle">
+							{ __( 'Follow at least 3 topics to personalize your feed.' ) }
path: client/reader/onboarding/interests-modal/index.tsx
user: login: michaelpick
body: > Reader: Update interests Modal by ntsekouras · Pull Request #101314 · Automattic/wp-calypso

I really like this approach!
created_at: 2025-03-19T15:31:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -41,7 +41,7 @@ export default function ( props ) {
 				<ConversationTitle title={ props.title } />
 				<NavigationHeader
 					title={ translate( 'Conversations' ) }
-					subtitle={ translate( 'Monitor all of your ongoing discussions.' ) }
+					subtitle={ translate( 'Check in on your comments.' ) }
path: client/reader/conversations/stream.js
user: login: ntsekouras
body: I didn't know about `fixMe` function @Addison-Stavlo , thank you. I'll use that.
created_at: 2025-03-19T15:50:43Z
author_association: MEMBER
diff_hunk: @@ -1,6 +1,11 @@
 import { recordTracksEvent } from '@automattic/calypso-analytics';
 import { SelectCardCheckbox } from '@automattic/onboarding';
-import { Modal, Button } from '@wordpress/components';
+import {
+	Modal,
+	Button,
+	__experimentalVStack as VStack,
+	__experimentalHStack as HStack,
path: client/reader/onboarding/interests-modal/index.tsx
user: login: ntsekouras
body: They are stable and heavily used in GB and core, despite their name. They are in core for a while now.
created_at: 2025-03-19T16:03:31Z
author_association: MEMBER

PR comments:
user: login: github-actions[bot]
created_at: 2025-03-13T13:44:03Z
body: <details>
<summary>Calypso Live <a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-137658">(direct link)</a></summary>
<table>
<tr>
<td>
<img src="https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl=https%3A%2F%2Fcalypso.live%3Fimage%3Dregistry.a8c.com%2Fcalypso%2Fapp%3Abuild-137658%26flags%3Doauth&choe=UTF-8" />
</td>
<td>
<a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-137658">https://calypso.live?image=registry.a8c.com/calypso/app:build-137658</a>
</td>
</tr>
</table>
</details>
<details>
<summary>Jetpack Cloud live <a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-137658&env=jetpack">(direct link)</a></summary>
<table>
<tr>
<td>
<img src="https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl=https%3A%2F%2Fcalypso.live%3Fimage%3Dregistry.a8c.com%2Fcalypso%2Fapp%3Abuild-137658%26env%3Djetpack%26flags%3Doauth&choe=UTF-8" />
</td>
<td>
<a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-137658&env=jetpack">https://calypso.live?image=registry.a8c.com/calypso/app:build-137658&env=jetpack</a>
</td>
</tr>
</table>
</details>
<details>
<summary>Automattic for Agencies live <a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-137658&env=a8c-for-agencies">(direct link)</a></summary>
<table>
<tr>
<td>
<img src="https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl=https%3A%2F%2Fcalypso.live%3Fimage%3Dregistry.a8c.com%2Fcalypso%2Fapp%3Abuild-137658%26env%3Da8c-for-agencies%26flags%3Doauth&choe=UTF-8" />
</td>
<td>
<a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-137658&env=a8c-for-agencies">https://calypso.live?image=registry.a8c.com/calypso/app:build-137658&env=a8c-for-agencies</a>
</td>
</tr>
</table>
</details>
<!--calypso-live-watermark:apr@v1-->
author_association: NONE
user: login: matticbot
created_at: 2025-03-13T13:44:42Z
body: <!-- icfy-watermark: c52822 -->
Here is how your PR affects size of JS and CSS bundles shipped to the user's browser:

**Sections** (~265 bytes added 📈 [gzipped])
<details>

```
name    parsed_size           gzip_size
reader      +1081 B  (+0.0%)     +265 B  (+0.0%)
```

Sections contain code specific for a given set of routes. Is downloaded and parsed only when a particular route is navigated to.
</details>

**Async-loaded Components** (~53 bytes added 📈 [gzipped])
<details>

```
name                                            parsed_size           gzip_size
async-load-calypso-reader-conversations-stream       +155 B  (+2.4%)      +53 B  (+2.2%)
```

React components that are loaded lazily, when a certain part of UI is displayed for the first time.
</details>

**Legend**
<details>
<summary>What is parsed and gzip size?</summary>

**Parsed Size:** Uncompressed size of the JS and CSS files. This much code needs to be parsed and stored in memory.
**Gzip Size:** Compressed size of the JS and CSS files. This much data needs to be downloaded over network.
</details>

Generated by performance advisor bot at [iscalypsofastyet.com](http://iscalypsofastyet.com).
author_association: CONTRIBUTOR
user: login: jasmussen
created_at: 2025-03-14T09:16:20Z
body: Nice one. Yes, this even came up in a consistency pass we did: UghCEspEeHFI3E1kRJeyOZ-fi-39927_15933. Mockup:

<img width="1920" alt="reader-welcome" src="https://github.com/user-attachments/assets/78ba0226-bdd1-4294-8b4d-b806553b710c" />

👍 👍

I wasn't able to review it this morning, so reviewing based on the visuals. 
author_association: MEMBER
user: login: matticbot
created_at: 2025-03-14T09:41:05Z
body: **This PR modifies the release build for the following Calypso Apps:**

_For info about this notification, see here: PCYsg-OT6-p2_

* notifications
* wpcom-block-editor

To test WordPress.com changes, run `install-plugin.sh $pluginSlug update/reader-interests-modal` on your sandbox.
<!--calypso-app-artifacts-watermark:apr@v1-->
author_association: CONTRIBUTOR
user: login: Addison-Stavlo
created_at: 2025-03-14T12:34:01Z
body: The subtitles are a great change, but the width and button placement change here puts the reader onboarding in an inconsistent state visually.

Instead of all steps having the same width and button placement. We have the first step with a different width and button placement than those that follow:

Step 1:
![Screenshot 2025-03-14 at 8 27 26 AM](https://github.com/user-attachments/assets/d4434fa5-c4e6-4df8-a17e-7fe395503c8e)

On pressing "continue" goes to:

Step 2:
![Screenshot 2025-03-14 at 8 30 58 AM](https://github.com/user-attachments/assets/64ab645c-4d5b-45dc-b597-e47cf48447ae)

^^ and this one is a bit more difficult to want to make narrow IMO, since we would lose the dual column view.
author_association: CONTRIBUTOR
user: login: jasmussen
created_at: 2025-03-14T12:43:29Z
body: Good point, those two need updating at the same time. Perhaps it needs to be set to "fill" in size, after all?
author_association: MEMBER
user: login: ntsekouras
created_at: 2025-03-17T09:23:09Z
body: >Good point, those two need updating at the same time. Perhaps it needs to be set to "fill" in size, after all?

How should we proceed with this PR?

Do we need to make some changes to other Modals too, regarding the buttons' placement and/or the Modal size?

Should we restrict the changes to some copy `subtitle` changes?


author_association: MEMBER
user: login: jasmussen
created_at: 2025-03-17T09:48:36Z
body: > How should we proceed with this PR?

Can you set the modal to `fill` (https://wordpress.github.io/gutenberg/?path=/docs/components-modal--docs), and update both modals, with continue buttons in the bottom right?
author_association: MEMBER
user: login: ntsekouras
created_at: 2025-03-19T08:32:53Z
body: @jasmussen @Addison-Stavlo is anything more needed here?
author_association: MEMBER
user: login: Addison-Stavlo
created_at: 2025-03-19T11:39:33Z
body: > I'm not sure if there is an easier way to do this, but I changed [this condition](https://github.com/Automattic/wp-calypso/blob/trunk/client/reader/following/main.tsx#L33) to if ( true ).

I just found it, so maybe not helpful this late in the PR but for future reference:  apparently there is a flag here for `reader/force-onboarding`, so if you append `?flags=reader/force-onboarding` in the url it should bring the modals up.
author_association: CONTRIBUTOR
user: login: a8ci18n
created_at: 2025-03-20T10:23:52Z
body: This Pull Request is now available for translation here: https://translate.wordpress.com/deliverables/17307762

Some locales (Brazilian Portuguese, Hebrew, Japanese) have been temporarily machine-translated due to translator availability. All other translations are usually ready within a few days. Untranslated and machine-translated strings will be sent for translation next Monday and are expected to be completed by the following Friday.

Thank you @ntsekouras for including a screenshot in the description! This is really helpful for our translators.
author_association: NONE