(feat)rebrand: NTP - Next Steps List + Stats - #2877
Conversation
Scope the card, tag, and pill-button overrides under data-rebrand, and use rebrand icons on macOS when the flag is enabled. Co-authored-by: Cursor <cursoragent@cursor.com>
Restore classic flex sizing so the illustration shrinks with the card, fluidly reduce left padding, and refine dismiss/CTA styles to match the rebrand spec. Co-authored-by: Cursor <cursoragent@cursor.com>
Map all list card icons to Pictograms-2026 SVGs behind the rebrand flag, drop the unused Subscription-96 asset, and expose a stickersheet for design review. Co-authored-by: Cursor <cursoragent@cursor.com>
Keep AGENTS.local.md and Cursor continual-learning state out of the shared repo. Co-authored-by: Cursor <cursoragent@cursor.com>
Show the back card again with Figma side inset and vertical offset so multi-card stacks read correctly. Co-authored-by: Cursor <cursoragent@cursor.com>
Align stats layout, Show More pill, shield/trash icons, and theme-aware card shadow with design tokens; add coverage for empty state, expand/collapse, and burn/remove icons. Co-authored-by: Cursor <cursoragent@cursor.com>
[Beta] Generated file diffTime updated: Thu, 23 Jul 2026 23:51:09 GMT Apple
File has changed Removed Files
❌ File only exists in old changeset Integration
File has changed Windows
File has changed New Files
❌ File only exists in new changeset |
Keep only an empty peek shell behind the active card so CTAs from the next step no longer show through the stack edge. Co-authored-by: Cursor <cursoragent@cursor.com>
Build Branch
Static preview entry points
QR codes (mobile preview)
Integration commandsnpm (Android / Extension): Swift Package Manager (Apple): .package(url: "https://github.com/duckduckgo/content-scope-scripts.git", branch: "pr-releases/matteo/rebrand/ntp-stats-and-next-steps")git submodule (Windows): git -C submodules/content-scope-scripts fetch origin pr-releases/matteo/rebrand/ntp-stats-and-next-steps
git -C submodules/content-scope-scripts checkout origin/pr-releases/matteo/rebrand/ntp-stats-and-next-stepsPin to exact commitnpm (Android / Extension): Swift Package Manager (Apple): .package(url: "https://github.com/duckduckgo/content-scope-scripts.git", revision: "4ec3c2ce2f055c273403e957b40a2ed30738edd2")git submodule (Windows): git -C submodules/content-scope-scripts fetch origin pr-releases/matteo/rebrand/ntp-stats-and-next-steps
git -C submodules/content-scope-scripts checkout 4ec3c2ce2f055c273403e957b40a2ed30738edd2 |
|
This PR requires a manual review and approval from a member of one of the following teams:
|
There was a problem hiding this comment.
Stale comment
Web Compatibility Assessment
File Severity Finding (none — injected/)info No injected runtime changes. This PR is scoped to special-pages/pages/new-tab/only, so third-party web compatibility categories (API shimming, prototype overrides, stack-trace exemptions) do not apply.special-pages/pages/new-tab/app/next-steps-list/NextStepsList.js:46warning Rebrand SVG icon paths are gated to macOS only ( useRebrandAssets = useNewTabPageRebranding() && platformName === 'macos'), but rebrand card CSS inNextStepsListCard.module.cssactivates on all platforms whenbody[data-rebrand="true"]. If native enablesnewTabPageRebrandingon Windows before macOS icon assets are ready, users will see rebrand card chrome with legacy theme PNG illustrations — verify this is an intentional staged rollout.special-pages/pages/new-tab/app/privacy-stats/components/PrivacyStats.module.css,protections/components/Protections.module.css,ProtectionsHeading.jsinfo Stats/protections visual refresh (counter layout, bar colors, feed switcher, shield icon swap) ships unconditionally — not behind newTabPageRebrandingordata-rebrand. Only Next Steps List detailed rebrand is config-gated. Confirm native rollout plan matches this split.special-pages/pages/new-tab/app/next-steps-list/components/NextStepsListCard.js:136-143info Dismiss animation setTimeout(300)has proper cleanup viauseEffectreturn — no unbounded timer leak.special-pages/pages/new-tab/app/next-steps-list/components/NextStepsListCard.js:172info Empty peek shell ( aria-hidden="true") correctly hides stacked next-card content from assistive tech — aligns with stacked-card UX requirement.special-pages/pages/new-tab/app/next-steps-list/components/NextStepsListCard.module.css:559info Rebrand styles use :has(.backCard)for conditional box-shadow. Supported in current DDG WebViews; no action needed unless targeting very old engines.special-pages/pages/new-tab/app/activity/components/ActivityItem.js:143info Burn control icon changes from Fire to Trash (non-legacy UI); Windows remove control remains Cross. Integration tests added for both. special-pages/package.jsoninfo @duckduckgo/design-tokensbumpedv0.30.0→v0.31.0. Verify new--ds-radius-*/ theme tokens resolve in all NTP themes after merge.Security Assessment
File Severity Finding (none — injected/)info No changes to captured-globals.js, wrapper utilities, message bridge, or API overrides.special-pages/pages/new-tab/messages/types/settings.json:30-38info New newTabPageRebrandingsetting follows existing read-only pattern (state: enabled | disabled, default disabled insettings.js). No newnotify/requestschemas; nonativeDataforwarding risk. Schema lacksadditionalProperties: falsebut matches sibling settings entries.special-pages/pages/new-tab/app/index.js:179info body[data-rebrand]is derived from native-injected settings, not page-controlled input. Mock transport URL override (?rebrand=enabled) is dev/test only.special-pages/pages/new-tab/app/next-steps-list/next-steps-list.data.js:89-110info Rebrand icon paths are a static hardcoded map keyed by known variant IDs — not constructed from page/user data. Safe. special-pages/pages/new-tab/public/icons/*.svginfo New SVG assets are inline static paths with no <script>, event handlers, or externalxlink:hrefreferences.special-pages/pages/new-tab/app/index.js:179warning Native platforms must ship newTabPageRebrandingin initial settings before enabling the feature in production. Default (disabled) is safe; missing key falls back to disabled viaSettingsconstructor.Risk Level
Low Risk — special-pages NTP UI/CSS only; no injected code, API overrides, messaging transport changes, or security-boundary modifications. Rebrand is config-gated (default off) with integration test coverage (50/50 pass locally across activity, protections, and new-tab specs).
Recommendations
- warning — Confirm macOS-only icon gating vs platform-agnostic
data-rebrandCSS is intentional for staged rollout; align Windows icon assets before enablingnewTabPageRebrandingon Windows.- info — Confirm with native that Protections/Privacy Stats visual refresh is meant to ship unconditionally (not behind the rebrand flag).
- info — Coordinate native settings schema so all platforms send
newTabPageRebrandingbefore feature flag flip.- info — Consider replacing hardcoded Pollen colors (
#FFD885,#47210A) in rebrand CSS with design tokens when available inv0.31.0.- info — Smoke-test with
?rebrand=enabledon macOS to verify all 9 Next Steps List rebrand SVG icons render (especiallybringStuffwhich has no rebrand SVG mapping and falls back to PNG).Sent by Cursor Automation: Web compat and sec
Move Learned Preferences/Facts out of shared AGENTS.md into gitignored AGENTS.local.md. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Icon selection now follows the rebrand feature flag alone, matching the data-rebrand body attribute, the rebrand CSS, and the examples renderer. Platform-specific artwork is already resolved via variant IDs (addAppToDockMac vs pinAppToTaskbarWindows), so Windows users with rebrand enabled get the correct rebrand SVGs instead of legacy PNGs. Adds integration tests covering both platform-specific variants. Co-authored-by: Cursor <cursoragent@cursor.com>
The "Polish Protections Report" changes previously applied globally, leaking the new look into the legacy/pre-rebrand UI (current production on all platforms). Isolate every visual change behind the newTabPageRebranding flag so that with the flag OFF the widget renders exactly as before. - CSS: restore Protections/PrivacyStats/ShowHide modules to their pre-polish originals and re-apply the new values only under :global(body[data-rebrand="true"]) (with compound [data-platform-name]/[data-theme] selectors where needed). - JS: choose icon/props/class via useNewTabPageRebranding() in ProtectionsHeading (shield icon + cookiePopUpsCounter), PrivacyStats (stats pill variant), and ActivityItem (Trash vs Fire burn glyph). - Restore FireIcon (+ .fireIcon) in Icons and keep TrashIcon; extract the burn-glyph choice into a readable renderSecondaryIcon helper. - Tests: run the trash-icon assertion with rebrand enabled and add FF-off coverage asserting the FireIcon fallback. Co-authored-by: Cursor <cursoragent@cursor.com>
Consume the standalone --ds-next-steps-badge-* tokens (imported page-scoped in the NTP App.module.css, mirroring onboarding.css) instead of hardcoded Pollen hex values, and drop the unused body[data-rebrand] placeholder rule. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Stale comment
Injected PR Evaluation: Web Compatibility & Security
Re-assessed at
de0902b(synchronize). Two commits since the prior run address the outstanding rebrand-gating concern.Web Compatibility Assessment
File Severity Finding (scope) info No injected/,messaging/,wrapper-utils.js, orcaptured-globals.jschanges. This PR touches only the embedded NTP (special-pages/pages/new-tab/); it does not run in third-party page contexts, so API-surface-fidelity and prototype-chain concerns for injected features do not apply.next-steps-list/components/NextStepsListCard.jsinfo Dismiss animation setTimeout(300)is cleaned up viauseEffectreturn (clearTimeout). No unbounded timer leak.next-steps-list/components/NextStepsListCard.jsinfo Empty peek shell renders as aria-hidden="true"with no inner content — avoids exposing duplicate/off-screen interactive content during the stacked-card animation.next-steps-list/next-steps-list.data.jsinfo Rebrand icon paths are a static rebrandIconPathsmap; dock vs taskbar artwork is selected by native-provided variant ID, not a client-side platform gate. Integration tests guard Mac/Windows icon regressions.activity/components/ActivityItem.jsinfo Burn/remove glyph selection ( TrashIconvsFireIconvsCross) is gated onuseNewTabPageRebranding()with integration coverage for both flag-on and flag-off paths.privacy-stats/,protections/info Rebrand CSS is scoped under :global(body[data-rebrand="true"]); JS switches (shield icon, stats pill variant, cookie counter class) useuseNewTabPageRebranding(). With the flag OFF, legacy UI is preserved. (Resolved in2bdbd8d1f.)Security Assessment
File Severity Finding (scope) info No changes to message-bridge trust boundaries, origin validation, captured-globals.js, or content-scope initialization.next-steps-list/info No new notify()/request()calls or schema changes. Existing next-steps messaging is unchanged.next-steps-list/next-steps-list.data.jsinfo getIconPath()returns only static relative asset paths from a fixed map when rebrand is enabled — no page-derived or user-controlled URL construction.settings.provider.js/index.jsinfo Visual rebrand is gated behind native-provided newTabPageRebrandingsetting →body[data-rebrand]attribute, enabling remote rollback without a code deploy.public/icons/*.svginfo New static SVG assets only. Subscription-96.svgremoved; next-steps rebrand path now usesDesktop-Mobile-Subscription-96.svg. No remaining broken references in this widget.Risk Level
Low Risk — special-pages-only NTP visual rebrand behind
newTabPageRebranding; no injected runtime, API overrides, or messaging security surface changes.Recommendations
- Resolved: Prior warning about Protections/Privacy Stats polish leaking into the legacy UI is fully addressed in
2bdbd8d1f(CSS behindbody[data-rebrand="true"], JS behinduseNewTabPageRebranding()).- Info: Confirm native clients ship the
newTabPageRebrandingsetting before enabling the rebrand in production.- Info:
design-tokensbump to v0.31.0 +next-steps-badge.cssimport is dev-only styling; no runtime security impact.Sent by Cursor Automation: Web compat and sec
|
@BugBot run |
The empty "peek" shell behind the front Next Steps List card is a rebrand-only treatment, but it was rendered for every user — removing the pre-rebrand stacked preview that showed the next step's illustration and copy (flagged by Bugbot). - JS: render the empty shell only when useNewTabPageRebranding() is on; otherwise keep the back card's CardBody content as before. - CSS: restore overflow: hidden on .card.backCard so the peek content is clipped when the next step's text is taller than the front card. - Tests: add rebrand-enabled coverage asserting the peek shell has no next-step content. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Stale comment
Injected PR Evaluation: Web Compatibility & Security
PR: #2877 — NTP Next Steps List + Stats rebrand
Head:9865d97a7(synchronize)
Scope:special-pages/only — noinjected/,messaging/, or API-override changes
Web Compatibility Assessment
File Lines Severity Finding (entire PR) — info All changes are in the embedded New Tab Page ( special-pages/pages/new-tab/). This code does not inject into third-party web pages, so injected-runtime compatibility categories (API shimming, prototype integrity, stack-trace exemptions, etc.) do not apply.app/index.js/settings.provider.js~70, ~42 info Rebrand visuals are gated behind newTabPageRebranding(defaultdisabled) →body[data-rebrand]. Native can disable per rollout without a deploy.next-steps-list/components/NextStepsListCard.js131, 174–187 info Resolved in 9865d97a7: the empty peek shell behind the front card is now rebrand-only; pre-rebrand users retain the stacked preview with the next step's illustration and copy. Integration test added.next-steps-list/components/NextStepsListCard.js137–144 info Dismiss animation setTimeout(300)has properclearTimeoutcleanup in theuseEffectreturn — no unbounded timer leak.next-steps-list/NextStepsList.js,next-steps-list.data.js45–56, 108–113 info Rebrand SVG icons selected via static rebrandIconPathsmap when flag is on; non-rebrand path unchanged (./next-steps-list/{icon}-{theme}.png). Platform-specific dock/taskbar icons driven by variant ID, not a macOS-only gate — covered by integration tests.activity/components/ActivityItem.js162–167 info Burn control icon switches Fire → Trash only when useNewTabPageRebranding()is true; legacy and non-burn paths unchanged. Integration tests cover rebrand on/off.privacy-stats/,protections/CSS + JSvarious info Rebrand styling scoped under :global(body[data-rebrand="true"]); JS conditionals (PrivacyStats.js,ProtectionsHeading.js) mirror the flag. Pre-rebrand rendering preserved when flag is off.next-steps-list/integration-tests/— info Good rebrand coverage (platform icons, empty peek shell). No rebrand-on screenshot/integration coverage for Protections/Privacy Stats visual refresh (low risk given CSS-only, flag-gated changes).
Security Assessment
File Lines Severity Finding (entire PR) — info No changes to captured-globals.js, message bridge, messaging transports, or content-scope initialization.(entire PR) — info No new notify()/request()calls or messaging schema changes. Existing next-steps/activity/protections messaging paths unchanged.next-steps-list.data.js,ProtectionsHeading.js89–113, 80 info Image srcvalues come from static path maps keyed by known icon/variant IDs — no page-derived URL construction orpostMessageusage.settings.json/index.js— info newTabPageRebrandingis a boolean feature flag withenabled/disabledenum — safe JSON Patch surface, remotely disableable..gitignore43–46 info Adds local-only ignores ( AGENTS.local.md,.cursor) — no runtime impact.No security findings (warning/error/critical).
Risk Level
Low Risk — CSS/UI-only changes to the first-party New Tab Page, fully gated behind
newTabPageRebranding(default off), with no injected-runtime, messaging, or browser API override surface.
Recommendations
- Ship coordination (info): Ensure native clients send
newTabPageRebranding: { state: 'enabled' }only when ready to roll out; default-off preserves current UX.- Testing (info): Consider a rebrand-on screenshot or integration pass for Protections/Privacy Stats heading refresh if visual regression risk is a concern during rollout.
- No action required on injected compatibility or security hardening — this PR does not touch the injection runtime.
Delta since prior assessment (
de0902b): commit9865d97a7correctly gates the Next Steps empty peek shell behind the rebrand flag and restoresoverflow: hiddenon the back card for the pre-rebrand stacked preview.Sent by Cursor Automation: Web compat and sec
Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Stale comment
Injected PR Evaluation: Web Compatibility & Security
Re-assessed on synchronize (
b0bf8e219) — delta since prior run: design-tokensv0.31.0→v0.32.0for next-steps-badge pollen tokens (no application logic changes).
Web Compatibility Assessment
File Lines Severity Finding (entire PR) — info No injected/changes. This PR touches onlyspecial-pages/(embedded first-party NTP UI), so third-party web compatibility criteria (API shimming, prototype patching,toString()masking, stack-trace exemptions) do not apply.special-pages/pages/new-tab/app/index.js~179 info Rebrand styling is gated behind newTabPageRebranding(defaultdisabled) →body[data-rebrand]. With the flag off, legacy UI is preserved.special-pages/pages/new-tab/app/next-steps-list/components/NextStepsListCard.js137–144 info Dismiss animation setTimeout(300ms)has proper cleanup viaclearTimeoutin theuseEffectreturn — no leak on unmount.special-pages/pages/new-tab/app/next-steps-list/components/NextStepsListCard.js174–187 info Empty peek shell for stacked cards is correctly gated behind isRebrand; pre-rebrand path still renders next-step content in the back card. Integration test added.special-pages/pages/new-tab/app/next-steps-list/next-steps-list.data.js88–114 info Rebrand icon paths are a static allowlist map; non-rebrand falls back to theme PNGs. Platform-specific dock/taskbar icons selected via native variant ID, not a client-side platform gate. special-pages/pages/new-tab/app/activity/components/ActivityItem.js155–160 info Burn icon swap (Fire → Trash) is gated on useNewTabPageRebranding(); integration tests cover both rebrand-on and rebrand-off paths.special-pages/pages/new-tab/app/privacy-stats/,protections/CSS blocks info Privacy Stats and Protections visual refresh scoped to body[data-rebrand="true"]; JS callers (PillShowMoreLess,ProtectionsHeading) also check the flag before applying rebrand variants.No warning or error web compatibility findings.
Security Assessment
File Lines Severity Finding (entire PR) — info No injected/,messaging/,captured-globals.js, message-bridge, or transport changes. No new API overrides orpostMessageusage.special-pages/pages/new-tab/app/next-steps-list/next-steps-list.data.js108–114 info getIconPath()resolves icons from a hardcoded map keyed by known variant names — no page-derived or user-controlled URL construction.special-pages/pages/new-tab/public/icons/*.svg— info New static SVG assets served from same origin; no external fetches introduced. special-pages/package.jsondevDep info @duckduckgo/design-tokensbumped tov0.32.0(devDependency, build-time CSS tokens only). Build verified locally.No warning, error, or critical security findings.
Risk Level
Low Risk — Special-pages-only UI rebrand behind a disabled-by-default feature flag; no injected runtime, API overrides, messaging boundary, or captured-globals changes.
Recommendations
- Info — Native apps must ship the
newTabPageRebrandingsetting before enabling rebrand in production (existing wiring insettings.js/index.js).- Info — Consider adding rebrand-on integration coverage for Protections/Privacy Stats visual refresh (currently CSS-only; behavior tests exist for Activity icons and Next Steps peek shell).
- Info —
Subscription-96.svgremoved; non-rebrand subscription variant still uses PNGs — verify native bundles include the new rebrand SVGs when the flag is enabled.
Tests: 49/49 integration tests pass locally (
next-steps-list,activity,protections).npm run build --workspace=special-pagessucceeds with design-tokensv0.32.0.Sent by Cursor Automation: Web compat and sec
vkraucunas
left a comment
There was a problem hiding this comment.
The badge was previously outside of the cards, but now it is inside, but the animations hasn’t been updated. So it stays pinned to same location on card dismissal, I’d expect it to move with the card now? That said, it’s the same content on every card.. so maybe something else. Bring it up to Chris in review.
| import { Star, StarFilled } from '../../components/icons/Star.js'; | ||
| import { Fire as FireIconLegacy } from '../../components/icons/Fire.js'; | ||
| import { Cross, FireIcon } from '../../components/Icons.js'; | ||
| import { Cross, FireIcon, TrashIcon } from '../../components/Icons.js'; |
There was a problem hiding this comment.
Is it called Cross in a lot of places in the codebase? I’m assuming this is the x icon, right?
There was a problem hiding this comment.
correct. I didn't change name for consistency.
| function renderSecondaryIcon({ canBurn, shouldDisplayLegacyActivity, isRebrand }) { | ||
| if (!canBurn) return <Cross />; | ||
| if (shouldDisplayLegacyActivity) return <FireIconLegacy />; | ||
| if (isRebrand) return <TrashIcon />; |
There was a problem hiding this comment.
Is there ever a case in which it could be (isRebrand && !canBurn) ? where we’d not get the correct icon?
There was a problem hiding this comment.
Everything should be covered here. Windows shows the trash bin and macOS the fire.
However, this reminds me that I have to check with Chris about the fire animantion.
There was a problem hiding this comment.
isRebrand && !canBurn → Cross.
On Windows, canBurn is always false(burn action unavailable), so the isRebrand branch is never reached on Windows TrashIcon is macOS-only in practice. No missing case.
I'll add a comment.
|
@vkraucunas re:Next-Steps animation -> I asked the same question and Stephen replied that it's okay to keep it as it is https://app.asana.com/1/137249556945/task/1216407910002005/comment/1216760049228758 |
…teps - Fix inverted fill prop on ShowHideButtonPill (was !isRebrand, always false) - Remove dead dark-mode CSS block in PrivacyStats (theme tokens already aware) - Move cookiePopUpsCounter margin override from JS conditional to CSS rebrand block - Replace --title-3-em-line-height with --ds-font-body-md-line-height in rebrand scope - Replace --sp-2 with --ds-space-x02 in rebrand scope - Update @import from next-steps-badge.css to ntp.css - Rename ShowHideButton variant stats -> rebrand, update comment for clarity - Add code comment explaining Windows/macOS platform distinction in ActivityItem
…s button tokens - Bump @duckduckgo/design-tokens from v0.32.0 to v0.33.0 - Replace --color-black-at-9/60 and --color-white-at-9/60 in dismissBtn rebrand styles with --ds-ntp-dismiss-btn-light/dark-border/color semantic tokens
There was a problem hiding this comment.
Injected PR Evaluation: Web Compatibility & Security
Re-assessed on synchronize (484fb01f3). Scope: special-pages/ only — no injected/, messaging/, wrapper-utils.js, or content-scope initialization changes. This PR affects the first-party New Tab Page embedded UI, not third-party page injection.
Web Compatibility Assessment
| File | Severity | Finding |
|---|---|---|
| (scope) | info | No browser API overrides, prototype patches, or toString() masking — standard web-compat injection risks do not apply. |
special-pages/pages/new-tab/app/index.js |
info | Rebrand rollout is correctly gated: native newTabPageRebranding (default disabled) sets body[data-rebrand]. All visual refresh CSS/JS in this PR keys off that attribute. |
special-pages/pages/new-tab/app/next-steps-list/components/NextStepsListCard.js |
info | Dismiss animation setTimeout(300) has proper clearTimeout cleanup in the useEffect return — no unbounded timer leak. |
special-pages/pages/new-tab/app/next-steps-list/next-steps-list.data.js |
info | Rebrand icon paths are a static lookup table keyed by known variant IDs; non-rebrand path falls back to theme PNGs. No page-derived URL construction. |
special-pages/pages/new-tab/app/protections/components/Protections.module.css |
info | Rebrand sets overflow: visible on .body/.feed — acceptable for NTP layout; scoped to body[data-rebrand="true"]. |
special-pages/pages/new-tab/app/components/App.module.css |
info | Global @import of ntp.css (design-tokens v0.33.0) adds CSS custom properties only; no visual change without rebrand selectors. Build verified locally. |
| Integration tests | info | Good rebrand coverage for Next Steps List (empty peek shell, Mac/Windows icons) and Activity (trash/fire/cross icons). No rebrand-on visual tests for Privacy Stats / Protections widgets. |
Resolved since last review: ntp.css build failure (v0.32.0) fixed by bumping to v0.33.0 (484fb01f3). Protections/Privacy Stats rebrand CSS is now scoped under body[data-rebrand="true"]. Next Steps empty peek shell is rebrand-only.
Security Assessment
| File | Severity | Finding |
|---|---|---|
| (scope) | info | No changes to message-bridge trust boundaries, captured-globals.js, origin validation, or postMessage usage. |
special-pages/pages/new-tab/messages/types/settings.json |
info | newTabPageRebranding schema allows remote per-domain disable via native settings — correct rollout pattern. |
special-pages/pages/new-tab/app/next-steps-list/next-steps-list.data.js |
info | <img src> values come from a fixed map or ./next-steps-list/{icon}-{theme}.png — no user-controlled URL injection or CSS exfiltration vectors. |
special-pages/pages/new-tab/app/activity/components/ActivityItem.js |
info | Icon selection is a pure function of canBurn, legacy flag, and rebrand state — no messaging or data exfiltration paths introduced. |
special-pages/pages/new-tab/app/protections/components/ProtectionsHeading.js |
info | Existing protections_scroll subscription unchanged; no new outgoing notify()/request() calls. |
Risk Level
Low Risk — special-pages UI/CSS/asset changes behind a remote-config feature flag; no injected runtime, API shims, or messaging security surface touched.
Recommendations
- ✅ Resolved:
ntp.cssimport now works with design-tokens v0.33.0;npm run build --workspace=special-pagespasses. - ✅ Resolved: All rebrand visual changes (Protections, Privacy Stats, Next Steps peek shell, Activity trash icon) are gated on
newTabPageRebranding. - Info: Consider adding rebrand-on integration tests for Privacy Stats / Protections visual states (screenshot or DOM assertions) before full rollout.
- Info: Confirm native apps ship the
newTabPageRebrandingsetting so the flag can be toggled without a C-S-S deploy.
49/49 affected integration tests pass locally (activity, next-steps-list, protections).
Sent by Cursor Automation: Web compat and sec
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 484fb01. Configure here.



Asana Task/Github Issue: https://app.asana.com/1/137249556945/project/72649045549333/task/1216270925937867?focus=true
Figma: https://www.figma.com/design/DBZiXJRgTTJTuBeWAPyE5h/%F0%9F%96%A5%EF%B8%8F-Desktop-Components?node-id=11105-170351&p=f&m=dev
Description
Visual update for the New Tab rebrand (behind the existing rebrand flag):
Depends on the rebrand feature-flag work (#2844).
Screenshots
Testing Steps
rebrand=disabled.?next-steps-list=add-app-to-dock&next-steps-list=import-passwords(add more ids as needed)?protections.feed=privacy-stats&stats=many?protections.feed=activity?protections.feed=activity&activity=emptyplatform=windows) and light/dark.Checklist
Please tick all that apply:
Note
Low Risk
Changes are UI-only and scoped to the existing NTP rebrand flag; burn/remove actions are unchanged aside from icons, with added integration tests.
Overview
Adds NTP rebrand visuals gated on
useNewTabPageRebranding()/body[data-rebrand="true"], plus design-tokens v0.33 and an import of@duckduckgo/design-tokens/build/desktop-browsers/ntp.cssin the app shell.Next Steps List picks new 96px SVG illustrations via
getIconPath(..., isRebrandEnabled), restyles cards (badge, borders, pill buttons, dismiss), and under rebrand renders the stacked peek as an empty chrome shell instead of the next step’s copy. Dev examples and Playwright coverage cover Mac/Windows dock assets and the empty peek behavior.Protections Report gets rebrand-scoped layout for the widget shell, tab switcher, and Privacy Stats (heading shield swaps to
Shield-Color-16.svg, tracker list + bars). Show more/less can useShowHideButtonPillvariant="rebrand".Activity burn control shows TrashIcon when rebrand is on (fire when off; cross on Windows remove); icons gain
data-testids for integration tests.Also bumps lockfile, adds rebrand icon assets, removes the old gradient
Subscription-96.svg, and extends protections/activity integration tests.Reviewed by Cursor Bugbot for commit 484fb01. Bugbot is set up for automated code reviews on this repo. Configure here.