PHANTOM
🇮🇳 IN
Skip to content

Implement new layout for widget search promo panel#34207

Open
simoarpe wants to merge 24 commits intomasterfrom
simone/widget-search-panel-promo
Open

Implement new layout for widget search promo panel#34207
simoarpe wants to merge 24 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 introduce 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
Comment on lines +3113 to +3124
<message name="IDS_SEARCH_WIDGET_PROMO_SEARCH_CONTENT_DESCRIPTION" desc="Content description for the search icon in the Brave search widget promo">
Search
</message>
<message name="IDS_SEARCH_WIDGET_PROMO_VOICE_SEARCH_CONTENT_DESCRIPTION" desc="Content description for the voice search icon in the Brave search widget promo">
Voice search
</message>
<message name="IDS_SEARCH_WIDGET_PROMO_PRIVATE_SEARCH_CONTENT_DESCRIPTION" desc="Content description for the private search icon in the Brave search widget promo">
Open private search
</message>
<message name="IDS_SEARCH_WIDGET_PROMO_LEO_CONTENT_DESCRIPTION" desc="Content description for the Leo icon in the Brave search widget promo">
Open Leo
</message>
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Image

@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

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

Description

This PR redesigns the search widget promotion panel in the Brave Android browser with several key improvements:

  1. UI Redesign: The search widget promo panel is completely redesigned — replacing the old horizontal icon+text layout with a centered card that includes a visual preview of the actual search widget (search bar with microphone, private search, and Leo icons), centered title/description text, and side-by-side "Not now" / "Add widget" buttons.

  2. Popup positioning improvements: The promo panel now displays at the bottom of the screen (using Gravity.BOTTOM) instead of as a dropdown from the URL bar, accounting for bottom toolbar height and navigation bar insets. It also handles orientation changes and keyboard open/close events properly.

  3. Source tracking for widget searches: When a search originates from the search widget, the source=android query parameter on search.brave.com URLs is rewritten to source=android-widget for analytics differentiation.

  4. Onboarding activity finish race fix: The WelcomeOnboardingActivity now waits for the next activity to resume (or itself to stop) before finishing, preventing visual glitches on foldable devices during task transitions.

  5. Tablet/foldable layout improvements: Adds height-bucketed dimension resources for onboarding card margins on tablets in portrait mode, and makes heading font weights bolder/consistent.

  6. Cleanup: Removes unused drawables (ic_search_widget_promotion_icon.xml, ic_widget_generic.xml, add_widget_button.xml), removes unnecessary Build.VERSION.SDK_INT checks (minSdk is already >= O), and removes the button_background_widget_promo color.

Possible Issues

  • Copyright year typo: Multiple new files have Copyright (c) 2026 in the header instead of 2025. This appears in button_transparent.xml, rounded_surface_container_background.xml, widget_promo_panel_search_background.xml, widget_search_preview.xml, BraveIntentHandlerUnitTest.java, and all new dimens files.

  • HeadingH3 style change is global: Changing heading_h3 from 22sp to 20sp and fontWeight from 500 to 600 affects every use of HeadingH3 style across the app, not just onboarding. This could cause unintended visual regressions elsewhere.

  • Race condition in launchPendingIntentAndFinish: If neither condition triggers (the current activity never reaches STOPPED/DESTROYED and no other activity resumes), the ActivityStateListener would leak and the activity would never finish. This seems unlikely but is theoretically possible in edge cases.

  • Promo panel re-shown on night mode change: In onDestroyInternal, the code writes SHOULD_SHOW_SEARCH_WIDGET_PROMO = true back to preferences if the promo was showing. However, the showIfNeeded path also writes it to false. This could cause the promo to persist across multiple configuration changes indefinitely until the user explicitly dismisses it.

  • PopupWindow focus steals touch: The PopupWindow is created with focusable = true, which may intercept back presses and touch events outside the popup in unexpected ways.

Security Hotspots

  • URL rewriting in maybeReplaceWidgetSearchSource: The method rebuilds the URL by iterating query parameters and reconstructing them. While the logic appears sound (only modifying source=androidsource=android-widget on search.brave.com), any URL parsing/reconstruction is sensitive. The use of Uri.parse() on untrusted intent data is standard Android practice but worth noting.
