Skip to content
This repository has been archived by the owner on Dec 11, 2019. It is now read-only.

Commit

Permalink
add gradient layer to mimic current title gradient
Browse files Browse the repository at this point in the history
- text w/ gradient can be buggy. Let's do it with a layer
Auditors: @luixxiul
fix #8414
fix #9398
  • Loading branch information
cezaraugusto committed Sep 19, 2017
1 parent 321281b commit a25ca8f
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 33 deletions.
44 changes: 44 additions & 0 deletions app/common/state/tabUIState.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
const settings = require('../../../js/constants/settings')

// State helpers
const partitionState = require('../../common/state/tabContentState/partitionState')
const privateState = require('../../common/state/tabContentState/privateState')
const closeState = require('../../common/state/tabContentState/closeState')
const frameStateUtil = require('../../../js/state/frameStateUtil')

Expand All @@ -18,6 +20,7 @@ const {getSetting} = require('../../../js/settings')

// Styles
const {intersection} = require('../../renderer/components/styles/global')
const {theme} = require('../../renderer/components/styles/theme')

module.exports.getThemeColor = (state, frameKey) => {
const frame = frameStateUtil.getFrameByKey(state, frameKey)
Expand Down Expand Up @@ -114,3 +117,44 @@ module.exports.centralizeTabIcons = (state, frameKey, isPinned) => {

return isPinned || isEntryIntersected(state, 'tabs', intersection.at40)
}

module.exports.getTabEndIconBackgroundColor = (state, frameKey) => {
const frame = frameStateUtil.getFrameByKey(state, frameKey)

if (frame == null) {
if (process.env.NODE_ENV !== 'test') {
console.error('Unable to find frame for getTabEndIconBackgroundColor method')
}
return false
}

const themeColor = module.exports.getThemeColor(state, frameKey)
const isPrivate = privateState.isPrivateTab(state, frameKey)
const isPartition = partitionState.isPartitionTab(state, frameKey)
const isHover = frameStateUtil.getTabHoverState(state, frameKey)
const isActive = frameStateUtil.isFrameKeyActive(state, frameKey)
const hasCloseIcon = closeState.showCloseTabIcon(state, frameKey)
const isIntersecting = isEntryIntersected(state, 'tabs', intersection.at40)

let backgroundColor = theme.tab.background

if (isActive && themeColor) {
backgroundColor = themeColor
}
if (isActive && !themeColor) {
backgroundColor = theme.tab.active.background
}
if (isIntersecting) {
backgroundColor = 'transparent'
}
if (!isActive && isPrivate) {
backgroundColor = theme.tab.private.background
}
if ((isActive || isHover) && isPrivate) {
backgroundColor = theme.tab.active.private.background
}

return isPartition || isPrivate || hasCloseIcon
? `linear-gradient(to left, ${backgroundColor} 10px, transparent 40px)`
: `linear-gradient(to left, ${backgroundColor} 0, transparent 12px)`
}
22 changes: 11 additions & 11 deletions app/renderer/components/styles/global.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
/* 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/. */
* 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 {opacityIncreaseKeyframes} = require('./animations')

/**
* Use this file when the style you need
* is applied in more than one element, or depends on it
* Use theme.js file to include colors that can be customized
*
* TODO:
* remove unnecessary styles properties (as items get refactored)
* migrate customizable options to theme.js
*/
* Use this file when the style you need
* is applied in more than one element, or depends on it
* Use theme.js file to include colors that can be customized
*
* TODO:
* remove unnecessary styles properties (as items get refactored)
* migrate customizable options to theme.js
*/

const globalStyles = {
defaultFontFamily: `-apple-system, BlinkMacSystemFont, "Segoe UI"` +
Expand Down Expand Up @@ -214,7 +214,7 @@ const globalStyles = {
zindexWindowIsPreview: '1100',
zindexDownloadsBar: '1000',
zindexTabs: '1000',
zindexTabsAudioTopBorder: '10001',
zindexTabsAudioTopBorder: '1001',
zindexTabsThumbnail: '1100',
zindexTabsDragIndicator: '1100',
zindexNavigationBar: '2000',
Expand Down
4 changes: 3 additions & 1 deletion app/renderer/components/tabs/content/privateIcon.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,14 @@ module.exports = ReduxComponent.connect(PrivateIcon)

const styles = StyleSheet.create({
private__icon: {
zIndex: 99,
boxSizing: 'border-box',
WebkitMaskRepeat: 'no-repeat',
WebkitMaskPosition: 'center',
WebkitMaskImage: `url(${privateSvg})`,
WebkitMaskSize: globalStyles.spacing.sessionIconSize,
width: globalStyles.spacing.sessionIconSize,
height: globalStyles.spacing.sessionIconSize
height: globalStyles.spacing.sessionIconSize,
marginRight: globalStyles.spacing.defaultTabMargin
}
})
62 changes: 41 additions & 21 deletions app/renderer/components/tabs/tab.js
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ class Tab extends React.Component {
props.partOfFullPageSet = partOfFullPageSet
props.showAudioTopBorder = audioState.showAudioTopBorder(currentWindow, frameKey, isPinned)
props.centralizeTabIcons = tabUIState.centralizeTabIcons(currentWindow, frameKey, isPinned)
props.gradientColor = tabUIState.getTabEndIconBackgroundColor(currentWindow, frameKey)

// used in other functions
props.dragData = state.getIn(['dragData', 'type']) === dragTypes.TAB && state.get('dragData')
Expand All @@ -281,6 +282,13 @@ class Tab extends React.Component {
}
}
})
const perPageGradient = StyleSheet.create({
tab_gradient: {
'::before': {
background: this.props.gradientColor
}
}
})
return <div
data-tab-area
className={cx({
Expand All @@ -307,12 +315,13 @@ class Tab extends React.Component {
ref={(node) => { this.tabNode = node }}
className={css(
styles.tab,
!this.props.isPinnedTab && perPageGradient.tab_gradient,
// Windows specific style
isWindows && styles.tab_forWindows,
this.props.isPinnedTab && styles.tab_pinned,
this.props.isActive && styles.tab_active,
this.props.showAudioTopBorder && styles.tab_audioTopBorder,
this.props.isActive && this.props.themeColor && perPageStyles.tab_themeColor,
this.props.showAudioTopBorder && styles.tab_audioTopBorder,
// Private color should override themeColor
this.props.isPrivateTab && styles.tab_private,
this.props.isActive && this.props.isPrivateTab && styles.tab_active_private,
Expand Down Expand Up @@ -369,6 +378,16 @@ const styles = StyleSheet.create({

':hover': {
background: theme.tab.hover.background
},

// this enable us to have gradient text
'::before': {
content: '""',
position: 'absolute',
top: 0,
left: 0,
width: '-webkit-fill-available',
height: '-webkit-fill-available'
}
},

Expand All @@ -377,6 +396,12 @@ const styles = StyleSheet.create({
color: theme.tab.forWindows.color
},

tab_pinned: {
padding: 0,
width: '28px',
justifyContent: 'center'
},

tab_active: {
background: theme.tab.active.background,

Expand All @@ -385,20 +410,8 @@ const styles = StyleSheet.create({
}
},

// The sentinel is responsible to respond to tabs
// intersection state. This is an empty hidden element
// which `width` value shouldn't be changed unless the intersection
// point needs to be edited.
tab__sentinel: {
position: 'absolute',
left: 0,
height: '1px',
background: 'transparent',
width: globalStyles.spacing.sentinelSize
},

tab_audioTopBorder: {
'::before': {
'::after': {
content: `''`,
display: 'block',
position: 'absolute',
Expand All @@ -410,13 +423,26 @@ const styles = StyleSheet.create({
}
},

// The sentinel is responsible to respond to tabs
// intersection state. This is an empty hidden element
// which `width` value shouldn't be changed unless the intersection
// point needs to be edited.
tab__sentinel: {
position: 'absolute',
left: 0,
height: '1px',
background: 'transparent',
width: globalStyles.spacing.sentinelSize
},

tab__identity: {
justifyContent: 'flex-start',
alignItems: 'center',
overflow: 'hidden',
display: 'flex',
flex: '1',
minWidth: '0', // @see https://bugzilla.mozilla.org/show_bug.cgi?id=1108514#c5
marginLeft: globalStyles.spacing.defaultTabMargin
margin: `0 ${globalStyles.spacing.defaultTabMargin}`
},

tab__content_centered: {
Expand All @@ -426,12 +452,6 @@ const styles = StyleSheet.create({
margin: 0
},

tab_pinned: {
padding: 0,
width: '28px',
justifyContent: 'center'
},

tab_active_private: {
background: theme.tab.active.private.background,
color: theme.tab.active.private.color,
Expand Down
92 changes: 92 additions & 0 deletions test/unit/app/common/state/tabUIStateTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const assert = require('assert')
const Immutable = require('immutable')
const mockery = require('mockery')
const fakeElectron = require('../../../lib/fakeElectron')
const {theme} = require('../../../../../app/renderer/components/styles/theme')
const {intersection} = require('../../../../../app/renderer/components/styles/global')

const frameKey = 1
Expand Down Expand Up @@ -313,4 +314,95 @@ describe('tabUIState unit tests', function () {
assert.equal(result, true)
})
})

describe('getTabEndIconBackgroundColor', function () {
before(function () {
// just a helper for results
this.defaultResult = (bgColor, color1Size, color2Size) =>
`linear-gradient(to left, ${bgColor} ${color1Size}, transparent ${color2Size})`
})

describe('when tab is private', function () {
it('returns `tab.private.background` color if not active', function * () {
const state = defaultState
.set('activeFrameKey', 1337)
.mergeIn(['frames', index], {
themeColor: '#c0ff33',
isPrivate: true
})
const result = tabUIState.getTabEndIconBackgroundColor(state, frameKey)
const expected = this.defaultResult(theme.tab.private.background, '10px', '40px')
assert.equal(result, expected)
})

it('returns `tab.active.private.background` if tab is active', function * () {
const state = defaultState
.mergeIn(['frames', index], {
themeColor: '#c0ff33',
isPrivate: true
})
const result = tabUIState.getTabEndIconBackgroundColor(state, frameKey)
const expected = this.defaultResult(theme.tab.active.private.background, '10px', '40px')
assert.equal(result, expected)
})

it('retuns active private color if tab is being hovered', function * () {
const state = defaultState
.mergeIn(['frames', index], {
themeColor: '#c0ff33',
isPrivate: true
})
.setIn(['ui', 'tabs', 'hoverTabIndex'], index)
const result = tabUIState.getTabEndIconBackgroundColor(state, frameKey)
const expected = this.defaultResult(theme.tab.active.private.background, '10px', '40px')
assert.equal(result, expected)
})
})

describe('when tab is not private', function () {
it('returns the themeColor if tab is active', function * () {
const state = defaultState
.setIn(['frames', index, 'themeColor'], '#c0ff33')
const result = tabUIState.getTabEndIconBackgroundColor(state, frameKey)
const expected = this.defaultResult('#c0ff33', '0', '12px')
assert.equal(result, expected)
})
it('returns `theme.tab.background` if tab is not active', function * () {
const state = defaultState
.set('activeFrameKey', 1337)
.setIn(['frames', index, 'themeColor'], '#c0ff33')
const result = tabUIState.getTabEndIconBackgroundColor(state, frameKey)
const expected = this.defaultResult(theme.tab.background, '0', '12px')
assert.equal(result, expected)
})
})

describe('returns `linear gradient` size', function () {
it('at 10px/40px if tab is partitioned', function * () {
const state = defaultState
.mergeIn(['frames', index], {
partitionNumber: 1337,
themeColor: '#c0ff33'
})
const result = tabUIState.getTabEndIconBackgroundColor(state, frameKey)
const expected = this.defaultResult('#c0ff33', '10px', '40px')
assert.equal(result, expected)
})
it('at 10px/40px gradient size if tab has a visible close icon', function * () {
const state = defaultState
.setIn(['frames', index, 'themeColor'], '#c0ff33')
.setIn(['ui', 'tabs', 'hoverTabIndex'], index)
const result = tabUIState.getTabEndIconBackgroundColor(state, frameKey)
const expected = this.defaultResult('#c0ff33', '10px', '40px')
assert.equal(result, expected)
})
it('at 0/12px gradient size if is neither private, partition or has close icon visible', function * () {
const state = defaultState
.setIn(['frames', index, 'themeColor'], '#c0ff33')
const result = tabUIState.getTabEndIconBackgroundColor(state, frameKey)
const expected = this.defaultResult('#c0ff33', '0', '12px')
assert.equal(result, expected)
})
})
})
})

0 comments on commit a25ca8f

Please sign in to comment.