Skip to content

feat: reader modal install prompt demo (mockup)#6052

Open
tsahimatsliah wants to merge 17 commits into
mainfrom
feat/reader-modal-install-prompt-demo
Open

feat: reader modal install prompt demo (mockup)#6052
tsahimatsliah wants to merge 17 commits into
mainfrom
feat/reader-modal-install-prompt-demo

Conversation

@tsahimatsliah
Copy link
Copy Markdown
Member

@tsahimatsliah tsahimatsliah commented May 14, 2026

Summary

This PR is a non-production mockup for design review and screen recording. Engineering will build the real version in a separate PR — the changes here are scoped to the reader_modal experiment and gated by // DEMO ONLY comments.

Three changes:

  1. Card / post-modal click flow — clicking a card now opens the classic post modal (title + TL;DR + actions). Clicking the Read post button on the card hover or inside the modal opens a new install-extension pop-up instead of navigating away.
  2. Install pop-up (ReaderInstallPromptModal) — blurred fake reader-preview background, Nikita-Bier-style headline + body, primary Install Chrome/Edge extension CTA, secondary Preview the experience CTA (demo-only path into the reader modal), tertiary open in new tab escape hatch. Reuses existing log events.
  3. Reader modal v2 layout — wider on large monitors (min(95vw, 118rem)), iframe swapped to the LEFT, engagement rail (TL;DR + tags + comments) swapped to the RIGHT, and the redundant title heading removed from the rail since the iframe shows the page title.

The reader experiment is force-enabled at useReaderModalEligibility so demo recordings don't depend on GrowthBook assignment.

Out of scope (do not implement from this PR)

  • Real extension-installed detection / persistence
  • Real onboarding gating logic — the Preview the experience CTA is a screen-recording aid only
  • EmbeddedBrowsingWebPrompt inline panel (the rail-fallback path) is intentionally left untouched
  • Mobile (<tablet) behavior — the reader experiment is tablet+ only

Test plan

  • node ./scripts/typecheck-strict-changed.js passes
  • pnpm --filter shared lint passes
  • pnpm --filter webapp lint passes
  • Card / post jest specs pass (184 / 184 in cards + PostHeaderActions + ReaderPostModal)
  • Manual: card click opens classic post modal, Read post opens install pop-up
  • Manual: Preview the experience from the install pop-up opens the reader modal with the new layout
  • Manual: /posts/[id] direct links also show the classic page with Read post CTA

Made with Cursor

Preview domain

https://feat-reader-modal-install-prompt.preview.app.daily.dev

DEMO ONLY: reshape the reader_modal experiment into a two-step flow for
team review. Force-enable the experiment, route card clicks to the
classic post modal, gate the "Read post" CTAs behind a new Nikita-Bier-
style install pop-up, and resize / swap sides on the reader modal so
the iframe sits on the left and the rail (TL;DR only, title dropped)
sits on the right. Not intended to ship as-is; engineering will build
the production version in a separate PR.

Co-authored-by: Cursor <cursoragent@cursor.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 14, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
daily-webapp Ready Ready Preview May 14, 2026 1:01pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
storybook Ignored Ignored May 14, 2026 1:01pm

Request Review

- Move close (X) from the iframe preview header to the engagement rail
  header next to the three-dots menu in modal mode. The iframe header
  keeps the X only when the rail is collapsed so users always have an
  escape hatch.
- Re-enable shouldUseReaderLayout on /posts/[id] and cap the reader
  page container to min(95vw, 118rem) centered, so the preview no
  longer stretches edge-to-edge on large monitors and matches the
  modal's footprint.
- Redesign the install prompt as a full-height reader-mimicking shell:
  - URL bar header with favicon + permalink (click to copy) on the left
  - Disabled three-dots + X cluster on the right
  - Two-column body: blurred fake article on the left, mocked rail on
    the right, install card overlaid in the center
  - Card copy and visual hierarchy reworked: badge, headline that
    promises the outcome, bullet list, primary install CTA, secondary
    preview CTA, and a trust microcopy line

Co-authored-by: Cursor <cursoragent@cursor.com>
- Bump default rail ratio (0.30 → 0.36) so the engagement rail starts
  with more breathing room without a manual drag.
- Bump reader modal + standalone post page max-width to min(96vw,132rem)
  for a more theater-sized reading shell on large displays.
