[Sidebar V2] Make brave's panel header as SidePanel's header (#36472)
Sidebar v2 attaches a Brave-styled panel header at the SidePanel level
instead of embedding it inside the content view.
## Changes
- New BraveSidePanelHeader (view) + BraveSidePanelHeaderController (delegate) under
brave/browser/ui/views/side_panel/. Visual spec (title, optional launch button + separator,
close button, 60px height, Nala colors, Leo icons) mirrors V1's inline headers in
BraveReadLaterSidePanelView/BraveBookmarksSidePanelView.
- BraveSidePanelCoordinator::PopulateSidePanel attaches the header via upstream
SidePanel::AddHeaderView only for entries ShouldShowBraveHeader allows (today: kReadingList, kBookmarks).
- SidePanel chromium_src override now wraps upstream AddHeaderView / RemoveHeaderView so each call also
re-runs Brave's UpdateBorder(). UpdateBorder() reserves a top inset equal to the header's preferred height
when a header is attached, in both the rounded-border and no-border states.
- brave_side_panel_header_controller is split into its own :side_panel_impl source_set
(depending on :side_panel) to keep dep chains clean.
## Test plan
- New SidebarBrowserTest.SidebarV2BraveHeaderTest test case
- Manual: run with enable_sidebar_v2=true, open reading list and bookmarks — header should be visible
This commit is contained in:
@@ -3,5 +3,7 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
# You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
brave_browser_window_internal_deps =
|
||||
[ "//brave/browser/ui/browser_window/internal" ]
|
||||
brave_browser_window_internal_deps = [
|
||||
"//brave/browser/ui/browser_window/internal",
|
||||
"//brave/browser/ui/sidebar/buildflags",
|
||||
]
|
||||
|
||||
@@ -56,6 +56,7 @@ if (toolkit_views) {
|
||||
"//brave/browser/ui/views/frame/vertical_tabs",
|
||||
"//brave/browser/ui/views/location_bar",
|
||||
"//brave/browser/ui/views/page_info",
|
||||
"//brave/browser/ui/views/side_panel:side_panel_impl",
|
||||
]
|
||||
|
||||
if (enable_ai_chat) {
|
||||
|
||||
@@ -96,6 +96,7 @@
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_SIDEBAR_V2)
|
||||
#include "brave/browser/ui/views/side_panel/brave_side_panel_header.h"
|
||||
#include "brave/browser/ui/views/side_panel/brave_side_panel_resize_area.h"
|
||||
#endif
|
||||
|
||||
@@ -2150,30 +2151,41 @@ IN_PROC_BROWSER_TEST_F(SidebarBrowserTest, SidebarV2ActiveItemStateSync) {
|
||||
[&]() { return !model()->active_index().has_value(); }));
|
||||
}
|
||||
|
||||
// Verify that the upstream SidePanelHeader is never added when a sidebar panel
|
||||
// is opened in V2, so Brave can render its own header.
|
||||
IN_PROC_BROWSER_TEST_F(SidebarBrowserTest, SidebarV2NoUpstreamHeaderTest) {
|
||||
// Verify the Brave-styled side panel header is attached for reading list and
|
||||
// bookmarks and absent for other entries.
|
||||
IN_PROC_BROWSER_TEST_F(SidebarBrowserTest, SidebarV2BraveHeaderTest) {
|
||||
auto* panel_ui = browser()->GetFeatures().side_panel_ui();
|
||||
auto* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
|
||||
auto* side_panel = browser_view->contents_height_side_panel();
|
||||
side_panel->DisableAnimationsForTesting();
|
||||
|
||||
panel_ui->Toggle();
|
||||
ASSERT_TRUE(base::test::RunUntil([&]() { return side_panel->GetVisible(); }));
|
||||
// Reading list: Brave header attached.
|
||||
panel_ui->Show(SidePanelEntryId::kReadingList);
|
||||
ASSERT_TRUE(base::test::RunUntil([&]() {
|
||||
return panel_ui->IsSidePanelEntryShowing(
|
||||
SidePanelEntry::Key(SidePanelEntryId::kReadingList));
|
||||
}));
|
||||
EXPECT_NE(nullptr, side_panel->GetHeaderView<BraveSidePanelHeader>())
|
||||
<< "BraveSidePanelHeader should be attached for the reading list panel";
|
||||
|
||||
EXPECT_EQ(nullptr, side_panel->GetHeaderView<views::View>())
|
||||
<< "Upstream SidePanelHeader should not be present after V2 panel open";
|
||||
// Bookmarks: Brave header attached.
|
||||
panel_ui->Show(SidePanelEntryId::kBookmarks);
|
||||
ASSERT_TRUE(base::test::RunUntil([&]() {
|
||||
return panel_ui->IsSidePanelEntryShowing(
|
||||
SidePanelEntry::Key(SidePanelEntryId::kBookmarks));
|
||||
}));
|
||||
EXPECT_NE(nullptr, side_panel->GetHeaderView<BraveSidePanelHeader>())
|
||||
<< "BraveSidePanelHeader should be attached for the bookmarks panel";
|
||||
|
||||
// Also verify CustomizeChrome panel does not get an upstream header.
|
||||
// CustomizeChrome: no Brave header (the previous one must be cleared when
|
||||
// switching to an entry that doesn't request a Brave header).
|
||||
panel_ui->Show(SidePanelEntryId::kCustomizeChrome);
|
||||
ASSERT_TRUE(base::test::RunUntil([&]() {
|
||||
return panel_ui->IsSidePanelEntryShowing(
|
||||
SidePanelEntry::Key(SidePanelEntryId::kCustomizeChrome));
|
||||
}));
|
||||
|
||||
EXPECT_EQ(nullptr, side_panel->GetHeaderView<views::View>())
|
||||
<< "Upstream SidePanelHeader should not be present for CustomizeChrome "
|
||||
"panel";
|
||||
EXPECT_EQ(nullptr, side_panel->GetHeaderView<BraveSidePanelHeader>())
|
||||
<< "BraveSidePanelHeader should not be attached for CustomizeChrome";
|
||||
}
|
||||
|
||||
// Verify that the resize area is positioned correctly for both border states.
|
||||
|
||||
@@ -23,8 +23,34 @@ source_set("side_panel") {
|
||||
|
||||
if (enable_sidebar_v2) {
|
||||
sources += [
|
||||
"brave_side_panel_header.cc",
|
||||
"brave_side_panel_header.h",
|
||||
"brave_side_panel_header_controller.h",
|
||||
"brave_side_panel_resize_area.cc",
|
||||
"brave_side_panel_resize_area.h",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
source_set("side_panel_impl") {
|
||||
sources = []
|
||||
deps = []
|
||||
|
||||
if (enable_sidebar_v2) {
|
||||
sources += [ "brave_side_panel_header_controller.cc" ]
|
||||
|
||||
deps += [
|
||||
":side_panel",
|
||||
"//base",
|
||||
"//brave/app:brave_generated_resources_grit_grit",
|
||||
"//brave/components/vector_icons",
|
||||
"//chrome/app:generated_resources",
|
||||
"//chrome/browser/ui/browser_window",
|
||||
"//chrome/browser/ui/color:mixers",
|
||||
"//chrome/browser/ui/side_panel:side_panel_views_dependent",
|
||||
"//chrome/common",
|
||||
"//ui/base",
|
||||
"//ui/views",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "base/check_op.h"
|
||||
#include "base/memory/raw_ref.h"
|
||||
#include "brave/browser/ui/color/brave_color_id.h"
|
||||
#include "brave/browser/ui/sidebar/features.h"
|
||||
#include "brave/components/vector_icons/vector_icons.h"
|
||||
#include "brave/grit/brave_generated_resources.h"
|
||||
#include "brave/ui/color/nala/nala_color_id.h"
|
||||
@@ -141,6 +142,8 @@ END_METADATA
|
||||
|
||||
BraveBookmarksSidePanelView::BraveBookmarksSidePanelView(
|
||||
SidePanelEntryScope& scope) {
|
||||
CHECK(!base::FeatureList::IsEnabled(sidebar::features::kSidebarV2));
|
||||
|
||||
CHECK_EQ(SidePanelEntryScope::ScopeType::kBrowser, scope.get_scope_type());
|
||||
SetLayoutManager(std::make_unique<views::FlexLayout>())
|
||||
->SetOrientation(views::LayoutOrientation::kVertical);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "brave/browser/ui/color/brave_color_id.h"
|
||||
#include "brave/browser/ui/sidebar/features.h"
|
||||
#include "brave/components/vector_icons/vector_icons.h"
|
||||
#include "brave/grit/brave_generated_resources.h"
|
||||
#include "brave/ui/color/nala/nala_color_id.h"
|
||||
@@ -112,6 +113,8 @@ BraveReadLaterSidePanelView::BraveReadLaterSidePanelView(
|
||||
TabStripModel* tab_strip_model,
|
||||
SidePanelEntryScope& scope,
|
||||
base::RepeatingClosure close_cb) {
|
||||
CHECK(!base::FeatureList::IsEnabled(sidebar::features::kSidebarV2));
|
||||
|
||||
SetLayoutManager(std::make_unique<views::FlexLayout>())
|
||||
->SetOrientation(views::LayoutOrientation::kVertical);
|
||||
AddChildView(std::make_unique<ReadLaterSidePanelHeaderView>(scope));
|
||||
|
||||
@@ -26,6 +26,12 @@
|
||||
#include "chrome/browser/profiles/profile.h"
|
||||
#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
|
||||
#include "chrome/browser/ui/side_panel/side_panel_entry.h"
|
||||
#include "chrome/browser/ui/views/side_panel/side_panel.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_SIDEBAR_V2)
|
||||
#include "brave/browser/ui/views/side_panel/brave_side_panel_header.h"
|
||||
#include "brave/browser/ui/views/side_panel/brave_side_panel_header_controller.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -202,8 +208,27 @@ void BraveSidePanelCoordinator::PopulateSidePanel(
|
||||
SidePanelCoordinator::PopulateSidePanel(supress_animations, unique_key,
|
||||
std::move(open_trigger), entry,
|
||||
std::move(content_view));
|
||||
|
||||
#if BUILDFLAG(ENABLE_SIDEBAR_V2)
|
||||
if (ShouldShowBraveHeader(entry)) {
|
||||
auto* side_panel = GetSidePanelFor(entry->type());
|
||||
CHECK(side_panel);
|
||||
side_panel->AddHeaderView(std::make_unique<BraveSidePanelHeader>(
|
||||
std::make_unique<BraveSidePanelHeaderController>(
|
||||
*browser_view_->browser(), entry)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if BUILDFLAG(ENABLE_SIDEBAR_V2)
|
||||
bool BraveSidePanelCoordinator::ShouldShowBraveHeader(
|
||||
SidePanelEntry* entry) const {
|
||||
const SidePanelEntry::Id id = entry->key().id();
|
||||
return id == SidePanelEntry::Id::kReadingList ||
|
||||
id == SidePanelEntry::Id::kBookmarks;
|
||||
}
|
||||
#endif
|
||||
|
||||
BraveBrowserView* BraveSidePanelCoordinator::GetBraveBrowserView() {
|
||||
return static_cast<BraveBrowserView*>(browser_view_);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include "brave/browser/ui/sidebar/buildflags/buildflags.h"
|
||||
#include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h"
|
||||
#include "chrome/browser/ui/views/side_panel/side_panel_helper.h"
|
||||
|
||||
@@ -52,6 +53,11 @@ class BraveSidePanelCoordinator : public SidePanelCoordinator {
|
||||
std::optional<SidePanelEntry::Key> GetLastActiveEntryKey() const;
|
||||
void UpdateToolbarButtonHighlight(bool side_panel_visible);
|
||||
BraveBrowserView* GetBraveBrowserView();
|
||||
|
||||
#if BUILDFLAG(ENABLE_SIDEBAR_V2)
|
||||
// Returns true when we want to show brave panel header view for |entry|.
|
||||
bool ShouldShowBraveHeader(SidePanelEntry* entry) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // BRAVE_BROWSER_UI_VIEWS_SIDE_PANEL_BRAVE_SIDE_PANEL_COORDINATOR_H_
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/* Copyright (c) 2026 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "brave/browser/ui/views/side_panel/brave_side_panel_header.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "base/check.h"
|
||||
#include "brave/ui/color/nala/nala_color_id.h"
|
||||
#include "ui/base/metadata/metadata_impl_macros.h"
|
||||
#include "ui/gfx/geometry/insets.h"
|
||||
#include "ui/views/background.h"
|
||||
#include "ui/views/controls/button/image_button.h"
|
||||
#include "ui/views/controls/label.h"
|
||||
#include "ui/views/controls/separator.h"
|
||||
#include "ui/views/layout/flex_layout.h"
|
||||
#include "ui/views/layout/flex_layout_types.h"
|
||||
#include "ui/views/layout/layout_types.h"
|
||||
#include "ui/views/view_class_properties.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int kHeaderInteriorMargin = 16;
|
||||
constexpr int kHeaderButtonSize = 20;
|
||||
constexpr int kHeaderHeight = 60;
|
||||
constexpr int kSeparatorHorizontalSpacing = 12;
|
||||
|
||||
} // namespace
|
||||
|
||||
BraveSidePanelHeader::BraveSidePanelHeader(std::unique_ptr<Delegate> delegate)
|
||||
: delegate_(std::move(delegate)) {
|
||||
CHECK(delegate_);
|
||||
|
||||
SetBackground(views::CreateSolidBackground(nala::kColorPageBackground));
|
||||
SetLayoutManager(std::make_unique<views::FlexLayout>())
|
||||
->SetOrientation(views::LayoutOrientation::kHorizontal)
|
||||
.SetInteriorMargin(gfx::Insets(kHeaderInteriorMargin))
|
||||
.SetMainAxisAlignment(views::LayoutAlignment::kStart)
|
||||
.SetCrossAxisAlignment(views::LayoutAlignment::kCenter);
|
||||
|
||||
AddChildView(delegate_->CreatePanelTitle());
|
||||
|
||||
AddChildView(std::make_unique<views::View>())
|
||||
->SetProperty(
|
||||
views::kFlexBehaviorKey,
|
||||
views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero,
|
||||
views::MaximumFlexSizeRule::kUnbounded)
|
||||
.WithOrder(2));
|
||||
|
||||
if (auto launch_button = delegate_->CreateLaunchButton()) {
|
||||
AddChildView(std::move(launch_button));
|
||||
auto* separator = AddChildView(std::make_unique<views::Separator>());
|
||||
separator->SetColorId(nala::kColorDividerSubtle);
|
||||
separator->SetPreferredLength(kHeaderButtonSize);
|
||||
separator->SetProperty(views::kMarginsKey,
|
||||
gfx::Insets::VH(0, kSeparatorHorizontalSpacing));
|
||||
}
|
||||
|
||||
AddChildView(delegate_->CreateCloseButton());
|
||||
}
|
||||
|
||||
BraveSidePanelHeader::~BraveSidePanelHeader() = default;
|
||||
|
||||
void BraveSidePanelHeader::Layout(PassKey) {
|
||||
LayoutSuperclass<views::View>(this);
|
||||
|
||||
// Need to set bounds as parent view(SidePanel) uses FillLayout.
|
||||
const gfx::Rect contents_bounds = parent()->GetContentsBounds();
|
||||
SetBoundsRect(gfx::Rect(contents_bounds.x(),
|
||||
contents_bounds.y() - kHeaderHeight,
|
||||
contents_bounds.width(), kHeaderHeight));
|
||||
}
|
||||
|
||||
BEGIN_METADATA(BraveSidePanelHeader)
|
||||
END_METADATA
|
||||
@@ -0,0 +1,48 @@
|
||||
/* Copyright (c) 2026 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BRAVE_BROWSER_UI_VIEWS_SIDE_PANEL_BRAVE_SIDE_PANEL_HEADER_H_
|
||||
#define BRAVE_BROWSER_UI_VIEWS_SIDE_PANEL_BRAVE_SIDE_PANEL_HEADER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "ui/base/metadata/metadata_header_macros.h"
|
||||
#include "ui/views/view.h"
|
||||
|
||||
namespace views {
|
||||
class ImageButton;
|
||||
class Label;
|
||||
} // namespace views
|
||||
|
||||
// Header view shown on top of the side panel border in sidebar v2. The visual
|
||||
// spec mirrors the v1 inline headers in BraveReadLaterSidePanelView and
|
||||
// BraveBookmarksSidePanelView; per-entry pieces are produced by a Delegate.
|
||||
class BraveSidePanelHeader : public views::View {
|
||||
METADATA_HEADER(BraveSidePanelHeader, views::View)
|
||||
|
||||
public:
|
||||
class Delegate {
|
||||
public:
|
||||
virtual ~Delegate() = default;
|
||||
virtual std::unique_ptr<views::Label> CreatePanelTitle() = 0;
|
||||
|
||||
// Return nullptr when the entry has no launch action (e.g. reading list).
|
||||
virtual std::unique_ptr<views::ImageButton> CreateLaunchButton() = 0;
|
||||
virtual std::unique_ptr<views::ImageButton> CreateCloseButton() = 0;
|
||||
};
|
||||
|
||||
explicit BraveSidePanelHeader(std::unique_ptr<Delegate> delegate);
|
||||
BraveSidePanelHeader(const BraveSidePanelHeader&) = delete;
|
||||
BraveSidePanelHeader& operator=(const BraveSidePanelHeader&) = delete;
|
||||
~BraveSidePanelHeader() override;
|
||||
|
||||
// views::View:
|
||||
void Layout(PassKey) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Delegate> delegate_;
|
||||
};
|
||||
|
||||
#endif // BRAVE_BROWSER_UI_VIEWS_SIDE_PANEL_BRAVE_SIDE_PANEL_HEADER_H_
|
||||
@@ -0,0 +1,124 @@
|
||||
/* Copyright (c) 2026 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "brave/browser/ui/views/side_panel/brave_side_panel_header_controller.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "brave/browser/ui/color/brave_color_id.h"
|
||||
#include "brave/components/vector_icons/vector_icons.h"
|
||||
#include "brave/grit/brave_generated_resources.h"
|
||||
#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
|
||||
#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
|
||||
#include "chrome/browser/ui/side_panel/side_panel_ui.h"
|
||||
#include "chrome/browser/ui/singleton_tabs.h"
|
||||
#include "chrome/common/webui_url_constants.h"
|
||||
#include "chrome/grit/generated_resources.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/base/models/image_model.h"
|
||||
#include "ui/gfx/font.h"
|
||||
#include "ui/gfx/font_list.h"
|
||||
#include "ui/views/controls/button/image_button.h"
|
||||
#include "ui/views/controls/label.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int kHeaderTitleFontSize = 16;
|
||||
constexpr int kHeaderButtonSize = 20;
|
||||
|
||||
std::unique_ptr<views::ImageButton> CreateHeaderImageButton(
|
||||
views::Button::PressedCallback callback,
|
||||
const gfx::VectorIcon& icon,
|
||||
int tooltip_id) {
|
||||
auto button = std::make_unique<views::ImageButton>(std::move(callback));
|
||||
button->SetTooltipText(l10n_util::GetStringUTF16(tooltip_id));
|
||||
button->SetImageModel(
|
||||
views::Button::STATE_NORMAL,
|
||||
ui::ImageModel::FromVectorIcon(icon, kColorSidebarPanelHeaderButton,
|
||||
kHeaderButtonSize));
|
||||
button->SetImageModel(
|
||||
views::Button::STATE_HOVERED,
|
||||
ui::ImageModel::FromVectorIcon(
|
||||
icon, kColorSidebarPanelHeaderButtonHovered, kHeaderButtonSize));
|
||||
return button;
|
||||
}
|
||||
|
||||
// Per-panel header titles. Mirrors V1's hardcoded labels in
|
||||
// BraveReadLaterSidePanelView / BraveBookmarksSidePanelView; we deliberately
|
||||
// don't read from the entry's action item because that text differs from the
|
||||
// label V1 uses in the header.
|
||||
std::u16string GetEntryTitle(SidePanelEntry::Id id) {
|
||||
int message_id = 0;
|
||||
switch (id) {
|
||||
case SidePanelEntry::Id::kReadingList:
|
||||
message_id = IDS_SIDEBAR_READING_LIST_PANEL_HEADER_TITLE;
|
||||
break;
|
||||
case SidePanelEntry::Id::kBookmarks:
|
||||
message_id = IDS_BOOKMARK_MANAGER_TITLE;
|
||||
break;
|
||||
default:
|
||||
return std::u16string();
|
||||
}
|
||||
return l10n_util::GetStringUTF16(message_id);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
BraveSidePanelHeaderController::BraveSidePanelHeaderController(
|
||||
BrowserWindowInterface& browser_window,
|
||||
SidePanelEntry* entry)
|
||||
: browser_window_(browser_window), entry_(entry->GetWeakPtr()) {}
|
||||
|
||||
BraveSidePanelHeaderController::~BraveSidePanelHeaderController() = default;
|
||||
|
||||
std::unique_ptr<views::Label>
|
||||
BraveSidePanelHeaderController::CreatePanelTitle() {
|
||||
CHECK(entry_);
|
||||
auto label =
|
||||
std::make_unique<views::Label>(GetEntryTitle(entry_->key().id()));
|
||||
const int size_delta =
|
||||
kHeaderTitleFontSize - views::Label::GetDefaultFontList().GetFontSize();
|
||||
label->SetFontList(views::Label::GetDefaultFontList()
|
||||
.DeriveWithSizeDelta(size_delta)
|
||||
.DeriveWithWeight(gfx::Font::Weight::SEMIBOLD));
|
||||
label->SetEnabledColor(kColorSidebarPanelHeaderTitle);
|
||||
label->SetAutoColorReadabilityEnabled(false);
|
||||
return label;
|
||||
}
|
||||
|
||||
std::unique_ptr<views::ImageButton>
|
||||
BraveSidePanelHeaderController::CreateLaunchButton() {
|
||||
CHECK(entry_);
|
||||
if (entry_->key().id() == SidePanelEntry::Id::kBookmarks) {
|
||||
return CreateHeaderImageButton(
|
||||
base::BindRepeating(
|
||||
&BraveSidePanelHeaderController::OnLaunchButtonPressed,
|
||||
weak_factory_.GetWeakPtr(), GURL(chrome::kChromeUIBookmarksURL)),
|
||||
kLeoLaunchIcon,
|
||||
IDS_SIDEBAR_READING_LIST_PANEL_HEADER_BOOKMARKS_BUTTON_TOOLTIP);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<views::ImageButton>
|
||||
BraveSidePanelHeaderController::CreateCloseButton() {
|
||||
return CreateHeaderImageButton(
|
||||
base::BindRepeating(&BraveSidePanelHeaderController::OnCloseButtonPressed,
|
||||
weak_factory_.GetWeakPtr()),
|
||||
kLeoCloseIcon, IDS_SIDEBAR_PANEL_CLOSE_BUTTON_TOOLTIP);
|
||||
}
|
||||
|
||||
void BraveSidePanelHeaderController::OnLaunchButtonPressed(const GURL& url) {
|
||||
ShowSingletonTab(base::to_address(browser_window_), url);
|
||||
}
|
||||
|
||||
void BraveSidePanelHeaderController::OnCloseButtonPressed() {
|
||||
if (auto* side_panel_ui = browser_window_->GetFeatures().side_panel_ui()) {
|
||||
side_panel_ui->Close(SidePanelEntry::PanelType::kContent);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/* Copyright (c) 2026 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BRAVE_BROWSER_UI_VIEWS_SIDE_PANEL_BRAVE_SIDE_PANEL_HEADER_CONTROLLER_H_
|
||||
#define BRAVE_BROWSER_UI_VIEWS_SIDE_PANEL_BRAVE_SIDE_PANEL_HEADER_CONTROLLER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/memory/raw_ref.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "brave/browser/ui/views/side_panel/brave_side_panel_header.h"
|
||||
#include "chrome/browser/ui/side_panel/side_panel_entry.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
class BrowserWindowInterface;
|
||||
|
||||
namespace views {
|
||||
class ImageButton;
|
||||
class Label;
|
||||
} // namespace views
|
||||
|
||||
class BraveSidePanelHeaderController : public BraveSidePanelHeader::Delegate {
|
||||
public:
|
||||
BraveSidePanelHeaderController(BrowserWindowInterface& browser_window,
|
||||
SidePanelEntry* entry);
|
||||
BraveSidePanelHeaderController(const BraveSidePanelHeaderController&) =
|
||||
delete;
|
||||
BraveSidePanelHeaderController& operator=(
|
||||
const BraveSidePanelHeaderController&) = delete;
|
||||
~BraveSidePanelHeaderController() override;
|
||||
|
||||
// BraveSidePanelHeader::Delegate:
|
||||
std::unique_ptr<views::Label> CreatePanelTitle() override;
|
||||
std::unique_ptr<views::ImageButton> CreateLaunchButton() override;
|
||||
std::unique_ptr<views::ImageButton> CreateCloseButton() override;
|
||||
|
||||
private:
|
||||
void OnLaunchButtonPressed(const GURL& url);
|
||||
void OnCloseButtonPressed();
|
||||
|
||||
const raw_ref<BrowserWindowInterface> browser_window_;
|
||||
base::WeakPtr<SidePanelEntry> entry_;
|
||||
base::WeakPtrFactory<BraveSidePanelHeaderController> weak_factory_{this};
|
||||
};
|
||||
|
||||
#endif // BRAVE_BROWSER_UI_VIEWS_SIDE_PANEL_BRAVE_SIDE_PANEL_HEADER_CONTROLLER_H_
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "brave/browser/ui/brave_browser_actions.h"
|
||||
#include "brave/browser/ui/brave_browser_command_controller.h"
|
||||
#include "brave/browser/ui/brave_browser_content_setting_bubble_model_delegate.h"
|
||||
#include "brave/browser/ui/sidebar/buildflags/buildflags.h"
|
||||
#include "brave/browser/ui/toolbar/brave_location_bar_model_delegate.h"
|
||||
#include "brave/browser/ui/views/side_panel/bookmarks/brave_bookmarks_side_panel_coordinator.h"
|
||||
#include "brave/browser/ui/views/side_panel/brave_side_panel_coordinator.h"
|
||||
@@ -25,18 +26,24 @@
|
||||
BraveBrowserContentSettingBubbleModelDelegate
|
||||
#define BrowserWindowFeatures BrowserWindowFeatures_ChromiumImpl
|
||||
#define SidePanelCoordinator BraveSidePanelCoordinator
|
||||
#define BookmarksSidePanelCoordinator BraveBookmarksSidePanelCoordinator
|
||||
#define BrowserActions BraveBrowserActions
|
||||
#define BrowserCommandController BraveBrowserCommandController
|
||||
|
||||
#if !BUILDFLAG(ENABLE_SIDEBAR_V2)
|
||||
#define BookmarksSidePanelCoordinator BraveBookmarksSidePanelCoordinator
|
||||
#endif
|
||||
|
||||
#include <chrome/browser/ui/browser_window/internal/browser_window_features.cc>
|
||||
|
||||
#if !BUILDFLAG(ENABLE_SIDEBAR_V2)
|
||||
#undef BookmarksSidePanelCoordinator
|
||||
#endif
|
||||
|
||||
#undef BrowserCommandController
|
||||
#undef BrowserActions
|
||||
#undef SidePanelCoordinator
|
||||
#undef BrowserWindowFeatures
|
||||
#undef BrowserContentSettingBubbleModelDelegate
|
||||
#undef BrowserActions
|
||||
#undef BrowserCommandController
|
||||
|
||||
const SidePanelUI* BrowserWindowFeatures_ChromiumImpl::side_panel_ui() const {
|
||||
return const_cast<BrowserWindowFeatures_ChromiumImpl*>(this)->side_panel_ui();
|
||||
|
||||
+5
@@ -3,11 +3,16 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "brave/browser/ui/sidebar/buildflags/buildflags.h"
|
||||
#include "brave/browser/ui/views/side_panel/brave_read_later_side_panel_view.h"
|
||||
#include "chrome/browser/ui/views/side_panel/reading_list/read_later_side_panel_web_view.h"
|
||||
|
||||
#if !BUILDFLAG(ENABLE_SIDEBAR_V2)
|
||||
#define ReadLaterSidePanelWebView BraveReadLaterSidePanelView
|
||||
#endif
|
||||
|
||||
#include <chrome/browser/ui/views/side_panel/reading_list/reading_list_side_panel_coordinator.cc>
|
||||
|
||||
#if !BUILDFLAG(ENABLE_SIDEBAR_V2)
|
||||
#undef ReadLaterSidePanelWebView
|
||||
#endif
|
||||
|
||||
@@ -13,11 +13,10 @@
|
||||
// .cc pulls it in.
|
||||
#include "chrome/browser/ui/views/side_panel/side_panel.h"
|
||||
|
||||
// Rename the upstream RemoveHeaderView implementation so we can provide
|
||||
// our own method. Upstream RemoveHeaderView() resets Border always but we
|
||||
// want to preserve the no-border state. As we don't set any header to all
|
||||
// panels, making it empty would not add any side-effect.
|
||||
#define RemoveHeaderView RemoveHeaderView_UnUsed
|
||||
// Rename the upstream Add/RemoveHeaderView implementation so we can provide
|
||||
// a thin wrapper that reapplies border state.
|
||||
#define AddHeaderView AddHeaderView_ChromiumImpl
|
||||
#define RemoveHeaderView RemoveHeaderView_ChromiumImpl
|
||||
|
||||
// Rename the upstream Open/Close implementation so we can provide a thin
|
||||
// wrapper that reapplies border state after UpdateVisibility() runs.
|
||||
@@ -31,6 +30,7 @@
|
||||
#undef Close
|
||||
#undef Open
|
||||
#undef RemoveHeaderView
|
||||
#undef AddHeaderView
|
||||
|
||||
#endif // BUILDFLAG(ENABLE_SIDEBAR_V2)
|
||||
|
||||
@@ -79,19 +79,32 @@ void SidePanel::UpdateBorder() {
|
||||
return;
|
||||
}
|
||||
|
||||
// When a Brave header is attached, reserve top inset for it so the header
|
||||
// paints over the border strip without overlapping content.
|
||||
const int header_top_inset =
|
||||
header_view_ ? header_view_->GetPreferredSize().height() : 0;
|
||||
|
||||
if (rounded_border_enabled_) {
|
||||
// Upstream GetBorderInsets() has a negative top to overlap the toolbar;
|
||||
// Brave doesn't need that overlap.
|
||||
SetBorder(views::CreateEmptyBorder(GetBorderInsets().set_top(0)));
|
||||
SetBorder(
|
||||
views::CreateEmptyBorder(GetBorderInsets().set_top(header_top_inset)));
|
||||
} else {
|
||||
SetBorder(nullptr);
|
||||
SetBorder(
|
||||
views::CreateEmptyBorder(gfx::Insets::TLBR(header_top_inset, 0, 0, 0)));
|
||||
}
|
||||
|
||||
border_view_->SetVisible(rounded_border_enabled_);
|
||||
}
|
||||
|
||||
void SidePanel::AddHeaderView(std::unique_ptr<views::View> view) {
|
||||
AddHeaderView_ChromiumImpl(std::move(view));
|
||||
UpdateBorder();
|
||||
}
|
||||
|
||||
void SidePanel::RemoveHeaderView() {
|
||||
// See above method overriding's comment why it's empty.
|
||||
RemoveHeaderView_ChromiumImpl();
|
||||
UpdateBorder();
|
||||
}
|
||||
|
||||
#endif // BUILDFLAG(ENABLE_SIDEBAR_V2)
|
||||
|
||||
@@ -22,14 +22,15 @@
|
||||
// Override Open/Close to apply our border style whenever open/close panel.
|
||||
// Override VisibilityChanged() is not sufficient as it's not called when
|
||||
// opening another panel while other panel is opened.
|
||||
#define GetContentParentView(...) \
|
||||
GetContentParentView(__VA_ARGS__); \
|
||||
void SetResizeArea(std::unique_ptr<views::View> resize_area); \
|
||||
void SetRoundedBorderEnabled(bool enabled); \
|
||||
void UpdateBorder(); \
|
||||
void Open_ChromiumImpl(bool animated); \
|
||||
void Close_ChromiumImpl(bool animated); \
|
||||
void RemoveHeaderView_UnUsed()
|
||||
#define GetContentParentView(...) \
|
||||
GetContentParentView(__VA_ARGS__); \
|
||||
void SetResizeArea(std::unique_ptr<views::View> resize_area); \
|
||||
void SetRoundedBorderEnabled(bool enabled); \
|
||||
void UpdateBorder(); \
|
||||
void Open_ChromiumImpl(bool animated); \
|
||||
void Close_ChromiumImpl(bool animated); \
|
||||
void AddHeaderView_ChromiumImpl(std::unique_ptr<views::View> view); \
|
||||
void RemoveHeaderView_ChromiumImpl()
|
||||
|
||||
#define did_resize_ \
|
||||
did_resize_ = false; \
|
||||
|
||||
Reference in New Issue
Block a user