Skip to content

Implement new layout for widget search promo panel#34207

Merged
simoarpe merged 26 commits intomasterfrom
simone/widget-search-panel-promo
Feb 27, 2026
Merged

Implement new layout for widget search promo panel#34207
simoarpe merged 26 commits intomasterfrom
simone/widget-search-panel-promo

Conversation

@simoarpe
Copy link
Collaborator

@simoarpe simoarpe commented Feb 26, 2026

Resolves brave/brave-browser#52840

Implements new layout for widget search promo panel.
Figma design: https://figma.com/design/TeDNTZqnV6LQJQRGledM6W/%F0%9F%8E%81-Android-onboarding?node-id=0-1&p=f&t=v8qdmXTviTaOad2w-0

This PR also introduces better handling of activity recreations and configuration changes to redraw the widget search promo panel with correct theme (day/night) and proper position.

Other notable enhancements:

  • Tweak tablet margins to better frame the onboarding cards on foldable devices after initial review with the design team.
  • Fix post-FRE intent and delay activity to avoid a glitch on foldable devices by following the same strategy applied upstream.
  • Accessibility: include content descriptions for widget search promo panel images.
  • Nala: include new drawables from Nala tokens.
  • Append new source android-widget for all searches made from the widget.
  • Implement tests to verify new source android-widget.

Out of scope

After initial review with the design team we noticed some styles are not properly reflecting the bold using the font property. To keep this PR scope at its minimum we opted to open a follow up issue that will modify the H styles globally: brave/brave-browser#53113

Previews

Screenshot_1772040700 Screenshot_1772040705 Screenshot_1772040883 Screenshot_1772040840 Screenshot_1772040846

@simoarpe simoarpe self-assigned this Feb 26, 2026
@simoarpe simoarpe requested review from a team as code owners February 26, 2026 11:11
@simoarpe simoarpe added CI/skip-ios Do not run CI builds for iOS CI/skip-windows-x64 Do not run CI builds for Windows x64 CI/skip-macos-arm64 Do not run CI builds for macOS arm64 labels Feb 26, 2026
@simoarpe simoarpe force-pushed the simone/widget-search-panel-promo branch from 5c98360 to 5677bad Compare February 26, 2026 11:49
@github-actions
Copy link
Contributor

github-actions bot commented Feb 26, 2026

Copy link
Contributor

@AlexeyBarabash AlexeyBarabash left a comment

Choose a reason for hiding this comment

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

lgtm

@simoarpe simoarpe changed the title Simone/widget search panel promo Implement new layout for widget search promo panel Feb 26, 2026
Copy link
Collaborator

@mkarolin mkarolin left a comment

Choose a reason for hiding this comment

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

strings++

@github-actions
Copy link
Contributor

Chromium major version is behind target branch (145.0.7632.120 vs 146.0.7680.32). Please rebase.

@github-actions github-actions bot added the chromium-version-mismatch The Chromium version on the PR branch does not match the version on the target branch label Feb 26, 2026
@github-actions
Copy link
Contributor

[puLL-Merge] - brave/brave-core@34207

Description

This PR redesigns the search widget promotion panel in the Brave Android browser and makes several related improvements:

  1. Redesigned search widget promo UI: The promo panel is completely overhauled from a dropdown-style popup to a bottom-anchored popup with a modern card design featuring a search widget preview, centered text, and side-by-side action buttons.
  2. Widget search source tracking: When a search originates from the Brave search widget, the source=android query parameter on search.brave.com URLs is rewritten to source=android-widget for analytics differentiation.
  3. Improved promo panel lifecycle management: The panel now properly handles orientation changes, keyboard open/close events, night mode transitions, and navigation bar insets.
  4. Onboarding activity finish race fix: The WelcomeOnboardingActivity now uses an ActivityStateListener pattern to delay finish() until the next activity is resumed, preventing transition glitches on foldable devices.
  5. Tablet onboarding layout improvements: Added height-aware dimension resources for tablet portrait mode and updated heading styles for consistency.
  6. Removed legacy API level checks: Removed Build.VERSION.SDK_INT >= Build.VERSION_CODES.O guards since the minimum API level now guarantees these APIs are available.
  7. Typography updates: Changed HeadingH3 font size from 22sp to 20sp and weight from 500 to 600.

Possible Issues

  • Copyright year "2026": Multiple new files have Copyright (c) 2026 in their headers (e.g., button_transparent.xml, rounded_surface_container_background.xml, widget_search_preview.xml, widget_promo_panel_search_background.xml, all new dimens.xml files, and BraveIntentHandlerUnitTest.java). This is clearly a typo and should be 2025.
  • HeadingH3 style change is global: Changing heading_h3 from 22sp to 20sp and fontWeight from 500 to 600 affects every use of HeadingH3 across the entire app, not just the onboarding/promo screens. This could cause unintended visual regressions elsewhere.
  • Promo re-shown on night mode change: In onDestroyInternal, when the promo is showing and the activity is being destroyed (e.g., night mode change), the pref is re-set to true. This could cause the promo to keep reappearing across multiple config changes even after the user has already seen it, potentially leading to an annoying UX loop if the user never explicitly interacts with it.
  • launchPendingIntentAndFinish listener leak potential: If neither the "self stopped/destroyed" nor "other activity resumed" condition is ever met (edge case), the ActivityStateListener would remain registered indefinitely. Though unlikely in practice, a timeout or safety guard might be warranted.
  • Widget preview is non-interactive but looks interactive: The widget_search_preview.xml layout shows icons (search, microphone, private, Leo) that visually appear tappable but are purely decorative in the promo context, which could confuse users.

