Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
3365c0a
feat: reader modal install prompt demo (mockup)
tsahimatsliah May 14, 2026
0604f09
feat: polish reader chrome and install prompt UX
tsahimatsliah May 14, 2026
a5bc685
feat(reader-demo): bigger reader shell + browser-style install prompt
tsahimatsliah May 14, 2026
2578fec
feat(reader-demo): tighter reader shell + cleaner browser-chrome inst…
tsahimatsliah May 14, 2026
5e26398
fix(reader-demo): post page matches modal shell exactly
tsahimatsliah May 14, 2026
3c84ce1
fix(reader-demo): cleaner install prompt — mockup chrome, full-width,…
tsahimatsliah May 14, 2026
d26d2c5
feat(reader-demo): post-page chrome polish — back-to-feed, inline men…
tsahimatsliah May 14, 2026
53633a3
feat(reader-demo): warmer permission prompt + floating opt-out button
tsahimatsliah May 14, 2026
29da72f
feat(reader-demo): bigger reader shell + redesigned install prompt
tsahimatsliah May 14, 2026
b253def
fix(reader-demo): flat outlined Maybe later button in permission prompt
tsahimatsliah May 14, 2026
227dd5f
fix(reader-demo): warmer install prompt headline
tsahimatsliah May 14, 2026
648df88
feat(reader-demo): widen shell, add new-tab escape, tighten composer
tsahimatsliah May 14, 2026
efc5d1f
fix(reader-demo): match new-tab button style to preview button
tsahimatsliah May 14, 2026
cda2fe5
fix(reader-demo): vertically center URL bar contents
tsahimatsliah May 14, 2026
361a1da
fix(reader-demo): force reader + install modals to honor max-w cap
tsahimatsliah May 14, 2026
b02fb61
fix(reader-demo): push preview copy, icon, and header polish
tsahimatsliah May 14, 2026
a105156
fix(reader-demo): polish permission prompt escape and ambient state
tsahimatsliah May 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 51 additions & 49 deletions packages/extension/src/frame/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,54 +23,54 @@ const ensureStyles = (): void => {
position: absolute;
inset: 0;
overflow: hidden;
opacity: 0.44;
opacity: 0.5;
background:
repeating-linear-gradient(
120deg,
rgba(255, 255, 255, 0.06) 0,
rgba(255, 255, 255, 0.06) 0.75rem,
transparent 0.75rem,
transparent 1.5rem
radial-gradient(
circle at 50% 42%,
rgba(192, 41, 240, 0.18) 0,
transparent 18rem
),
linear-gradient(
180deg,
rgba(255, 255, 255, 0.02),
rgba(255, 255, 255, 0.04)
radial-gradient(
circle at 38% 58%,
rgba(57, 217, 138, 0.1) 0,
transparent 16rem
),
radial-gradient(
circle at 62% 58%,
rgba(82, 139, 255, 0.1) 0,
transparent 16rem
);
background-size: 190% 190%, 100% 100%;
animation: embeddedBrowsingStripeShift 42s linear infinite;
will-change: background-position;
animation: embeddedBrowsingGlow 6s ease-in-out infinite alternate;
will-change: opacity, transform;
}
.embedded-browsing-ambient::before {
content: '';
position: absolute;
inset: 0;
background: repeating-linear-gradient(
120deg,
transparent 0,
transparent 1.75rem,
rgba(255, 255, 255, 0.04) 1.75rem,
rgba(255, 255, 255, 0.04) 2.5rem
);
background-size: 220% 220%;
animation: embeddedBrowsingStripeShiftReverse 58s linear infinite;
opacity: 0.24;
top: 50%;
left: 50%;
width: 12rem;
height: 12rem;
border: 1px solid rgba(255, 255, 255, 0.16);
border-radius: 9999px;
opacity: 0.22;
transform: translate(-50%, -50%) scale(0.9);
animation: embeddedBrowsingPulse 3.8s ease-in-out infinite;
}
@keyframes embeddedBrowsingStripeShift {
0% { background-position: 0% 0%, 50% 50%; }
100% { background-position: 220% 120%, 50% 50%; }
@keyframes embeddedBrowsingGlow {
0% { opacity: 0.36; transform: scale(0.99); }
100% { opacity: 0.54; transform: scale(1.01); }
}
@keyframes embeddedBrowsingStripeShiftReverse {
0% { background-position: 220% 140%; }
100% { background-position: 0% 0%; }
@keyframes embeddedBrowsingPulse {
0% { opacity: 0.08; transform: translate(-50%, -50%) scale(0.82); }
55% { opacity: 0.22; }
100% { opacity: 0; transform: translate(-50%, -50%) scale(1.35); }
}
@media (prefers-reduced-motion: reduce) {
.embedded-browsing-ambient,
.embedded-browsing-ambient::before {
animation: none;
}
.embedded-browsing-ambient {
background-position: 50% 50%, 50% 50%;
opacity: 0.42;
}
.embedded-browsing-ambient::before {
Expand All @@ -82,7 +82,7 @@ const ensureStyles = (): void => {
z-index: 10;
display: flex;
width: 100%;
max-width: 40rem;
max-width: 24rem;
flex-shrink: 0;
flex-direction: column;
align-items: center;
Expand All @@ -99,6 +99,7 @@ const ensureStyles = (): void => {
}
.embedded-browsing-body {
margin: 0;
max-width: 21rem;
font-size: 0.9375rem;
line-height: 1.25rem;
color: #cfd6e6;
Expand Down Expand Up @@ -142,15 +143,16 @@ const ensureStyles = (): void => {
.embedded-browsing-button:disabled { opacity: 0.6; cursor: not-allowed; }
.embedded-browsing-button-secondary {
background: transparent;
color: #cfd6e6;
font-weight: 500;
min-width: 0;
padding: 0 0.75rem;
color: #e3e8f3;
border: 1.5px solid rgba(255, 255, 255, 0.28);
font-weight: 600;
}
.embedded-browsing-button-secondary:hover {
opacity: 1;
background: rgba(255, 255, 255, 0.08);
border-color: rgba(255, 255, 255, 0.42);
color: #ffffff;
transform: none;
opacity: 1;
transform: translateY(-1px);
}
`;
document.head.appendChild(style);
Expand Down Expand Up @@ -210,47 +212,47 @@ export const renderPermissionPrompt = ({

const heading = document.createElement('h2');
heading.className = 'embedded-browsing-heading';
heading.textContent = 'Enable embedded browsing';
heading.textContent = 'Read it right here.';

const description = document.createElement('p');
description.className = 'embedded-browsing-body';
description.textContent =
'To load websites inside daily.dev, allow this extension to modify response headers on embedded pages.';
'Enable reader preview to open articles inside daily.dev with the discussion next to them.';

const status = document.createElement('p');
status.className = 'embedded-browsing-status';
status.textContent =
'This is optional and only applies to pages embedded by daily.dev.';
status.textContent = 'Only for links you open from daily.dev.';

const actions = document.createElement('div');
actions.className = 'embedded-browsing-actions';

const button = document.createElement('button');
button.type = 'button';
button.className = 'embedded-browsing-button';
button.textContent = 'Enable for this browser';
button.textContent = 'Enable reader preview';

const resetButton = () => {
button.disabled = false;
};

button.addEventListener('click', async () => {
button.disabled = true;
status.textContent = 'Requesting permissions...';
status.textContent = 'Just a sec…';

const outcome = await onRequestPermission();
if (outcome === 'granted') {
status.textContent = 'Permissions granted. Reloading extension...';
status.textContent = "You're in. Reloading…";
return;
}

if (outcome === 'dismissed') {
status.textContent = 'Permission request was dismissed.';
status.textContent =
'Permission was dismissed — tap below when you’re ready.';
resetButton();
return;
}

status.textContent = 'Failed to enable embedded browsing.';
status.textContent = "Something didn't quite work. Try again?";
resetButton();
});

Expand All @@ -261,7 +263,7 @@ export const renderPermissionPrompt = ({
optOutButton.type = 'button';
optOutButton.className =
'embedded-browsing-button embedded-browsing-button-secondary';
optOutButton.textContent = "I'd rather not read inside daily.dev";
optOutButton.textContent = "Don't ask again, open new tab";
optOutButton.addEventListener('click', () => {
onOptOut();
});
Expand Down
24 changes: 4 additions & 20 deletions packages/shared/src/components/Feed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,6 @@ const SocialTwitterPostModal = dynamic(
),
);

const ReaderPostModal = dynamic(
() =>
import(
/* webpackChunkName: "readerPostModal" */ './modals/ReaderPostModal'
),
);

const BriefCardFeed = dynamic(
() =>
import(
Expand Down Expand Up @@ -544,20 +537,11 @@ export default function Feed<T>({
if (!selectedPost) {
return undefined;
}
const readerEligibleTypes = new Set([
PostType.Article,
PostType.Digest,
PostType.VideoYouTube,
]);
if (
isReaderModalFeatureReady &&
isReaderModalOn &&
readerEligibleTypes.has(selectedPost.type)
) {
return ReaderPostModal;
}
// DEMO ONLY: card clicks now always open the classic post modal so the
// user can see title / TL;DR first. The reader modal is reached via the
// new install-prompt pop-up's "Preview the experience" CTA instead.
return PostModalMap[selectedPost.type];
}, [selectedPost, isReaderModalFeatureReady, isReaderModalOn]);
}, [selectedPost]);

if (!loadedSettings || isFallback) {
return <></>;
Expand Down
12 changes: 11 additions & 1 deletion packages/shared/src/components/cards/common/PostCardHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { isSourceUserSource } from '../../../graphql/sources';
import { ReadArticleButton, getReadPostButtonIcon } from './ReadArticleButton';
import { getGroupedHoverContainer } from './common';
import { useBookmarkProvider, useFeedPreviewMode } from '../../../hooks';
import { useReaderInstallPromptGate } from '../../../hooks/useReaderInstallPromptGate';
import type { Post } from '../../../graphql/posts';
import {
getReadPostButtonText,
Expand Down Expand Up @@ -66,6 +67,15 @@ export const PostCardHeader = ({
const { highlightBookmarkedPost } = useBookmarkProvider({
bookmarked: (post.bookmarked && !showFeedback) ?? false,
});
const { onReadClick: onReaderInstallGateClick } =
useReaderInstallPromptGate(post);

const handleReadArticleClick = (event: React.MouseEvent) => {
if (onReaderInstallGateClick(event)) {
return;
}
onReadArticleClick?.(event);
};

const articleLink = useMemo(() => {
if (post.sharedPost) {
Expand Down Expand Up @@ -118,7 +128,7 @@ export const PostCardHeader = ({
className="mr-2"
variant={ButtonVariant.Primary}
href={articleLink ?? ''}
onClick={onReadArticleClick}
onClick={handleReadArticleClick}
openNewTab={openNewTab}
icon={getReadPostButtonIcon(post)}
/>
Expand Down
Loading
Loading