diff --git a/app/extensions/brave/img/tabs/loading.svg b/app/extensions/brave/img/tabs/loading.svg
new file mode 100644
index 00000000000..eb6ba3740a0
--- /dev/null
+++ b/app/extensions/brave/img/tabs/loading.svg
@@ -0,0 +1,11 @@
+
+
+
diff --git a/app/renderer/components/styles/animations.js b/app/renderer/components/styles/animations.js
new file mode 100644
index 00000000000..38c8bddb349
--- /dev/null
+++ b/app/renderer/components/styles/animations.js
@@ -0,0 +1,16 @@
+/* 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 http://mozilla.org/MPL/2.0/. */
+
+const spinKeyframes = {
+ 'from': {
+ transform: 'rotate(0deg)'
+ },
+ 'to': {
+ transform: 'rotate(360deg)'
+ }
+}
+
+module.exports = {
+ spinKeyframes
+}
diff --git a/app/renderer/components/styles/global.js b/app/renderer/components/styles/global.js
index ed3961ac1cd..def03e9fe89 100644
--- a/app/renderer/components/styles/global.js
+++ b/app/renderer/components/styles/global.js
@@ -78,6 +78,9 @@ const globalStyles = {
urlBarOutline: '#bbb',
alphaWhite: 'rgba(255,255,255,0.8)'
},
+ filter: {
+ makeWhite: 'brightness(0) invert(1)'
+ },
radius: {
borderRadius: '4px',
borderRadiusTabs: '4px',
diff --git a/app/renderer/components/tabContent.js b/app/renderer/components/tabContent.js
index 7196b4635a7..044c1216b40 100644
--- a/app/renderer/components/tabContent.js
+++ b/app/renderer/components/tabContent.js
@@ -7,10 +7,12 @@ const ImmutableComponent = require('../../../js/components/immutableComponent')
const {StyleSheet, css} = require('aphrodite/no-important')
const globalStyles = require('./styles/global')
const {isWindows} = require('../../common/lib/platformUtil')
-const {getTextColorForBackground} = require('../../../js/lib/color')
const {tabs} = require('../../../js/constants/config')
const {hasBreakpoint, hasRelativeCloseIcon,
- hasFixedCloseIcon, hasVisibleSecondaryIcon} = require('../lib/tabUtil')
+ hasFixedCloseIcon, hasVisibleSecondaryIcon, getTabIconColor} = require('../lib/tabUtil')
+const {spinKeyframes} = require('./styles/animations')
+
+const loadingIconSvg = require('../../extensions/brave/img/tabs/loading.svg')
const newSessionSvg = require('../../extensions/brave/img/tabs/new_session.svg')
const privateSvg = require('../../extensions/brave/img/tabs/private.svg')
const closeTabSvg = require('../../extensions/brave/img/tabs/close_btn_normal.svg')
@@ -57,12 +59,6 @@ class Favicon extends ImmutableComponent {
return !this.props.isLoading && this.props.tab.get('icon')
}
- get loadingIcon () {
- return this.props.isLoading
- ? globalStyles.appIcons.loading
- : null
- }
-
get defaultIcon () {
return (!this.props.isLoading && !this.favicon)
? globalStyles.appIcons.defaultIcon
@@ -80,18 +76,25 @@ class Favicon extends ImmutableComponent {
render () {
const iconStyles = StyleSheet.create({
- favicon: {backgroundImage: `url(${this.favicon})`}
+ favicon: {backgroundImage: `url(${this.favicon})`},
+ loadingIconColor: {
+ // Don't change icon color unless when it should be white
+ filter: getTabIconColor(this.props) === 'white' ? globalStyles.filter.makeWhite : 'none'
+ }
})
return !this.shouldHideFavicon
?
+ symbol={
+ (this.props.isLoading && css(styles.loadingIcon, iconStyles.loadingIconColor)) ||
+ this.defaultIcon
+ } />
: null
}
}
@@ -166,10 +169,7 @@ class NewSessionIcon extends ImmutableComponent {
}
get iconColor () {
- const themeColor = this.props.tab.get('themeColor') || this.props.tab.get('computedThemeColor')
- return this.props.paintTabs && themeColor
- ? getTextColorForBackground(themeColor)
- : globalStyles.color.black100
+ return getTabIconColor(this.props)
}
render () {
@@ -206,22 +206,11 @@ class TabTitle extends ImmutableComponent {
hasFixedCloseIcon(this.props)
}
- get themeColor () {
- const themeColor = this.props.tab.get('themeColor') || this.props.tab.get('computedThemeColor')
- const activeNonPrivateTab = !this.props.tab.get('isPrivate') && this.props.isActive
- const isPrivateTab = this.props.tab.get('isPrivate') && (this.props.isActive || this.props.tab.get('hoverState'))
- const defaultColor = isPrivateTab ? globalStyles.color.white100 : globalStyles.color.black100
-
- return activeNonPrivateTab && this.props.paintTabs && !!themeColor
- ? getTextColorForBackground(themeColor)
- : defaultColor
- }
-
render () {
const titleStyles = StyleSheet.create({
gradientText: {
backgroundImage: `-webkit-linear-gradient(left,
- ${this.themeColor} 90%, ${globalStyles.color.almostInvisible} 100%)`
+ ${getTabIconColor(this.props)} 90%, ${globalStyles.color.almostInvisible} 100%)`
}
})
@@ -286,6 +275,14 @@ const styles = StyleSheet.create({
backgroundPosition: 'center center'
},
+ loadingIcon: {
+ backgroundImage: `url(${loadingIconSvg})`,
+ animationName: spinKeyframes,
+ animationTimingFunction: 'linear',
+ animationDuration: '1200ms',
+ animationIterationCount: 'infinite'
+ },
+
audioIcon: {
color: globalStyles.color.highlightBlue,
fontSize: '16px'
diff --git a/app/renderer/lib/tabUtil.js b/app/renderer/lib/tabUtil.js
index ae0984966d5..4b167548a77 100644
--- a/app/renderer/lib/tabUtil.js
+++ b/app/renderer/lib/tabUtil.js
@@ -6,6 +6,7 @@ const styles = require('../components/styles/global')
const frameStateUtil = require('../../../js/state/frameStateUtil')
const settings = require('../../../js/constants/settings')
const getSetting = require('../../../js/settings').getSetting
+const {getTextColorForBackground} = require('../../../js/lib/color')
/**
* Get tab's breakpoint name for current tab size.
@@ -69,6 +70,22 @@ module.exports.hasFixedCloseIcon = (props) => {
return props.isActive && module.exports.hasBreakpoint(props, ['small', 'extraSmall'])
}
+/**
+ * Gets the icon color based on tab's background
+ * @param {Object} props - Object that hosts the tab props
+ * @returns {String} Contrasting color to use based on tab's color
+ */
+module.exports.getTabIconColor = (props) => {
+ const themeColor = props.tab.get('themeColor') || props.tab.get('computedThemeColor')
+ const activeNonPrivateTab = !props.tab.get('isPrivate') && props.isActive
+ const isPrivateTab = props.tab.get('isPrivate') && (props.isActive || props.tab.get('hoverState'))
+ const defaultColor = isPrivateTab ? styles.color.white100 : styles.color.black100
+
+ return activeNonPrivateTab && props.paintTabs && !!themeColor
+ ? getTextColorForBackground(themeColor)
+ : defaultColor
+}
+
/**
* Updates the tab page index to the specified frameProps
* @param frameProps Any frame belonging to the page
diff --git a/js/components/tab.js b/js/components/tab.js
index c4a05413097..e769ee31864 100644
--- a/js/components/tab.js
+++ b/js/components/tab.js
@@ -324,6 +324,7 @@ class Tab extends ImmutableComponent {
)}>
)
- assert.equal(wrapper.props().symbol, globalStyles.appIcons.loading)
+ assert.equal(wrapper.props()['data-test-id'], 'loading')
})
it('should not show favicon for new tab page', function () {
const wrapper = shallow(