Security Hotspots

  • URL rewriting in maybeReplaceWidgetSearchSource: The method parses and reconstructs URLs. While the logic correctly checks for the specific host (search.brave.com) and parameter values before modifying, any future changes to this method should be careful not to introduce open redirect or URL manipulation vulnerabilities. The current implementation appears safe as it only modifies a known parameter value on a known host.
Changes

Changes

  • android/BUILD.gn: Removed old drawable resources (add_widget_button.xml, ic_search_widget_promotion_icon.xml, ic_widget_generic.xml), added new drawables (button_transparent.xml, rounded_surface_container_background.xml, widget_promo_panel_search_background.xml) and layout (widget_search_preview.xml).
  • BraveIntentHandler.java: Added maybeReplaceWidgetSearchSource() to rewrite source=androidsource=android-widget for search widget-originated Brave Search URLs.
  • BraveActivity.java: Added lifecycle management for the search widget promo panel: handles orientation changes, keyboard events, bottom toolbar offset, and night mode destroy/recreate.
  • WelcomeOnboardingActivity.java: Replaced direct finish() + intent pattern with launchPendingIntentAndFinish() using ActivityStateListener to avoid transition glitches.
  • SearchWidgetPromoPanel.java: Refactored from constructor-based initialization to on-demand popup creation; now positions at bottom of screen with proper inset handling.
  • BraveSearchWidgetUtils.java: Removed unnecessary Build.VERSION SDK checks.
  • Layout/style files: Complete redesign of layout_search_widget_promo.xml; new widget_search_preview.xml; updated heading styles and tablet-specific dimension resources.
  • BraveIntentHandlerUnitTest.java: New unit tests for URL rewriting logic.
  • Color resources: Removed button_background_widget_promo color.
  • Strings: Added accessibility content descriptions for widget promo icons.
sequenceDiagram
    participant User
    participant BraveActivity
    participant SearchWidgetPromoPanel
    participant PopupWindow
    participant BraveSearchWidgetUtils
    participant BraveIntentHandler

    Note over BraveActivity: URL bar focused, promo pref is true
    BraveActivity->>SearchWidgetPromoPanel: new SearchWidgetPromoPanel()
    BraveActivity->>BraveActivity: showWidgetPromoPanel()
    BraveActivity->>BraveActivity: getBottomOffsetForWidgetPromo()
    BraveActivity->>SearchWidgetPromoPanel: showIfNeeded(rootView, offset, context)
    SearchWidgetPromoPanel->>BraveSearchWidgetUtils: getShouldShowWidgetPromo()
    BraveSearchWidgetUtils-->>SearchWidgetPromoPanel: true
    SearchWidgetPromoPanel->>PopupWindow: new PopupWindow(view)
    SearchWidgetPromoPanel->>PopupWindow: showAtLocation(Gravity.BOTTOM)

    alt User clicks "Add widget"
        User->>SearchWidgetPromoPanel: onClick(btAddWidget)
        SearchWidgetPromoPanel->>BraveSearchWidgetUtils: requestPinAppWidget()
        SearchWidgetPromoPanel->>PopupWindow: dismiss()
    else User clicks "Not Now"
        User->>SearchWidgetPromoPanel: onClick(tvNotNow)
        SearchWidgetPromoPanel->>BraveSearchWidgetUtils: setShouldShowWidgetPromo(false)
        SearchWidgetPromoPanel->>PopupWindow: dismiss()
    else Keyboard opens
        BraveActivity->>BraveActivity: onKeyboardOpened()
        BraveActivity->>SearchWidgetPromoPanel: dismiss()
    else Orientation changes
        BraveActivity->>BraveActivity: onOrientationChange()
        BraveActivity->>SearchWidgetPromoPanel: showIfNeeded() (repositions)
    else Night mode changes (activity destroyed)
        BraveActivity->>BraveActivity: onDestroyInternal()
        BraveActivity->>SearchWidgetPromoPanel: dismiss()
        Note over BraveActivity: Writes pref=true for next creation
    end

    Note over User: Search via widget
    User->>BraveIntentHandler: extractUrlFromIntent(intent)
    BraveIntentHandler->>BraveIntentHandler: maybeReplaceWidgetSearchSource()
    Note over BraveIntentHandler: Rewrites source=android → source=android-widget
    BraveIntentHandler-->>User: Modified URL
Loading

@simoarpe simoarpe force-pushed the simone/widget-search-panel-promo branch from f8079cc to f4d8c03 Compare February 27, 2026 10:37
@github-actions github-actions bot removed the chromium-version-mismatch The Chromium version on the PR branch does not match the version on the target branch label Feb 27, 2026
@simoarpe simoarpe merged commit 3f35655 into master Feb 27, 2026
22 checks passed
@simoarpe simoarpe deleted the simone/widget-search-panel-promo branch February 27, 2026 12:45
@github-actions github-actions bot added this to the 1.89.x - Nightly milestone Feb 27, 2026
@brave-builds
Copy link
Collaborator

Released in v1.89.85

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI/skip-ios Do not run CI builds for iOS CI/skip-macos-arm64 Do not run CI builds for macOS arm64 CI/skip-windows-x64 Do not run CI builds for Windows x64 puLL-Merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tweak widget search panel promo

7 participants