Commit 4df86c4e authored by John Lee's avatar John Lee Committed by Commit Bot

WebUI Tab Strip: Adjust tab sizes based on container layout

Bug: 1013646
Change-Id: Ib4ef4402b3d4fae7efdb8f5c474886e8da1fc99e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1879952Reviewed-by: default avatarDemetrios Papadopoulos <dpapad@chromium.org>
Commit-Queue: John Lee <johntlee@chromium.org>
Cr-Commit-Position: refs/heads/master@{#709594}
parent 5cf6316c
<style> <style>
:host { :host {
--tabstrip-tab-title-height: 40px;
--tabstrip-tab-transition-duration: 250ms; --tabstrip-tab-transition-duration: 250ms;
cursor: pointer; cursor: pointer;
......
...@@ -212,7 +212,7 @@ export class TabElement extends CustomElement { ...@@ -212,7 +212,7 @@ export class TabElement extends CustomElement {
const animation = this.animate( const animation = this.animate(
[ [
{maxWidth: 0, opacity: 0}, {maxWidth: 0, opacity: 0},
{maxWidth: '280px', opacity: 1}, {maxWidth: 'var(--tabstrip-tab-width)', opacity: 1},
], ],
{ {
duration: DEFAULT_ANIMATION_DURATION, duration: DEFAULT_ANIMATION_DURATION,
...@@ -229,7 +229,7 @@ export class TabElement extends CustomElement { ...@@ -229,7 +229,7 @@ export class TabElement extends CustomElement {
return new Promise(resolve => { return new Promise(resolve => {
const animation = this.animate( const animation = this.animate(
[ [
{maxWidth: '280px', opacity: 1}, {maxWidth: 'var(--tabstrip-tab-width)', opacity: 1},
{maxWidth: 0, opacity: 0}, {maxWidth: 0, opacity: 0},
], ],
{ {
......
<style> <style>
:host { :host {
--tabstrip-tab-height: calc(var(--tabstrip-tab-title-height) +
var(--tabstrip-tab-thumbnail-height));
--tabstrip-tab-width: var(--tabstrip-tab-thumbnail-width);
background: var(--tabstrip-background-color); background: var(--tabstrip-background-color);
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;
......
...@@ -73,6 +73,8 @@ class TabListElement extends CustomElement { ...@@ -73,6 +73,8 @@ class TabListElement extends CustomElement {
/** @type {!Element} */ ( /** @type {!Element} */ (
this.shadowRoot.querySelector('#tabsContainer')); this.shadowRoot.querySelector('#tabsContainer'));
addWebUIListener(
'layout-changed', layout => this.applyCSSDictionary_(layout));
addWebUIListener('theme-changed', () => this.fetchAndUpdateColors_()); addWebUIListener('theme-changed', () => this.fetchAndUpdateColors_());
this.tabStripEmbedderProxy_.observeThemeChanges(); this.tabStripEmbedderProxy_.observeThemeChanges();
...@@ -114,8 +116,21 @@ class TabListElement extends CustomElement { ...@@ -114,8 +116,21 @@ class TabListElement extends CustomElement {
this.animationPromises = this.animationPromises.then(() => promise); this.animationPromises = this.animationPromises.then(() => promise);
} }
/**
* @param {!Object<string, string>} dictionary
* @private
*/
applyCSSDictionary_(dictionary) {
for (const [cssVariable, value] of Object.entries(dictionary)) {
this.style.setProperty(cssVariable, value);
}
}
connectedCallback() { connectedCallback() {
this.tabStripEmbedderProxy_.getLayout().then(
layout => this.applyCSSDictionary_(layout));
this.fetchAndUpdateColors_(); this.fetchAndUpdateColors_();
this.tabsApi_.getTabs().then(tabs => { this.tabsApi_.getTabs().then(tabs => {
tabs.forEach(tab => this.onTabCreated_(tab)); tabs.forEach(tab => this.onTabCreated_(tab));
this.moveOrScrollToActiveTab_(); this.moveOrScrollToActiveTab_();
...@@ -153,11 +168,8 @@ class TabListElement extends CustomElement { ...@@ -153,11 +168,8 @@ class TabListElement extends CustomElement {
/** @private */ /** @private */
fetchAndUpdateColors_() { fetchAndUpdateColors_() {
this.tabStripEmbedderProxy_.getColors().then(colors => { this.tabStripEmbedderProxy_.getColors().then(
for (const [cssVariable, rgbaValue] of Object.entries(colors)) { colors => this.applyCSSDictionary_(colors));
this.style.setProperty(cssVariable, rgbaValue);
}
});
} }
/** /**
......
...@@ -14,8 +14,6 @@ ...@@ -14,8 +14,6 @@
--google-blue-500-rgb: 66, 133, 244; --google-blue-500-rgb: 66, 133, 244;
--tabstrip-background-color: $i18n{frameColor}; --tabstrip-background-color: $i18n{frameColor};
--tabstrip-tab-height: 216px;
--tabstrip-tab-width: 288px;
--tabstrip-tab-border-radius: 8px; --tabstrip-tab-border-radius: 8px;
--tabstrip-tab-active-border-color: rgb(var(--google-blue-500-rgb)); --tabstrip-tab-active-border-color: rgb(var(--google-blue-500-rgb));
} }
......
...@@ -18,6 +18,14 @@ export class TabStripEmbedderProxy { ...@@ -18,6 +18,14 @@ export class TabStripEmbedderProxy {
return sendWithPromise('getThemeColors'); return sendWithPromise('getThemeColors');
} }
/**
* @return {!Promise<!Object<string, string>>} Object with CSS variables
* as keys and pixel lengths as values
*/
getLayout() {
return sendWithPromise('getLayout');
}
observeThemeChanges() { observeThemeChanges() {
chrome.send('observeThemeChanges'); chrome.send('observeThemeChanges');
} }
......
...@@ -134,7 +134,7 @@ class TabStripUIHandler : public content::WebUIMessageHandler, ...@@ -134,7 +134,7 @@ class TabStripUIHandler : public content::WebUIMessageHandler,
void NotifyLayoutChanged() { void NotifyLayoutChanged() {
if (!IsJavascriptAllowed()) if (!IsJavascriptAllowed())
return; return;
FireWebUIListener("layout-changed"); FireWebUIListener("layout-changed", embedder_->GetLayout().AsDictionary());
} }
// TabStripModelObserver: // TabStripModelObserver:
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.h" #include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h" #include "base/values.h"
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
...@@ -42,11 +43,14 @@ TabStripUILayout TabStripUILayout::CalculateForWebViewportSize( ...@@ -42,11 +43,14 @@ TabStripUILayout TabStripUILayout::CalculateForWebViewportSize(
base::Value TabStripUILayout::AsDictionary() const { base::Value TabStripUILayout::AsDictionary() const {
base::Value dict(base::Value::Type::DICTIONARY); base::Value dict(base::Value::Type::DICTIONARY);
dict.SetIntKey("--tabstrip-tab-list-padding", padding_around_tab_list); dict.SetStringKey("--tabstrip-tab-list-padding",
dict.SetIntKey("--tabstrip-tab-title-height", tab_title_height); base::NumberToString(padding_around_tab_list) + "px");
dict.SetIntKey("--tabstrip-tab-thumbnail-width", tab_thumbnail_size.width()); dict.SetStringKey("--tabstrip-tab-title-height",
dict.SetIntKey("--tabstrip-tab-thumbnail-height", base::NumberToString(tab_title_height) + "px");
tab_thumbnail_size.height()); dict.SetStringKey("--tabstrip-tab-thumbnail-width",
base::NumberToString(tab_thumbnail_size.width()) + "px");
dict.SetStringKey("--tabstrip-tab-thumbnail-height",
base::NumberToString(tab_thumbnail_size.height()) + "px");
return dict; return dict;
} }
......
...@@ -107,6 +107,10 @@ suite('TabList', () => { ...@@ -107,6 +107,10 @@ suite('TabList', () => {
'--background-color': 'white', '--background-color': 'white',
'--foreground-color': 'black', '--foreground-color': 'black',
}); });
testTabStripEmbedderProxy.setLayout({
'--height': '100px',
'--width': '150px',
});
TabStripEmbedderProxy.instance_ = testTabStripEmbedderProxy; TabStripEmbedderProxy.instance_ = testTabStripEmbedderProxy;
tabList = document.createElement('tabstrip-tab-list'); tabList = document.createElement('tabstrip-tab-list');
...@@ -137,6 +141,38 @@ suite('TabList', () => { ...@@ -137,6 +141,38 @@ suite('TabList', () => {
assertEquals(tabList.style.getPropertyValue('--foreground-color'), 'blue'); assertEquals(tabList.style.getPropertyValue('--foreground-color'), 'blue');
}); });
test('sets layout variables on init', async () => {
await testTabStripEmbedderProxy.whenCalled('getLayout');
assertEquals(tabList.style.getPropertyValue('--height'), '100px');
assertEquals(tabList.style.getPropertyValue('--width'), '150px');
});
test('updates layout variables when layout changes', async () => {
webUIListenerCallback('layout-changed', {
'--height': '10000px',
'--width': '10px',
});
await testTabStripEmbedderProxy.whenCalled('getLayout');
assertEquals(tabList.style.getPropertyValue('--height'), '10000px');
assertEquals(tabList.style.getPropertyValue('--width'), '10px');
});
test('calculates the correct unpinned tab width and height', async () => {
webUIListenerCallback('layout-changed', {
'--tabstrip-tab-thumbnail-height': '132px',
'--tabstrip-tab-thumbnail-width': '200px',
'--tabstrip-tab-title-height': '15px',
});
await testTabStripEmbedderProxy.whenCalled('getLayout');
const tabListStyle = window.getComputedStyle(tabList);
assertEquals(
tabListStyle.getPropertyValue('--tabstrip-tab-height').trim(),
'calc(15px + 132px)');
assertEquals(
tabListStyle.getPropertyValue('--tabstrip-tab-width').trim(), '200px');
});
test('creates a tab element for each tab', () => { test('creates a tab element for each tab', () => {
const tabElements = getUnpinnedTabs(); const tabElements = getUnpinnedTabs();
assertEquals(tabs.length, tabElements.length); assertEquals(tabs.length, tabElements.length);
......
...@@ -36,6 +36,9 @@ suite('Tab', function() { ...@@ -36,6 +36,9 @@ suite('Tab', function() {
document.body.innerHTML = ''; document.body.innerHTML = '';
// Set CSS variable for animations
document.body.style.setProperty('--tabstrip-tab-width', '280px');
testTabStripEmbedderProxy = new TestTabStripEmbedderProxy(); testTabStripEmbedderProxy = new TestTabStripEmbedderProxy();
TabStripEmbedderProxy.instance_ = testTabStripEmbedderProxy; TabStripEmbedderProxy.instance_ = testTabStripEmbedderProxy;
......
...@@ -9,11 +9,14 @@ export class TestTabStripEmbedderProxy extends TestBrowserProxy { ...@@ -9,11 +9,14 @@ export class TestTabStripEmbedderProxy extends TestBrowserProxy {
super([ super([
'closeContainer', 'closeContainer',
'getColors', 'getColors',
'getLayout',
'isVisible', 'isVisible',
'observeThemeChanges', 'observeThemeChanges',
'showTabContextMenu', 'showTabContextMenu',
]); ]);
this.colors_ = {};
this.layout_ = {};
this.visible_ = false; this.visible_ = false;
} }
...@@ -22,6 +25,11 @@ export class TestTabStripEmbedderProxy extends TestBrowserProxy { ...@@ -22,6 +25,11 @@ export class TestTabStripEmbedderProxy extends TestBrowserProxy {
return Promise.resolve(this.colors_); return Promise.resolve(this.colors_);
} }
getLayout() {
this.methodCalled('getLayout');
return Promise.resolve(this.layout_);
}
isVisible() { isVisible() {
this.methodCalled('isVisible'); this.methodCalled('isVisible');
return this.visible_; return this.visible_;
...@@ -31,6 +39,10 @@ export class TestTabStripEmbedderProxy extends TestBrowserProxy { ...@@ -31,6 +39,10 @@ export class TestTabStripEmbedderProxy extends TestBrowserProxy {
this.colors_ = colors; this.colors_ = colors;
} }
setLayout(layout) {
this.layout_ = layout;
}
setVisible(visible) { setVisible(visible) {
this.visible_ = visible; this.visible_ = visible;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment