[Sidebar] Suppress animation when switching between panels (#36203)

Add suppress_animations=true when ActivatePanelItem is called while a
panel is already active.

Resolves brave/brave-browser#55285
This commit is contained in:
Simon Hong
2026-05-06 17:05:52 +09:00
committed by GitHub
parent b710c75ce3
commit 80e4faf421
3 changed files with 114 additions and 4 deletions
+95
View File
@@ -2223,6 +2223,101 @@ IN_PROC_BROWSER_TEST_F(SidebarBrowserTest,
<< "No-border resize area width should equal kNoBorderResizeAreaWidth";
}
class ScopedSidePanelUIForTesting {
public:
ScopedSidePanelUIForTesting(SidebarController* controller, SidePanelUI* ui)
: controller_(controller) {
controller_->SetSidePanelUIForTesting(ui);
}
~ScopedSidePanelUIForTesting() {
controller_->SetSidePanelUIForTesting(nullptr);
}
private:
raw_ptr<SidebarController> controller_;
};
class MockSidePanelUI : public SidePanelUI {
public:
MOCK_METHOD(void,
Show,
(SidePanelEntryId, std::optional<SidePanelOpenTrigger>, bool),
(override));
MOCK_METHOD(void,
Show,
(SidePanelEntryKey, std::optional<SidePanelOpenTrigger>, bool),
(override));
MOCK_METHOD(void, ShowFrom, (SidePanelEntryKey, gfx::Rect), (override));
MOCK_METHOD(void,
Close,
(SidePanelEntry::PanelType, SidePanelEntryHideReason, bool),
(override));
MOCK_METHOD(void,
Toggle,
(SidePanelEntryKey, SidePanelOpenTrigger),
(override));
MOCK_METHOD(std::optional<SidePanelEntryId>,
GetCurrentEntryId,
(SidePanelEntry::PanelType),
(const, override));
MOCK_METHOD(int,
GetCurrentEntryDefaultContentWidth,
(SidePanelEntry::PanelType),
(const, override));
MOCK_METHOD(bool,
IsSidePanelShowing,
(SidePanelEntry::PanelType),
(const, override));
MOCK_METHOD(bool,
IsSidePanelEntryShowing,
(const SidePanelEntryKey&),
(const, override));
MOCK_METHOD(bool,
IsSidePanelEntryShowing,
(const SidePanelEntry::Key&, bool),
(const, override));
MOCK_METHOD(base::CallbackListSubscription,
RegisterSidePanelShown,
(SidePanelEntry::PanelType, ShownCallback),
(override));
MOCK_METHOD(void,
OnActiveTabChanged,
(content::WebContents*, content::WebContents*, bool),
(override));
MOCK_METHOD(content::WebContents*,
GetWebContentsForTest,
(SidePanelEntryId),
(override));
MOCK_METHOD(void, DisableAnimationsForTesting, (), (override));
MOCK_METHOD(void, SetNoDelaysForTesting, (bool), (override));
};
// Verify suppress_animations is false when opening from a closed state and
// true when switching panels while one is already active.
IN_PROC_BROWSER_TEST_F(SidebarBrowserTest,
SidebarV2ActivatePanelItemSuppressAnimation) {
MockSidePanelUI mock_ui;
ScopedSidePanelUIForTesting scoped_ui(controller(), &mock_ui);
// No active panel: opening should animate (suppress_animations=false).
ASSERT_FALSE(model()->active_index().has_value())
<< "Expected no active panel before first ActivatePanelItem call";
EXPECT_CALL(mock_ui,
Show(testing::An<SidePanelEntryId>(), testing::Eq(std::nullopt),
/*suppress_animations=*/false));
controller()->ActivatePanelItem(SidebarItem::BuiltInItemType::kBookmarks);
testing::Mock::VerifyAndClearExpectations(&mock_ui);
controller()->UpdateActiveItemState(SidebarItem::BuiltInItemType::kBookmarks);
// Active panel present: switching panels should suppress animations.
ASSERT_TRUE(model()->active_index().has_value())
<< "Expected active panel after UpdateActiveItemState";
EXPECT_CALL(mock_ui,
Show(testing::An<SidePanelEntryId>(), testing::Eq(std::nullopt),
/*suppress_animations=*/true));
controller()->ActivatePanelItem(SidebarItem::BuiltInItemType::kReadingList);
}
#endif // BUILDFLAG(ENABLE_SIDEBAR_V2)
} // namespace sidebar
+13 -4
View File
@@ -10,6 +10,7 @@
#include "base/check.h"
#include "base/check_op.h"
#include "brave/browser/ui/sidebar/buildflags/buildflags.h"
#include "brave/browser/ui/sidebar/sidebar.h"
#include "brave/browser/ui/sidebar/sidebar_model.h"
#include "brave/browser/ui/sidebar/sidebar_service_factory.h"
@@ -150,17 +151,25 @@ void SidebarController::ActivateItemAt(std::optional<size_t> index,
void SidebarController::ActivatePanelItem(
SidebarItem::BuiltInItemType panel_item) {
// For panel item activation, SidePanelUI is the single source of truth.
auto* side_panel_ui = browser_->GetFeatures().side_panel_ui();
if (!side_panel_ui) {
return;
}
auto* side_panel_ui = side_panel_ui_for_testing_
? side_panel_ui_for_testing_.get()
: browser_->GetFeatures().side_panel_ui();
CHECK(side_panel_ui);
if (panel_item == SidebarItem::BuiltInItemType::kNone) {
side_panel_ui->Close(SidePanelEntry::PanelType::kContent);
return;
}
#if BUILDFLAG(ENABLE_SIDEBAR_V2)
// Suppress opening animation when we have active item.
// When opening another panel while other panel is visible,
// we don't need to open new panel with animation.
const bool suppress_animations = sidebar_model_->active_index().has_value();
side_panel_ui->Show(sidebar::SidePanelIdFromSideBarItemType(panel_item),
/*open_trigger*/ std::nullopt, suppress_animations);
#else
side_panel_ui->Show(sidebar::SidePanelIdFromSideBarItemType(panel_item));
#endif
}
void SidebarController::DeactivateCurrentPanel() {
+6
View File
@@ -19,6 +19,7 @@
class Browser;
class GURL;
class Profile;
class SidePanelUI;
class TabStripModel;
namespace sidebar {
@@ -63,6 +64,10 @@ class SidebarController : public SidebarService::Observer {
void ActivatePanelItem(SidebarItem::BuiltInItemType panel_item);
void DeactivateCurrentPanel();
void SetSidePanelUIForTesting(SidePanelUI* side_panel_ui) {
side_panel_ui_for_testing_ = side_panel_ui;
}
// If current browser doesn't have a tab for |url|, active tab will load
// |url|. Otherwise, existing tab will be activated.
// ShowSingletonTab() has similar functionality but it loads url in the
@@ -99,6 +104,7 @@ class SidebarController : public SidebarService::Observer {
raw_ptr<Profile> profile_ = nullptr;
raw_ptr<Browser> browser_ = nullptr;
raw_ptr<Sidebar> sidebar_ = nullptr;
raw_ptr<SidePanelUI> side_panel_ui_for_testing_ = nullptr;
std::unique_ptr<SidebarModel> sidebar_model_;
std::unique_ptr<SidebarWebPanelController> web_panel_controller_;