From 4373d6bd99149c1e338b3884dbd9419f32974d0c Mon Sep 17 00:00:00 2001 From: tomeredlich Date: Wed, 2 Sep 2026 11:43:31 +0300 Subject: [PATCH 1/8] feat(snapshot): status moments review page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Splits the "Status moments" section out of #6544 so it can be reviewed on its own. Seven win moments that end in a dismiss — reading streak, achievements, leaderboard rank, top reader badge, streak tiers, being awarded, and post analytics — each drawn today / recommended / push. Lives at /dev/status-moments alongside the existing /dev/buttons and /dev/checkbox-radio review surfaces, so it renders in the real app shell rather than in Storybook. Gated to non-production builds and noindex. Adds the Snapshot icon the control needs. Everything on the page is inert: no data wiring, no capture, no feature flag. Co-Authored-By: Claude Opus 5 --- .../src/components/icons/Snapshot/filled.svg | 13 + .../src/components/icons/Snapshot/index.tsx | 10 + .../components/icons/Snapshot/outlined.svg | 11 + packages/shared/src/components/icons/index.ts | 1 + packages/webapp/pages/dev/status-moments.tsx | 705 ++++++++++++++++++ 5 files changed, 740 insertions(+) create mode 100644 packages/shared/src/components/icons/Snapshot/filled.svg create mode 100644 packages/shared/src/components/icons/Snapshot/index.tsx create mode 100644 packages/shared/src/components/icons/Snapshot/outlined.svg create mode 100644 packages/webapp/pages/dev/status-moments.tsx diff --git a/packages/shared/src/components/icons/Snapshot/filled.svg b/packages/shared/src/components/icons/Snapshot/filled.svg new file mode 100644 index 00000000000..d4cc05f0b56 --- /dev/null +++ b/packages/shared/src/components/icons/Snapshot/filled.svg @@ -0,0 +1,13 @@ + + + Icon/Snapshot/Filled + + + + + + + + + + diff --git a/packages/shared/src/components/icons/Snapshot/index.tsx b/packages/shared/src/components/icons/Snapshot/index.tsx new file mode 100644 index 00000000000..8707b229fad --- /dev/null +++ b/packages/shared/src/components/icons/Snapshot/index.tsx @@ -0,0 +1,10 @@ +import type { ReactElement } from 'react'; +import React from 'react'; +import type { IconProps } from '../../Icon'; +import Icon from '../../Icon'; +import OutlinedIcon from './outlined.svg'; +import FilledIcon from './filled.svg'; + +export const SnapshotIcon = (props: IconProps): ReactElement => ( + +); diff --git a/packages/shared/src/components/icons/Snapshot/outlined.svg b/packages/shared/src/components/icons/Snapshot/outlined.svg new file mode 100644 index 00000000000..af265154e03 --- /dev/null +++ b/packages/shared/src/components/icons/Snapshot/outlined.svg @@ -0,0 +1,11 @@ + + + Icon/Snapshot/Outline + + + + + + + + diff --git a/packages/shared/src/components/icons/index.ts b/packages/shared/src/components/icons/index.ts index 52ee9458013..5c1057b1724 100644 --- a/packages/shared/src/components/icons/index.ts +++ b/packages/shared/src/components/icons/index.ts @@ -150,6 +150,7 @@ export * from './Shortcuts'; export * from './Sidebar'; export * from './Sites'; export * from './Slack'; +export * from './Snapshot'; export * from './Sort'; export * from './Source'; export * from './Sparkle'; diff --git a/packages/webapp/pages/dev/status-moments.tsx b/packages/webapp/pages/dev/status-moments.tsx new file mode 100644 index 00000000000..992fafa7b7b --- /dev/null +++ b/packages/webapp/pages/dev/status-moments.tsx @@ -0,0 +1,705 @@ +import type { ReactElement, ReactNode } from 'react'; +import React from 'react'; +import { NextSeo } from 'next-seo'; +import { + Button, + ButtonSize, + ButtonVariant, +} from '@dailydotdev/shared/src/components/buttons/Button'; +import { + DownloadIcon, + MiniCloseIcon, + SnapshotIcon, +} from '@dailydotdev/shared/src/components/icons'; +import { isDevelopment } from '@dailydotdev/shared/src/lib/constants'; + +/** + * /dev/status-moments — internal review surface for the Snapshot sharing + * initiative. Seven win moments that end in a dismiss, drawn today / recommended + * / push so the placement call can be made against real screens. + * + * Gated to non-production builds. Carries `noindex` SEO regardless. + */ + +const AVATAR = + 'https://res.cloudinary.com/daily-now/image/upload/s--O0TOmw4y--/f_auto/v1715772965/public/noProfile'; + +const ART = + 'https://media.daily.dev/image/upload/s--_MjhSTze--/q_auto/v1773608417/achievements/cant_spend_it_all'; + +/* ---------------------------------------------------------------- chrome */ + +/** + * Inert on purpose: this page compares where a control sits inside a real + * screen, not what it does when pressed. + */ +const Control = ({ + className, + label, + size = ButtonSize.Small, + variant = ButtonVariant.Tertiary, +}: { + className?: string; + label?: boolean; + size?: ButtonSize; + variant?: ButtonVariant; +}) => ( + +); + +/** The frame every surface is drawn inside, so variants compare like for like. */ +const Screen = ({ children }: { children: ReactNode }) => ( +
+ {children} +
+); + +/** Screens sit in a scroller rather than wrapping, so widths stay honest. */ +const Rail = ({ children }: { children: ReactNode }) => ( +
+ {children} +
+); + +const Variant = ({ + step, + headline, + note, + children, +}: { + step: string; + headline: string; + note: string; + children: ReactNode; +}) => ( + // Full width so a rail can scroll across the whole canvas. +
+
+ + {step} + + + {headline} + + {note} +
+ {children} +
+); + +const Category = ({ + title, + covers, + verdict, + children, +}: { + title: string; + covers: string; + verdict: string; + children: ReactNode; +}) => ( +
+
+

{title}

+ {covers} +

+ {verdict} +

+
+
{children}
+
+); + +/* -------------------------------------------------------------- surfaces */ + +/** + * NewStreakModal: a reminder switch and close at the top, the fire art with + * the count overlaid in typo-tera, a title, one line of copy, the freeze + * upsell, and an opt-out checkbox. No share control, and no primary button. + */ +const StreakScreen = ({ spot }: { spot: 'today' | 'share' | 'milestone' }) => ( + +
+
+ + + Remind me + +
+ + + 🔥 + 100 + + + + {spot === 'milestone' ? 'New streak record!' : '100 days streak'} + +

+ {spot === 'milestone' + ? 'Epic win! You are in a league of your own' + : 'New milestone reached! You are unstoppable.'} +

+ + + Protect your streak with streak freezes + + + {spot !== 'today' && ( + + )} + + + + Never show this again + +
+
+); + +/** + * AchievementCard: a 48px thumbnail, name and description, then the snapshot + * button and the points. The snapshot is `opacity-0 group-hover:opacity-100`, + * so it is invisible until hover — and permanently invisible on touch. + */ +const AchievementScreen = ({ + spot, +}: { + spot: 'today' | 'card' | 'celebration'; +}) => ( + +
+ {spot === 'celebration' && ( + + Just unlocked + + )} + +
+
+ +
+ + Can't spend it all + + + Hold more than 10,000 cores without spending any of them. + +
+
+ {spot !== 'today' && ( + + )} + + 120 + +
+
+ + {spot !== 'celebration' && ( +
+ + Progress + 8/10 + + + + +
+ )} +
+
+
+); + +/** + * UserTopList rows: a w-14 tabular score, TopRankBadge, an optional level + * ring, then UserHighlight (32px avatar, caption1 name, caption2 handle). + * The snapshot is `opacity-0 group-hover:opacity-100` at XSmall Float — + * shipped, and invisible on touch. + */ +const RankScreen = ({ spot }: { spot: 'today' | 'hover' | 'band' }) => ( + +
+ {spot === 'band' && ( +
+
+ + You're #1 this week + + + Highest level · 103 + +
+ +
+ )} + +

+ Highest level +

+ +
    + {[ + ['Bobby Iliev', 'bobbyiliev', 103], + ['Ante Barić', 'antebaric', 99], + ['Ido Shamun', 'idoshamun', 95], + ].map(([name, handle, score], index) => ( +
  1. + + {score} + + + {index === 0 ? '🥇' : `#${index + 1}`} + +
    + +
    + + {name} + + + @{handle} + +
    +
    + {index === 0 && spot === 'hover' && ( + + )} +
  2. + ))} +
+
+
+); + +/* -------------------------------------------------- other win moments */ + +const TopReaderScreen = ({ share }: { share: boolean }) => ( + +
+
+ 🥇 +
+

+ You've earned the top reader badge! +

+

+ Top 1% of readers in #typescript this week +

+
+ + {share && } +
+
+
+); + +const WEEK: [string, string][] = [ + ['Monday', 'M'], + ['Tuesday', 'T'], + ['Wednesday', 'W'], + ['Thursday', 'T'], + ['Friday', 'F'], + ['Saturday', 'S'], + ['Sunday', 'S'], +]; + +const TIER_DAYS: [string, number][] = [ + ['Spark', 3], + ['Flame', 7], + ['Inferno', 30], + ['Supernova', 180], +]; + +const StreakTierScreen = ({ share }: { share: boolean }) => ( + +
+
+ 🔥 +
+ + Inferno + + 30 +

A full month, unbroken

+
+ {WEEK.map(([name, initial], index) => ( + + {initial} + + ))} +
+
+ {TIER_DAYS.map(([label, day]) => ( + + {label} · {day}d + + ))} +
+ {share && ( + + )} +
+
+); + +/** + * The award moment, from the recipient's side. ListAwardsModal shows who gave + * what and the cores total; the person who received it gets no way to mark it. + */ +const AwardedScreen = ({ share }: { share: boolean }) => ( + +
+
+ + Awards given + +
+ +
+ + 🪙 + +
+ Cores given + 1,250 +
+ {share && ( + + )} +
+ + {['Bobby Iliev', 'Ante Barić', 'Ido Shamun'].map((name) => ( +
+ + + {name} + + 🏅 +
+ ))} +
+
+); + +const POST_STATS: [string, string][] = [ + ['Impressions', '41.2K'], + ['Upvotes', '862'], + ['Comments', '134'], + ['Clicks', '3.8K'], + ['Followers gained', '96'], + ['Cores earned', '1,250'], +]; + +/** posts/[id]/analytics, behind canViewPostAnalytics. */ +const AnalyticsScreen = ({ share }: { share: boolean }) => ( + +
+
+
+ + Post analytics + + + Why iconic tech brands lost their dominance + +
+ {share && } +
+ +
+ +
+ {POST_STATS.map(([label, value]) => ( +
+ + {value} + + {label} +
+ ))} +
+ + {share && } +
+ +); + +/* ------------------------------------------------------------------ page */ + +const ProductionGate = ({ children }: { children: ReactNode }) => { + if (!isDevelopment) { + return ( +
+

+ The status moments review page is only available in development. +

+
+ ); + } + return <>{children}; +}; + +const StatusMomentsDevPage = (): ReactElement => ( + + +
+
+
+

+ Status moments +

+

+ Seven surfaces that share one property: there is no page to send + anyone to. A link to your streak, your rank or your unlocked + achievement means nothing to the person receiving it. Snapshot is + not the louder option here — it is the only one. +

+

+ Sharing map: lead with Snapshot on all three (#6358 streak, #6360 + achievements, #6359 rank). Copy link is not a secondary option, it + is absent, because there is nothing to link to. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+
+ +); + +StatusMomentsDevPage.getLayout = (page: ReactNode): ReactNode => page; + +export default StatusMomentsDevPage; From 6260c50a7d71b2d4b99aa379087c46cfcfa80610 Mon Sep 17 00:00:00 2001 From: tomeredlich Date: Wed, 2 Sep 2026 16:47:29 +0300 Subject: [PATCH 2/8] chore(snapshot): trim commentary the code already carries The six surface docblocks walked through the JSX beneath them, and two restated copy that the page already renders in its own `note` and `verdict` props. The achievement block also described hover behaviour this page does not implement. Replaced with the one-line source reference the analytics screen already used, so each screen names the real component it redraws and nothing else. Co-Authored-By: Claude Opus 5 --- packages/webapp/pages/dev/status-moments.tsx | 32 +++++--------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/packages/webapp/pages/dev/status-moments.tsx b/packages/webapp/pages/dev/status-moments.tsx index 992fafa7b7b..b5fca7a9038 100644 --- a/packages/webapp/pages/dev/status-moments.tsx +++ b/packages/webapp/pages/dev/status-moments.tsx @@ -15,10 +15,8 @@ import { isDevelopment } from '@dailydotdev/shared/src/lib/constants'; /** * /dev/status-moments — internal review surface for the Snapshot sharing - * initiative. Seven win moments that end in a dismiss, drawn today / recommended - * / push so the placement call can be made against real screens. - * - * Gated to non-production builds. Carries `noindex` SEO regardless. + * initiative. Every screen below is a redraw of a real one; the reference is + * named above each. */ const AVATAR = @@ -120,11 +118,7 @@ const Category = ({ /* -------------------------------------------------------------- surfaces */ -/** - * NewStreakModal: a reminder switch and close at the top, the fire art with - * the count overlaid in typo-tera, a title, one line of copy, the freeze - * upsell, and an opt-out checkbox. No share control, and no primary button. - */ +/** NewStreakModal.tsx — the streak milestone popup. */ const StreakScreen = ({ spot }: { spot: 'today' | 'share' | 'milestone' }) => (
@@ -172,11 +166,7 @@ const StreakScreen = ({ spot }: { spot: 'today' | 'share' | 'milestone' }) => ( ); -/** - * AchievementCard: a 48px thumbnail, name and description, then the snapshot - * button and the points. The snapshot is `opacity-0 group-hover:opacity-100`, - * so it is invisible until hover — and permanently invisible on touch. - */ +/** AchievementCard.tsx — the unlock card. */ const AchievementScreen = ({ spot, }: { @@ -238,12 +228,7 @@ const AchievementScreen = ({ ); -/** - * UserTopList rows: a w-14 tabular score, TopRankBadge, an optional level - * ring, then UserHighlight (32px avatar, caption1 name, caption2 handle). - * The snapshot is `opacity-0 group-hover:opacity-100` at XSmall Float — - * shipped, and invisible on touch. - */ +/** UserTopList.tsx — the leaderboard rows. */ const RankScreen = ({ spot }: { spot: 'today' | 'hover' | 'band' }) => (
@@ -314,6 +299,7 @@ const RankScreen = ({ spot }: { spot: 'today' | 'hover' | 'band' }) => ( /* -------------------------------------------------- other win moments */ +/** TopReaderBadgeModal.tsx — download only, no share route. */ const TopReaderScreen = ({ share }: { share: boolean }) => (
@@ -358,6 +344,7 @@ const TIER_DAYS: [string, number][] = [ ['Supernova', 180], ]; +/** StreakOfferCelebration.tsx, over the tiers in streakTiers.ts. */ const StreakTierScreen = ({ share }: { share: boolean }) => (
@@ -404,10 +391,7 @@ const StreakTierScreen = ({ share }: { share: boolean }) => ( ); -/** - * The award moment, from the recipient's side. ListAwardsModal shows who gave - * what and the cores total; the person who received it gets no way to mark it. - */ +/** ListAwardsModal.tsx, from the recipient's side. */ const AwardedScreen = ({ share }: { share: boolean }) => (
From f5341de3258a1eb1f38922599e0f12e9fe724877 Mon Sep 17 00:00:00 2001 From: tomeredlich Date: Wed, 2 Sep 2026 18:19:44 +0300 Subject: [PATCH 3/8] refactor(snapshot): draw the status moment screens with real components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The screens hand-rolled five parts the design system already ships: the reminder toggle, the opt-out checkbox, the achievement progress bar, the leaderboard avatars and the rank badges were raw spans with styling typed in directly. Swapped for Switch, Checkbox, ProgressBar, ProfilePicture and TopRankBadge. The rank column changes visibly and deliberately: TopRankBadge draws the gold/silver/bronze medals the real leaderboard draws, replacing a 🥇 emoji and "#2"/"#3" text. Mockup-to-eng-pass: 1 Co-Authored-By: Claude Opus 5 --- packages/webapp/pages/dev/status-moments.tsx | 49 ++++++++++++-------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/packages/webapp/pages/dev/status-moments.tsx b/packages/webapp/pages/dev/status-moments.tsx index b5fca7a9038..e378f73d698 100644 --- a/packages/webapp/pages/dev/status-moments.tsx +++ b/packages/webapp/pages/dev/status-moments.tsx @@ -11,6 +11,14 @@ import { MiniCloseIcon, SnapshotIcon, } from '@dailydotdev/shared/src/components/icons'; +import { Switch } from '@dailydotdev/shared/src/components/fields/Switch'; +import { Checkbox } from '@dailydotdev/shared/src/components/fields/Checkbox'; +import { ProgressBar } from '@dailydotdev/shared/src/components/fields/ProgressBar'; +import { + ProfileImageSize, + ProfilePicture, +} from '@dailydotdev/shared/src/components/ProfilePicture'; +import { TopRankBadge } from '@dailydotdev/shared/src/components/cards/Leaderboard/TopRankBadge'; import { isDevelopment } from '@dailydotdev/shared/src/lib/constants'; /** @@ -123,10 +131,9 @@ const StreakScreen = ({ spot }: { spot: 'today' | 'share' | 'milestone' }) => (
- - + Remind me - +
); @@ -218,9 +224,14 @@ const AchievementScreen = ({ Progress 8/10 - - - +
)}
@@ -265,14 +276,12 @@ const RankScreen = ({ spot }: { spot: 'today' | 'hover' | 'band' }) => ( {score} - - {index === 0 ? '🥇' : `#${index + 1}`} - +
-
@@ -423,10 +432,10 @@ const AwardedScreen = ({ share }: { share: boolean }) => ( {['Bobby Iliev', 'Ante Barić', 'Ido Shamun'].map((name) => (
- {name} From 076561bf46cba8e58a5093cba244b004fa0af6ac Mon Sep 17 00:00:00 2001 From: tomeredlich Date: Thu, 3 Sep 2026 12:11:46 +0300 Subject: [PATCH 4/8] feat(snapshot): redraw the streak screens on the milestone-rewards design MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The streak screens were drawn from the old popup: a 🔥 emoji with the count overlaid, a text tier pill and a hand-built day row. The milestone-rewards review (claude/milestone-rewards-storybook-764fa6, Milestone Rewards/Final review) supersedes it. Both screens now use that celebration panel — the Inferno tier artwork over an ember wash, the tier chip, a tabular day count and the week strip — with the first-party decision column under it: Cores and freezes as option rows, then No thanks. The streak popup no longer has a reminder toggle or a "never show this again" checkbox, so Switch and Checkbox are gone with them. Not brought over: the sponsored-gift half of that review (partner offers, claim sheet, gift vault) and the ember and entrance animations. This page compares control placement across eleven screens. Mockup-to-eng-pass: 2 Co-Authored-By: Claude Opus 5 --- packages/webapp/pages/dev/status-moments.tsx | 279 +++++++++++------- .../webapp/public/streak-tiers/inferno.png | Bin 0 -> 39849 bytes 2 files changed, 179 insertions(+), 100 deletions(-) create mode 100644 packages/webapp/public/streak-tiers/inferno.png diff --git a/packages/webapp/pages/dev/status-moments.tsx b/packages/webapp/pages/dev/status-moments.tsx index e378f73d698..43263572f51 100644 --- a/packages/webapp/pages/dev/status-moments.tsx +++ b/packages/webapp/pages/dev/status-moments.tsx @@ -7,12 +7,13 @@ import { ButtonVariant, } from '@dailydotdev/shared/src/components/buttons/Button'; import { + CoreIcon, DownloadIcon, MiniCloseIcon, + ShieldPlusIcon, SnapshotIcon, } from '@dailydotdev/shared/src/components/icons'; -import { Switch } from '@dailydotdev/shared/src/components/fields/Switch'; -import { Checkbox } from '@dailydotdev/shared/src/components/fields/Checkbox'; +import { IconSize } from '@dailydotdev/shared/src/components/Icon'; import { ProgressBar } from '@dailydotdev/shared/src/components/fields/ProgressBar'; import { ProfileImageSize, @@ -124,50 +125,180 @@ const Category = ({ ); -/* -------------------------------------------------------------- surfaces */ +/* --------------------------------------------------- streak celebration */ -/** NewStreakModal.tsx — the streak milestone popup. */ -const StreakScreen = ({ spot }: { spot: 'today' | 'share' | 'milestone' }) => ( - -
-
- - Remind me - -
+/** Day 30 on the streak ladder: milestone-rewards `data.ts`. */ +const INFERNO = { + art: '/streak-tiers/inferno.png', + day: 30, + headline: 'A full month, unbroken', + label: 'Inferno', + reward: '50 Cores', +}; + +const WEEK = ['M', 'T', 'W', 'T', 'F', 'S', 'S']; - - 🔥 - 100 +/** The ember wash behind the flame, from `moment.tsx` PanelTone.Fire. */ +const FIRE = + 'radial-gradient(120% 100% at 20% 0%, rgba(236,82,122,0.38) 0%, rgba(236,82,122,0.22) 42%, rgba(15,18,24,0) 78%), linear-gradient(160deg, rgba(177,75,215,0.18) 0%, rgba(15,18,24,0) 60%)'; + +/** + * The celebration half: tier art over a warm glow, the tier name, the count. + * The embers and the staged entrance are dropped — this page compares control + * placement, and a particle system on eleven screens is noise. + */ +const Celebration = () => ( +
+ + + + + + + {INFERNO.label} + + +
+ + + {INFERNO.day} + + day streak +

{INFERNO.headline}

+
- - {spot === 'milestone' ? 'New streak record!' : '100 days streak'} - -

- {spot === 'milestone' - ? 'Epic win! You are in a league of your own' - : 'New milestone reached! You are unstoppable.'} -

+
+ {WEEK.map((day, index) => ( + + {day} + + ))} +
+
+); - - Protect your streak with streak freezes +/** The list primitive the decision column is built from. */ +const OptionRow = ({ + action, + icon, + meta, + primary, + title, +}: { + action: string; + icon: ReactNode; + meta: string; + primary?: boolean; + title: string; +}) => ( +
+ + {icon} + +
+ + {title} + + {meta} + +
+ +
+); - {spot !== 'today' && ( - - )} +/* -------------------------------------------------------------- surfaces */ - - Never show this again - +/** + * The streak milestone popup, redrawn from the milestone-rewards review + * (Milestone Rewards/Final review, phone width): celebration panel above, one + * decision column below. + */ +const StreakScreen = ({ spot }: { spot: 'today' | 'share' | 'milestone' }) => ( + +
+ +
); @@ -336,67 +467,15 @@ const TopReaderScreen = ({ share }: { share: boolean }) => ( ); -const WEEK: [string, string][] = [ - ['Monday', 'M'], - ['Tuesday', 'T'], - ['Wednesday', 'W'], - ['Thursday', 'T'], - ['Friday', 'F'], - ['Saturday', 'S'], - ['Sunday', 'S'], -]; - -const TIER_DAYS: [string, number][] = [ - ['Spark', 3], - ['Flame', 7], - ['Inferno', 30], - ['Supernova', 180], -]; - -/** StreakOfferCelebration.tsx, over the tiers in streakTiers.ts. */ +/** The tier moment on its own: the celebration panel with no decision under it. */ const StreakTierScreen = ({ share }: { share: boolean }) => ( -
-
- 🔥 -
- - Inferno - - 30 -

A full month, unbroken

-
- {WEEK.map(([name, initial], index) => ( - - {initial} - - ))} + + {share && ( +
+
-
- {TIER_DAYS.map(([label, day]) => ( - - {label} · {day}d - - ))} -
- {share && ( - - )} -
+ )} ); @@ -543,8 +622,8 @@ const StatusMomentsDevPage = (): ReactElement => ( @@ -615,7 +694,7 @@ const StatusMomentsDevPage = (): ReactElement => ( @@ -631,7 +710,7 @@ const StatusMomentsDevPage = (): ReactElement => ( diff --git a/packages/webapp/public/streak-tiers/inferno.png b/packages/webapp/public/streak-tiers/inferno.png new file mode 100644 index 0000000000000000000000000000000000000000..baf3c16ea462f0b2cd254c9df8861c6beff8ace7 GIT binary patch literal 39849 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

>{KCop(XjwlMdEV7Ybe2V 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 aZe{${g(r-9V($UQWpe(qVTHbP^#1@A?t||D literal 0 HcmV?d00001 From 1f8139ed1b9b7419ec70037550f4930898e5ee62 Mon Sep 17 00:00:00 2001 From: tomeredlich Date: Thu, 3 Sep 2026 13:03:45 +0300 Subject: [PATCH 5/8] docs(snapshot): draw one placement per moment, not three MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every moment was drawn as a triplet — the surface as it ships, the placement we want, and a louder push option — plus three moments listed without a drawing at all. That made a page about a decision read as a menu of decisions still open. Each moment now shows the placement it argues for and nothing else. The props that switched between the three states go with them, as does the rail that only existed to sit before/after pairs side by side. Co-Authored-By: Claude Opus 5 --- packages/webapp/pages/dev/status-moments.tsx | 234 ++++--------------- 1 file changed, 49 insertions(+), 185 deletions(-) diff --git a/packages/webapp/pages/dev/status-moments.tsx b/packages/webapp/pages/dev/status-moments.tsx index 43263572f51..17e6a5aa81a 100644 --- a/packages/webapp/pages/dev/status-moments.tsx +++ b/packages/webapp/pages/dev/status-moments.tsx @@ -69,13 +69,6 @@ const Screen = ({ children }: { children: ReactNode }) => (

); -/** Screens sit in a scroller rather than wrapping, so widths stay honest. */ -const Rail = ({ children }: { children: ReactNode }) => ( -
- {children} -
-); - const Variant = ({ step, headline, @@ -241,7 +234,7 @@ const OptionRow = ({ * (Milestone Rewards/Final review, phone width): celebration panel above, one * decision column below. */ -const StreakScreen = ({ spot }: { spot: 'today' | 'share' | 'milestone' }) => ( +const StreakScreen = () => (
); /** UserTopList.tsx — the leaderboard rows. */ -const RankScreen = ({ spot }: { spot: 'today' | 'hover' | 'band' }) => ( +const RankScreen = () => (
- {spot === 'band' && ( -
-
- - You're #1 this week - - - Highest level · 103 - -
- -
- )} -

Highest level

@@ -401,7 +351,7 @@ const RankScreen = ({ spot }: { spot: 'today' | 'hover' | 'band' }) => (
  • @@ -423,7 +373,7 @@ const RankScreen = ({ spot }: { spot: 'today' | 'hover' | 'band' }) => (
  • - {index === 0 && spot === 'hover' && ( + {index === 0 && ( ( /* -------------------------------------------------- other win moments */ /** TopReaderBadgeModal.tsx — download only, no share route. */ -const TopReaderScreen = ({ share }: { share: boolean }) => ( +const TopReaderScreen = () => (
    @@ -457,30 +407,28 @@ const TopReaderScreen = ({ share }: { share: boolean }) => ( icon={} size={ButtonSize.Small} type="button" - variant={share ? ButtonVariant.Float : ButtonVariant.Primary} + variant={ButtonVariant.Float} > Download badge - {share && } +
    ); /** The tier moment on its own: the celebration panel with no decision under it. */ -const StreakTierScreen = ({ share }: { share: boolean }) => ( +const StreakTierScreen = () => ( - {share && ( -
    - -
    - )} +
    + +
    ); /** ListAwardsModal.tsx, from the recipient's side. */ -const AwardedScreen = ({ share }: { share: boolean }) => ( +const AwardedScreen = () => (
    @@ -504,9 +452,7 @@ const AwardedScreen = ({ share }: { share: boolean }) => ( Cores given 1,250
    - {share && ( - - )} +
    {['Bobby Iliev', 'Ante Barić', 'Ido Shamun'].map((name) => ( @@ -536,7 +482,7 @@ const POST_STATS: [string, string][] = [ ]; /** posts/[id]/analytics, behind canViewPostAnalytics. */ -const AnalyticsScreen = ({ share }: { share: boolean }) => ( +const AnalyticsScreen = () => (
    @@ -548,7 +494,7 @@ const AnalyticsScreen = ({ share }: { share: boolean }) => ( Why iconic tech brands lost their dominance
    - {share && } +
    @@ -567,7 +513,7 @@ const AnalyticsScreen = ({ share }: { share: boolean }) => ( ))}
    - {share && } +
    ); @@ -614,26 +560,12 @@ const StatusMomentsDevPage = (): ReactElement => ( title="Reading streak" verdict="Placement is settled; frequency is the real lever. Every day dulls it — 10 / 50 / 100 keeps it an event." > - - - - - - - + @@ -642,26 +574,12 @@ const StatusMomentsDevPage = (): ReactElement => ( title="Achievements" verdict="The artwork is already designed to be looked at. The only question is whether we wait to be asked." > - - - - - - - + @@ -670,26 +588,12 @@ const StatusMomentsDevPage = (): ReactElement => ( title="Your leaderboard rank" verdict="The shipped control is `opacity-0 group-hover:opacity-100` at XSmall Float, pinned right with ml-auto. It works on desktop and does not exist on touch — the third hover-gated share control in the product, after the achievement card and the squad directory card." > - - - - - - - + @@ -701,70 +605,30 @@ const StatusMomentsDevPage = (): ReactElement => ( - - - - + - - - - + - - - - + - - - - - - - - - -
    - - -
    - - -
    +
    From 1393f356660aa81f71529b23495aff503c783e8f Mon Sep 17 00:00:00 2001 From: tomeredlich Date: Thu, 3 Sep 2026 15:51:35 +0300 Subject: [PATCH 6/8] fix(snapshot): one Snapshot control on the post analytics screen The screen drew the control twice: an icon in the header and a labelled control under the stats. The header placement asks before the numbers have made the case, so it goes; the control under the stats stays. Co-Authored-By: Claude Opus 5 --- packages/webapp/pages/dev/status-moments.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/webapp/pages/dev/status-moments.tsx b/packages/webapp/pages/dev/status-moments.tsx index 17e6a5aa81a..b851fb2aeae 100644 --- a/packages/webapp/pages/dev/status-moments.tsx +++ b/packages/webapp/pages/dev/status-moments.tsx @@ -494,7 +494,6 @@ const AnalyticsScreen = () => ( Why iconic tech brands lost their dominance
    -
    @@ -625,7 +624,7 @@ const StatusMomentsDevPage = (): ReactElement => ( From f760b19888df3462cbe6c93250ba80a4f9253c73 Mon Sep 17 00:00:00 2001 From: tomeredlich Date: Thu, 3 Sep 2026 15:59:16 +0300 Subject: [PATCH 7/8] feat(snapshot): add a Snapshot icon to the awards header An icon-only Tertiary control beside the close button, matching its weight, so the moment can be captured from the header as well as from the cores row. Co-Authored-By: Claude Opus 5 --- packages/webapp/pages/dev/status-moments.tsx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/webapp/pages/dev/status-moments.tsx b/packages/webapp/pages/dev/status-moments.tsx index b851fb2aeae..d608f36c9f3 100644 --- a/packages/webapp/pages/dev/status-moments.tsx +++ b/packages/webapp/pages/dev/status-moments.tsx @@ -435,13 +435,16 @@ const AwardedScreen = () => ( Awards given -
    From c305de12307342fb11dedf8bf05ae90e72457eb5 Mon Sep 17 00:00:00 2001 From: tomeredlich Date: Sun, 6 Sep 2026 11:25:34 +0300 Subject: [PATCH 8/8] fix(dev): serve the status moments review page off production hosts The page gated on isDevelopment, so the Vercel preview showed the gate message instead of the screens it exists to review. It now blocks the canonical production hosts only, matching /dev/snapshot-happening-now. Co-Authored-By: Claude Opus 5 --- packages/webapp/pages/dev/status-moments.tsx | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/webapp/pages/dev/status-moments.tsx b/packages/webapp/pages/dev/status-moments.tsx index d608f36c9f3..8c3ef386f9e 100644 --- a/packages/webapp/pages/dev/status-moments.tsx +++ b/packages/webapp/pages/dev/status-moments.tsx @@ -1,5 +1,5 @@ import type { ReactElement, ReactNode } from 'react'; -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { NextSeo } from 'next-seo'; import { Button, @@ -20,7 +20,6 @@ import { ProfilePicture, } from '@dailydotdev/shared/src/components/ProfilePicture'; import { TopRankBadge } from '@dailydotdev/shared/src/components/cards/Leaderboard/TopRankBadge'; -import { isDevelopment } from '@dailydotdev/shared/src/lib/constants'; /** * /dev/status-moments — internal review surface for the Snapshot sharing @@ -522,12 +521,25 @@ const AnalyticsScreen = () => ( /* ------------------------------------------------------------------ page */ +const useIsAllowedHost = () => { + const [allowed, setAllowed] = useState(true); + + useEffect(() => { + const { hostname } = window.location; + setAllowed(hostname !== 'app.daily.dev' && hostname !== 'www.daily.dev'); + }, []); + + return allowed; +}; + const ProductionGate = ({ children }: { children: ReactNode }) => { - if (!isDevelopment) { + const allowed = useIsAllowedHost(); + + if (!allowed) { return (

    - The status moments review page is only available in development. + The status moments review page is not available on this host.

    );