- Redesign install prompt as a believable in-app browser: tab strip with
  traffic lights, back/forward/refresh, lock + permalink address bar,
  bookmark/menu/close. Drop the engagement rail and the misleading
  "Free. Works offline." microcopy. Sharper Nikita-Bier copy:
  "Read this inside daily.dev? Install the extension and {host} opens
  right here — no new tab, no context switching."

Co-authored-by: Cursor <cursoragent@cursor.com>
…all prompt

Reader modal / post page:
- Cap width at min(96vw, 76rem) so the article + rail stay legible and
  centered instead of stretching across ultrawide monitors.
- Lock rail to 380px and remove the drag-to-resize PaneDivider so the
  layout is deliberate (preview ~720-760px, rail 380px).

Install prompt:
- Collapse the two-row faux chrome (tab strip + URL bar) into one single
  browser bar: traffic lights, back/forward/refresh, URL pill (lock +
  favicon + permalink + star), menu, close.
- Replace the empty placeholder block with a full-width article preview
  that uses the real post title, source name/avatar, hero image, and
  read time. Only the body paragraphs stay blurred, so the surface
  reads as "we opened your article inside daily.dev".
- Drop the em-dash in the install card subtitle: now reads
  "Install the extension and {host} opens right here inside daily.dev.
  No new tab. No context switching."
- Match install modal width to reader modal width so the
  install → preview transition feels like just removing the overlay.

Co-authored-by: Cursor <cursoragent@cursor.com>
- MainLayout was adding `laptop:!pl-60` (240px expanded-sidebar inset)
  because the post page had `screenCentered: false`. That offset pushed
  the reader shell off-center and made the engagement rail anchor to
  the right edge of the viewport. Flipping the page to
  `screenCentered: true` removes the inset so the shell can center on
  the viewport like the modal portal does.
- Move the 76rem width cap + mx-auto centering INSIDE `ReaderPostLayout`
  itself (on a new inner wrapper) so the shell is always capped to the
  modal's footprint regardless of what the outer `outerClassName` does.
  The page now only sets viewport-height bounds via `outerClassName`.
- Net result: post page and modal render the exact same shell at the
  exact same width and behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>
… opaque card

- Force inner wrapper to w-full and add !w-full on the modal class so
  the prompt actually fills the modal width instead of shrinking to
  content.
- Browser chrome is now obviously a mockup:
  - drop the three-dots / menu button entirely
  - URL pill is a rounded rectangle (rounded-10) instead of an oval
    pill; lock + star icons removed; just favicon + URL
  - back / forward / refresh rendered as aria-hidden spans at low
    opacity so they read as decoration, not clickable controls
  - only the close (X) button stays interactive
- Background preview is now a heavily blurred (18px) abstract layout —
  no real title, source, or cover image to compete with the install
  card. Gradient overlay biases toward the page background so the
  card pops.
- Overlay card is fully opaque (`bg-background-default`, no backdrop
  blur, no /95 translucency) and gets a stronger shadow, so the
  heading is always crisp regardless of what's behind it.

Co-authored-by: Cursor <cursoragent@cursor.com>
…u, prominent CTAs

- Surface "Back to feed" inside the article preview header on the
  post page (left of the URL/favicon) via a new
  `leftHeaderActions` prop on `ArticleReaderFrame`. The rail header
  no longer renders its own back button.
- Add `border-l` to the article column so the shell has a visible
  left edge that matches the rail's `border-l` on the right.
- On the standalone post page, drop the rail's sticky header
  entirely and move `PostMenuOptions` inline next to the source's
  Follow button via a new `inlineHeaderMenu` prop on
  `EngagementRail`. The modal keeps its existing sticky header
  (three-dots + close).
- Make the `NewComment` composer the obvious discussion entry
  point: BlueCheese-accent border, action-comment surface, larger
  avatar, taller hit area, and a soft shadow so it can't be missed.
- Beef up `ReaderFloatingActionBar`: medium-size icons, h-11/w-11
  buttons, gap-2 between actions, px-3/py-2 padding, rounded-20
  pill so the bar reads as the primary "react to this post"
  surface instead of a thin chip.

