Skip to content

(feat)rebrand: NTP - Next Steps List + Stats - #2877

Open
borgateo wants to merge 18 commits into
mainfrom
matteo/rebrand/ntp-stats-and-next-steps
Open

(feat)rebrand: NTP - Next Steps List + Stats#2877
borgateo wants to merge 18 commits into
mainfrom
matteo/rebrand/ntp-stats-and-next-steps

Conversation

@borgateo

@borgateo borgateo commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

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):

  • Next Steps List: new card layout and illustrations
  • Protections Report: updated stats/details presentation (Summary + Details)

Depends on the rebrand feature-flag work (#2844).

Screenshots

Screenshot 2026-07-17 at 12 57 55 Screenshot 2026-07-17 at 12 58 01 Screenshot 2026-07-17 at 12 58 31 Screenshot 2026-07-17 at 13 03 16 Screenshot 2026-07-17 at 13 08 19 Screenshot 2026-07-17 at 13 08 22 Screenshot 2026-07-17 at 13 08 32 Screenshot 2026-07-17 at 13 08 40

Testing Steps

  1. Serve special pages and open New Tab with the rebrand enabled (default). To compare against the old UI, add rebrand=disabled.
  2. Next Steps List: confirm the stacked cards + new illustrations look correct at normal and narrow widths:
    • ?next-steps-list=add-app-to-dock&next-steps-list=import-passwords (add more ids as needed)
  3. Protections → Summary. Long tracker list + Show More:
    • ?protections.feed=privacy-stats&stats=many
  4. Protections → Details. Activity feed + empty state:
    • ?protections.feed=activity
    • ?protections.feed=activity&activity=empty
  5. Quick pass on macOS + Windows (platform=windows) and light/dark.

Checklist

Please tick all that apply:

  • I have tested this change locally
  • I have tested this change locally in all supported browsers
  • This change will be visible to users
  • I have added automated tests that cover this change
  • I have ensured the change is gated by config
  • This change was covered by a ship review
  • This change was covered by a tech design
  • Any dependent config has been merged

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.css in 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 use ShowHideButtonPill variant="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.

borgateo and others added 7 commits July 7, 2026 20:32
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>
@borgateo borgateo self-assigned this Jul 17, 2026
@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

[Beta] Generated file diff

Time updated: Thu, 23 Jul 2026 23:51:09 GMT

Apple
    - apple/pages/errorpage/dist/index.css
  • apple/pages/errorpage/index.html
  • apple/pages/history/dist/index.css
  • apple/pages/new-tab/dist/index.css
  • apple/pages/new-tab/dist/index.js
  • apple/pages/onboarding/dist/index.css
  • apple/pages/release-notes/dist/index.css
  • apple/pages/special-error/dist/index.css
  • apple/pages/special-error/index.html

File has changed

Removed Files
    - apple/pages/new-tab/icons/Subscription-96.svg
  • integration/pages/new-tab/icons/Subscription-96.svg
  • windows/pages/new-tab/icons/Subscription-96.svg

❌ File only exists in old changeset

Integration
    - integration/pages/errorpage/dist/index.css
  • integration/pages/example/dist/index.css
  • integration/pages/history/dist/index.css
  • integration/pages/new-tab/dist/index.css
  • integration/pages/new-tab/dist/index.js
  • integration/pages/onboarding/dist/index.css
  • integration/pages/release-notes/dist/index.css
  • integration/pages/special-error/dist/index.css

File has changed

Windows
    - windows/pages/history/dist/index.css
  • windows/pages/new-tab/dist/index.css
  • windows/pages/new-tab/dist/index.js
  • windows/pages/onboarding/dist/index.css
  • windows/pages/release-notes/dist/index.css
  • windows/pages/special-error/dist/index.css
  • windows/pages/special-error/index.html

File has changed

New Files
    - apple/pages/new-tab/icons/Browser-Redesign-96.svg
  • apple/pages/new-tab/icons/Default-App-96.svg
  • apple/pages/new-tab/icons/Desktop-Mobile-Subscription-96.svg
  • apple/pages/new-tab/icons/Dock-Add-Mac-96.svg
  • apple/pages/new-tab/icons/Dock-Add-Windows-96.svg
  • apple/pages/new-tab/icons/Email-Protection-96.svg
  • apple/pages/new-tab/icons/Passwords-Import-96.svg
  • apple/pages/new-tab/icons/Shield-Color-16.svg
  • apple/pages/new-tab/icons/Sync-96.svg
  • apple/pages/new-tab/icons/YouTube-Clean-96.svg
  • integration/pages/new-tab/icons/Browser-Redesign-96.svg
  • integration/pages/new-tab/icons/Default-App-96.svg
  • integration/pages/new-tab/icons/Desktop-Mobile-Subscription-96.svg
  • integration/pages/new-tab/icons/Dock-Add-Mac-96.svg
  • integration/pages/new-tab/icons/Dock-Add-Windows-96.svg
  • integration/pages/new-tab/icons/Email-Protection-96.svg
  • integration/pages/new-tab/icons/Passwords-Import-96.svg
  • integration/pages/new-tab/icons/Shield-Color-16.svg
  • integration/pages/new-tab/icons/Sync-96.svg
  • integration/pages/new-tab/icons/YouTube-Clean-96.svg
  • windows/pages/new-tab/icons/Browser-Redesign-96.svg
  • windows/pages/new-tab/icons/Default-App-96.svg
  • windows/pages/new-tab/icons/Desktop-Mobile-Subscription-96.svg
  • windows/pages/new-tab/icons/Dock-Add-Mac-96.svg
  • windows/pages/new-tab/icons/Dock-Add-Windows-96.svg
  • windows/pages/new-tab/icons/Email-Protection-96.svg
  • windows/pages/new-tab/icons/Passwords-Import-96.svg
  • windows/pages/new-tab/icons/Shield-Color-16.svg
  • windows/pages/new-tab/icons/Sync-96.svg
  • windows/pages/new-tab/icons/YouTube-Clean-96.svg

❌ 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>
@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Build Branch

Branch pr-releases/matteo/rebrand/ntp-stats-and-next-steps
Commit 4ec3c2ce2f
Updated July 23, 2026 at 11:47:50 PM UTC

Static preview entry points

QR codes (mobile preview)
Entry point QR code
Docs QR for docs preview
Static pages QR for static pages preview
Integration pages QR for integration pages preview

Integration commands

npm (Android / Extension):

npm i github:duckduckgo/content-scope-scripts#pr-releases/matteo/rebrand/ntp-stats-and-next-steps

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-steps
Pin to exact commit

npm (Android / Extension):

npm i github:duckduckgo/content-scope-scripts#4ec3c2ce2f055c273403e957b40a2ed30738edd2

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

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Cursor review was not successful.

This PR requires a manual review and approval from a member of one of the following teams:

  • @duckduckgo/content-scope-scripts-owners
  • @duckduckgo/apple-devs
  • @duckduckgo/android-devs
  • @duckduckgo/team-windows-development
  • @duckduckgo/extension-owners
  • @duckduckgo/config-aor
  • @duckduckgo/breakage-aor
  • @duckduckgo/breakage

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:46 warning Rebrand SVG icon paths are gated to macOS only (useRebrandAssets = useNewTabPageRebranding() && platformName === 'macos'), but rebrand card CSS in NextStepsListCard.module.css activates on all platforms when body[data-rebrand="true"]. If native enables newTabPageRebranding on 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.js info Stats/protections visual refresh (counter layout, bar colors, feed switcher, shield icon swap) ships unconditionally — not behind newTabPageRebranding or data-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-143 info Dismiss animation setTimeout(300) has proper cleanup via useEffect return — no unbounded timer leak.
special-pages/pages/new-tab/app/next-steps-list/components/NextStepsListCard.js:172 info 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:559 info 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:143 info Burn control icon changes from Fire to Trash (non-legacy UI); Windows remove control remains Cross. Integration tests added for both.
special-pages/package.json info @duckduckgo/design-tokens bumped v0.30.0v0.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-38 info New newTabPageRebranding setting follows existing read-only pattern (state: enabled | disabled, default disabled in settings.js). No new notify/request schemas; no nativeData forwarding risk. Schema lacks additionalProperties: false but matches sibling settings entries.
special-pages/pages/new-tab/app/index.js:179 info 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-110 info 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/*.svg info New SVG assets are inline static paths with no <script>, event handlers, or external xlink:href references.
special-pages/pages/new-tab/app/index.js:179 warning Native platforms must ship newTabPageRebranding in initial settings before enabling the feature in production. Default (disabled) is safe; missing key falls back to disabled via Settings constructor.

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

  1. warning — Confirm macOS-only icon gating vs platform-agnostic data-rebrand CSS is intentional for staged rollout; align Windows icon assets before enabling newTabPageRebranding on Windows.
  2. info — Confirm with native that Protections/Privacy Stats visual refresh is meant to ship unconditionally (not behind the rebrand flag).
  3. info — Coordinate native settings schema so all platforms send newTabPageRebranding before feature flag flip.
  4. info — Consider replacing hardcoded Pollen colors (#FFD885, #47210A) in rebrand CSS with design tokens when available in v0.31.0.
  5. info — Smoke-test with ?rebrand=enabled on macOS to verify all 9 Next Steps List rebrand SVG icons render (especially bringStuff which has no rebrand SVG mapping and falls back to PNG).
Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

borgateo and others added 2 commits July 17, 2026 13:11
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>
Comment thread special-pages/pages/new-tab/app/next-steps-list/NextStepsList.js Outdated
Comment thread special-pages/pages/new-tab/app/index.js
Comment thread special-pages/pages/new-tab/app/next-steps-list/NextStepsList.js Outdated
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>
Comment thread special-pages/pages/new-tab/app/protections/components/Protections.module.css Outdated
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>
@cursor cursor Bot mentioned this pull request Jul 21, 2026
8 tasks
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>

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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, or captured-globals.js changes. 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.js info Dismiss animation setTimeout(300) is cleaned up via useEffect return (clearTimeout). No unbounded timer leak.
next-steps-list/components/NextStepsListCard.js info 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.js info Rebrand icon paths are a static rebrandIconPaths map; 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.js info Burn/remove glyph selection (TrashIcon vs FireIcon vs Cross) is gated on useNewTabPageRebranding() 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) use useNewTabPageRebranding(). With the flag OFF, legacy UI is preserved. (Resolved in 2bdbd8d1f.)

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.js info 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.js info Visual rebrand is gated behind native-provided newTabPageRebranding setting → body[data-rebrand] attribute, enabling remote rollback without a code deploy.
public/icons/*.svg info New static SVG assets only. Subscription-96.svg removed; next-steps rebrand path now uses Desktop-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

  1. Resolved: Prior warning about Protections/Privacy Stats polish leaking into the legacy UI is fully addressed in 2bdbd8d1f (CSS behind body[data-rebrand="true"], JS behind useNewTabPageRebranding()).
  2. Info: Confirm native clients ship the newTabPageRebranding setting before enabling the rebrand in production.
  3. Info: design-tokens bump to v0.31.0 + next-steps-badge.css import is dev-only styling; no runtime security impact.
Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

@borgateo

Copy link
Copy Markdown
Contributor Author

@BugBot run

Comment thread special-pages/pages/new-tab/app/next-steps-list/components/NextStepsListCard.js Outdated
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>

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Injected PR Evaluation: Web Compatibility & Security

PR: #2877 — NTP Next Steps List + Stats rebrand
Head: 9865d97a7 (synchronize)
Scope: special-pages/ only — no injected/, 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 (default disabled) → body[data-rebrand]. Native can disable per rollout without a deploy.
next-steps-list/components/NextStepsListCard.js 131, 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.js 137–144 info Dismiss animation setTimeout(300) has proper clearTimeout cleanup in the useEffect return — no unbounded timer leak.
next-steps-list/NextStepsList.js, next-steps-list.data.js 45–56, 108–113 info Rebrand SVG icons selected via static rebrandIconPaths map 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.js 162–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 + JS various 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.js 89–113, 80 info Image src values come from static path maps keyed by known icon/variant IDs — no page-derived URL construction or postMessage usage.
settings.json / index.js info newTabPageRebranding is a boolean feature flag with enabled/disabled enum — safe JSON Patch surface, remotely disableable.
.gitignore 43–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

  1. Ship coordination (info): Ensure native clients send newTabPageRebranding: { state: 'enabled' } only when ready to roll out; default-off preserves current UX.
  2. 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.
  3. No action required on injected compatibility or security hardening — this PR does not touch the injection runtime.

Delta since prior assessment (de0902b): commit 9865d97a7 correctly gates the Next Steps empty peek shell behind the rebrand flag and restores overflow: hidden on the back card for the pre-rebrand stacked preview.

Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

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

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Injected PR Evaluation: Web Compatibility & Security

Re-assessed on synchronize (b0bf8e219) — delta since prior run: design-tokens v0.31.0v0.32.0 for 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 only special-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 (default disabled) → body[data-rebrand]. With the flag off, legacy UI is preserved.
special-pages/pages/new-tab/app/next-steps-list/components/NextStepsListCard.js 137–144 info Dismiss animation setTimeout(300ms) has proper cleanup via clearTimeout in the useEffect return — no leak on unmount.
special-pages/pages/new-tab/app/next-steps-list/components/NextStepsListCard.js 174–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.js 88–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.js 155–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 or postMessage usage.
special-pages/pages/new-tab/app/next-steps-list/next-steps-list.data.js 108–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.json devDep info @duckduckgo/design-tokens bumped to v0.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

  1. Info — Native apps must ship the newTabPageRebranding setting before enabling rebrand in production (existing wiring in settings.js / index.js).
  2. 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).
  3. InfoSubscription-96.svg removed; 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-pages succeeds with design-tokens v0.32.0.

Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

@vkraucunas vkraucunas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it called Cross in a lot of places in the codebase? I’m assuming this is the x icon, right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 />;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there ever a case in which it could be (isRebrand && !canBurn) ? where we’d not get the correct icon?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread special-pages/pages/new-tab/app/components/App.module.css Outdated
Comment thread special-pages/pages/new-tab/app/components/ShowHide.module.css Outdated
Comment thread special-pages/pages/new-tab/app/privacy-stats/components/PrivacyStats.module.css Outdated
Comment thread special-pages/pages/new-tab/app/privacy-stats/components/PrivacyStats.module.css Outdated
Comment thread special-pages/pages/new-tab/app/privacy-stats/components/PrivacyStats.module.css Outdated
Comment thread special-pages/pages/new-tab/app/protections/components/Protections.module.css Outdated
@borgateo

Copy link
Copy Markdown
Contributor Author

@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
Comment thread special-pages/pages/new-tab/app/components/App.module.css
…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

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

  1. Resolved: ntp.css import now works with design-tokens v0.33.0; npm run build --workspace=special-pages passes.
  2. Resolved: All rebrand visual changes (Protections, Privacy Stats, Next Steps peek shell, Activity trash icon) are gated on newTabPageRebranding.
  3. Info: Consider adding rebrand-on integration tests for Privacy Stats / Protections visual states (screenshot or DOM assertions) before full rollout.
  4. Info: Confirm native apps ship the newTabPageRebranding setting so the flag can be toggled without a C-S-S deploy.

49/49 affected integration tests pass locally (activity, next-steps-list, protections).

Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

@borgateo
borgateo requested a review from vkraucunas July 23, 2026 23:49
@borgateo
borgateo marked this pull request as ready for review July 23, 2026 23:49
@borgateo
borgateo requested review from a team and daxtheduck as code owners July 23, 2026 23:49

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ 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.

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.

2 participants