Changes

Changes

BraveIntentHandler.java

  • Added maybeReplaceWidgetSearchSource() to rewrite source=android to source=android-widget for searches originating from the search widget on search.brave.com.

BraveActivity.java

  • Added onOrientationChange override to reposition the promo panel.
  • Added showWidgetPromoPanel(), hideWidgetPromoPanel(), and getBottomOffsetForWidgetPromo() helper methods.
  • Promo panel is now dismissed on keyboard open/close.
  • Promo panel state is preserved across onDestroyInternal for config changes.

SearchWidgetPromoPanel.java

  • Refactored to show popup at screen bottom with gravity-based positioning.
  • Added dismiss(), isShowing() methods.
  • View inflation moved from constructor to showIfNeeded().

WelcomeOnboardingActivity.java

  • Added launchPendingIntentAndFinish() to avoid finish-before-resume race conditions on foldables.

layout_search_widget_promo.xml — Complete redesign with ConstraintLayout, centered text, included widget preview, and side-by-side buttons.

widget_search_preview.xml — New layout showing a mock search widget with search, mic, private, and Leo icons.

New drawablesbutton_transparent.xml, rounded_surface_container_background.xml, widget_promo_panel_search_background.xml.

Tablet onboarding dimens — Added 4 height-bucketed resource qualifiers for portrait tablet margins.

BraveIntentHandlerUnitTest.java — Unit tests for the URL source rewriting logic.

sequenceDiagram
    participant User
    participant BraveActivity
    participant SearchWidgetPromoPanel
    participant PopupWindow
    participant BraveIntentHandler
    participant SearchWidget

    Note over BraveActivity: URL bar focused, promo flag is true
    BraveActivity->>SearchWidgetPromoPanel: new SearchWidgetPromoPanel()
    BraveActivity->>BraveActivity: showWidgetPromoPanel()
    BraveActivity->>SearchWidgetPromoPanel: showIfNeeded(rootView, bottomOffset, context)
    SearchWidgetPromoPanel->>PopupWindow: new PopupWindow(view)
    SearchWidgetPromoPanel->>PopupWindow: showAtLocation(Gravity.BOTTOM)

    alt User taps "Add widget"
        User->>SearchWidgetPromoPanel: onClick(btAddWidget)
        SearchWidgetPromoPanel->>SearchWidget: requestPinAppWidget()
        SearchWidgetPromoPanel->>PopupWindow: dismiss()
    else User taps "Not now"
        User->>SearchWidgetPromoPanel: onClick(tvNotNow)
        SearchWidgetPromoPanel->>PopupWindow: dismiss()
    else Keyboard opens
        BraveActivity->>BraveActivity: onKeyboardOpened()
        BraveActivity->>SearchWidgetPromoPanel: dismiss()
    else Orientation changes
        BraveActivity->>BraveActivity: onOrientationChange()
        BraveActivity->>SearchWidgetPromoPanel: showIfNeeded() (reposition)
    end

    Note over SearchWidget: User searches via widget
    SearchWidget->>BraveIntentHandler: Intent with EXTRA_FROM_SEARCH_WIDGET
    BraveIntentHandler->>BraveIntentHandler: extractUrlFromIntent()
    BraveIntentHandler->>BraveIntentHandler: maybeReplaceWidgetSearchSource()
    Note over BraveIntentHandler: source=android → source=android-widget
Loading

@github-actions
Copy link
Contributor

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++

android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_gravity="center_vertical|start"
android:background="@drawable/widget_promo_panel_search_background"
Copy link
Member

@SergeyZhukovsky SergeyZhukovsky Feb 26, 2026

Choose a reason for hiding this comment

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

I don't think the background has to be duplicated here since FrameLayout has it already. One of them is redundant and causes double-drawing.

<color name="schemes_surface_container_highest">#343438</color>
<color name="schemes_surface_container_lowest">#0f0f0f</color>
<color name="schemes_surface_container">#1F1F23</color>
<color name="schemes_on_primary_container">#DFE4F6</color>
Copy link
Member

Choose a reason for hiding this comment

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

do we have that in nala colors already? @fallaciousreasoning merged a PR recently to auto populate nala colors to use them directly from there #34106

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

5 participants