Co-authored-by: Cursor <cursoragent@cursor.com>
Context: user has just installed the extension, returned to daily.dev,
and lands inside the iframe asking for embedded-browsing permission.
The previous screen ("Enable embedded browsing" / "Enable for this
browser" / "I'd rather not read inside daily.dev") read as a generic,
slightly intimidating second ask after the install. Rewrite the copy
in the Nikita-Bier register: continuation, not obstacle.

- Permission prompt (`packages/extension/src/frame/render.ts`):
  - Heading: "One tap to read in here."
  - Body: "Turn on embedded browsing and articles open right inside
    daily.dev. No new tabs, no bouncing around."
  - Reassurance: "We only use it on links you open from daily.dev."
  - Primary CTA: "Let's do it" (was "Enable for this browser")
  - Secondary CTA: "Maybe later" (was "I'd rather not read inside
    daily.dev")
  - Dynamic status lines warmer: "Just a sec…", "You're in.
    Reloading…", etc.
  - Secondary button is now a real floating button (subtle bg +
    1px border, matching the primary's dimensions) instead of a
    transparent text link, so it reads as a clear escape hatch.

- Web fallback install prompt (`EmbeddedBrowsingWebPrompt.tsx`):
  - Heading: "Read this inside daily.dev." (matches the install
    modal so the journey feels cohesive)
  - Body: shorter, value-first copy
  - Opt-out switched from `Tertiary` text button to `Float` button
    sized to match the install CTA.

Co-authored-by: Cursor <cursoragent@cursor.com>
- Drop traffic-light circles from the install prompt browser bar
- Repaint the backdrop as a heavily blurred white article page with
  richer skeleton content so it reads as a real webpage behind glass
- Sharpen the install prompt copy in a Nikita-Bier register
  ("Stop opening tabs.")
- Bump reader modal + post page max width to min(96vw, 88rem)
- Flatten the comment composer (neutral surface, slight border,
  no shadow)
- Wrap the post-page "Back to feed" button in the same chrome group
  as the eye toggle so they match visually
- Show "Close browser mode" label on the eye toggle inside the modal,
  keep icon-only on the standalone post page

Co-authored-by: Cursor <cursoragent@cursor.com>
tsahimatsliah and others added 2 commits May 14, 2026 12:29
Make the secondary opt-out button read clearly as a button: transparent
background with a 1.5px visible outline instead of a near-invisible
6% white fill that looked like plain text.

Co-authored-by: Cursor <cursoragent@cursor.com>
Swap "Stop opening tabs." for "Read it right here." — invitational
rather than pain-led, with a positive follow-up that highlights the
benefit (article + discussion side by side).

Co-authored-by: Cursor <cursoragent@cursor.com>
- Reader modal, install prompt and post page all share max width of
  min(96vw, 100rem) so the three surfaces render the same shell size
- Install prompt gets a third action: "Open the article in a new tab"
  for users who want the regular new-tab behavior. Routes around the
  install + preview flow entirely and logs ClickReaderInstallSkip.
- Eye toggle label inside the modal shortened to "Classic view"
  (was "Close browser mode") — clearer and shorter
- Comment composer scaled down: Medium avatar, p-2, callout type so
  the rail stops being dominated by an empty CTA

Co-authored-by: Cursor <cursoragent@cursor.com>
tsahimatsliah and others added 3 commits May 14, 2026 12:55
Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the asymmetric `pt-3 pb-2` with a symmetric `py-2` and lock a
min height (3.25rem / 52px) on the URL row so the back button, favicon,
URL and right-side chrome groups all sit on the same baseline in both
the modal and the post page.

Co-authored-by: Cursor <cursoragent@cursor.com>
ModalSize.XLarge applies a fixed `tablet:w-[69.25rem]` (1108px) which
silently overrode our `tablet:!max-w-[min(96vw,100rem)]` cap — the
modal was stuck at 1108px regardless of the requested width while the
post page rendered at 1382px+ on the same viewport.

Add an `!important` `tablet:!w-[min(96vw,100rem)]` alongside the
existing max-w so width and max-width line up, and the modal actually
fills the same shell as the post page.

Co-authored-by: Cursor <cursoragent@cursor.com>
Align the web and extension embedded-reader prompts, switch the reader
layout toggle to the globe icon, rename the reader exit action to
"Close preview", make the new-tab escape opt out of future prompts, and
match the preview and rail header heights.

Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the stripe animation in both web and extension prompts with a
subtle ambient glow/pulse, tighten prompt width to avoid awkward subtitle
wraps, and make the secondary escape explicit: "Don't ask again, open
new tab".

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

1 participant