diff --git a/app/renderer/components/frame/frame.js b/app/renderer/components/frame/frame.js
index e190d58aa44..63bbcc7859f 100644
--- a/app/renderer/components/frame/frame.js
+++ b/app/renderer/components/frame/frame.js
@@ -859,12 +859,15 @@ class Frame extends React.Component {
const props = {}
// used in renderer
+ props.transitionState = ownProps.transitionState
props.partition = frameStateUtil.getPartition(frame)
props.isFullScreen = frame.get('isFullScreen')
props.isPreview = frame.get('key') === currentWindow.get('previewFrameKey')
props.isActive = frameStateUtil.isFrameKeyActive(currentWindow, frame.get('key'))
props.showFullScreenWarning = frame.get('showFullScreenWarning')
props.location = location
+ props.isDefaultNewTabLocation = location === 'about:newtab'
+ props.isBlankLocation = location === 'about:blank'
props.tabId = tabId
props.showMessageBox = tabMessageBoxState.hasMessageBoxDetail(state, tabId)
props.isFocused = isFocused(state)
@@ -906,7 +909,16 @@ class Frame extends React.Component {
return props
}
+ getTransitionStateClassName (stateName) {
+ if (!stateName) {
+ return null
+ } else {
+ return `is${stateName[0].toUpperCase()}${stateName.slice(1)}`
+ }
+ }
+
render () {
+ const transitionClassName = this.getTransitionStateClassName(this.props.transitionState)
return
{
this.props.isFullScreen && this.props.showFullScreenWarning
diff --git a/app/renderer/components/main/main.js b/app/renderer/components/main/main.js
index 1a3e65793a8..aeefb98da7c 100644
--- a/app/renderer/components/main/main.js
+++ b/app/renderer/components/main/main.js
@@ -17,6 +17,7 @@ const contextMenus = require('../../../../js/contextMenus')
const {getSetting} = require('../../../../js/settings')
// Components
+const { Transition, TransitionGroup } = require('react-transition-group')
const Navigator = require('../navigation/navigator')
const Frame = require('../frame/frame')
const TabPages = require('../tabs/tabPages')
@@ -733,15 +734,27 @@ class Main extends React.Component {
}
-
+
{
this.props.sortedFrames.map((frameKey) =>
- )
+ // after how long (ms)
+ // should the state 'entering' switch to 'entered'
+ // and also how long should state switch from 'exiting'
+ // to the component actually being removed
+ timeout={150}>
+ {
+ (transitionState) =>
+
+ }
+
+ )
}
-
+
{
this.props.showDownloadBar
diff --git a/app/renderer/components/styles/theme.js b/app/renderer/components/styles/theme.js
index 245d4065285..d2e8ce41826 100644
--- a/app/renderer/components/styles/theme.js
+++ b/app/renderer/components/styles/theme.js
@@ -163,5 +163,12 @@
color: 'inherit'
}
}
+ },
+
+ frame: {
+ defaultBackground: '#fff',
+ newTabBackground: '#222',
+ privateTabBackground: globalStyles.color.privateTabBackgroundActive,
+ privateTabBackground2: '#000'
}
}
diff --git a/js/about/newprivatetab.js b/js/about/newprivatetab.js
index e4d752de2be..0366dcb49df 100644
--- a/js/about/newprivatetab.js
+++ b/js/about/newprivatetab.js
@@ -5,6 +5,7 @@
const React = require('react')
const {StyleSheet, css} = require('aphrodite')
const globalStyles = require('../../app/renderer/components/styles/global')
+const { theme } = require('../../app/renderer/components/styles/theme')
const Stats = require('./newTabComponents/stats')
const Clock = require('./newTabComponents/clock')
const privateTabIcon = require('../../app/extensions/brave/img/newtab/private_tab_pagearea_icon.svg')
@@ -38,9 +39,24 @@ class NewPrivateTab extends React.Component {
const atBreakpoint = `@media screen and (max-width: ${globalStyles.breakpoint.breakpointNewPrivateTab})`
const styles = StyleSheet.create({
newPrivateTab: {
+ // animate gradient from the default new tab background,
+ // to the private new tab background
background: `linear-gradient(
- ${globalStyles.color.privateTabBackgroundActive},
- ${globalStyles.color.black100})`,
+ ${theme.frame.privateTabBackground},
+ ${theme.frame.privateTabBackground2}
+ )`,
+ // fade in from the new tab background color
+ animationName: {
+ '0%': {
+ opacity: '0'
+ },
+ '100%': {
+ opacity: '1'
+ }
+ },
+ backgroundAttachment: 'fixed',
+ animationDuration: `0.5s`,
+ animationTiming: 'ease-out',
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-start',
diff --git a/less/window.less b/less/window.less
index e943183db1f..12ec648d38a 100644
--- a/less/window.less
+++ b/less/window.less
@@ -62,16 +62,68 @@ html,
.frameWrapper {
height: 100%;
width: 100%;
- z-index: @zindexWindow;
+
position: absolute;
top: 0;
left: 0;
// Needed to be able to click and drag to select content in pages.
user-select: none;
+ // default frame background
+ // TODO: use theme.frame.defaultBackground
+ --frame-bg: #fff;
+ // custom frame background(s)
+ &.isDefaultNewTabLocation {
+ // matches tab dashboard background
+ // will also show when about:newtab === about:blank or is Private Tab
+ // TODO: use theme.frame.newTabBackground
+ --frame-bg: #222;
+ }
+ // Webviews can cause flickers w/ Chrome v49 if left visible
+ // in the background. This also has a major benefit for background
+ // tabs that have video and animations in them.
+ visibility: hidden;
+ // delay frames getting hidden when new tabs show up
+ // in order to avoid showing 0 frames and just the window
+ // background
+ // whilst this does also affect visibility when switching tabs,
+ // z-index ensures the delayed-hidden tab is not visible
+ // Note that this value can be as large as we want, it does not
+ // need to match the timeout specified in the frame's element
+ // (in renderer main.js). However, there is no reason to set it higher than that.
+ transition: visibility 0s linear 150ms;
+ // 1000
+ z-index: @zindexWindow;
+ &:not(.isActive) {
+ // 900
+ z-index: @zindexWindowNotActive;
+ }
+ &.isPreview {
+ background: #222;
+ // 1100
+ z-index: @zindexWindowIsPreview;
+ }
+ // show frame when active or preview
+ &.isActive,
+ &.isPreview,
+ // keep window contents around when exiting, to allow
+ // time for next active frame to be shown
+ &.isExiting {
+ visibility: visible;
+ // show instantly
+ transition-delay: 0s;
+ }
+ // hide frame whilst it's figuring out which location to be
+ // note: that isEntering is timed-out at a value set in renderer main.js
+ // but isBlankLocation will change at the exact moment that the frame
+ // has an actual location
+ &.isEntering.isBlankLocation {
+ visibility: hidden;
+ transition-delay: 0s;
+ }
webview {
- background-color: #fff;
+ background-color: var(--frame-bg);
border: 0;
height: 100%;
outline: none;
@@ -89,21 +141,6 @@ html,
}
}
- &:not(.isActive) {
- z-index: @zindexWindowNotActive;
-
- &.isPreview {
- background: gray;
- z-index: @zindexWindowIsPreview;
- }
-
- // Webviews can cause flickers w/ Chrome v49 if left visible
- // in the background. This also has a major benefit for background
- // tabs that have video and animations in them.
- &:not(.isPreview) {
- visibility: hidden;
- }
- }
}
.hrefPreview {
diff --git a/package-lock.json b/package-lock.json
index 72b2d0417c1..61bcb7c22b1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2702,6 +2702,11 @@
"integrity": "sha1-CdekApCKpw39vq1T5YU/x50+8hw=",
"dev": true
},
+ "chain-function": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/chain-function/-/chain-function-1.0.0.tgz",
+ "integrity": "sha1-DUqzfn4Y6tC9xHuSB2QRjOWHM9w="
+ },
"chainsaw": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz",
@@ -4771,6 +4776,11 @@
}
}
},
+ "dom-helpers": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.2.1.tgz",
+ "integrity": "sha1-MgPgf+0he9H0JLAZc1WC/Deyglo="
+ },
"dom-serializer": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
@@ -16617,6 +16627,19 @@
"object-assign": "4.1.1"
}
},
+ "react-transition-group": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.2.1.tgz",
+ "integrity": "sha512-q54UBM22bs/CekG8r3+vi9TugSqh0t7qcEVycaRc9M0p0aCEu+h6rp/RFiW7fHfgd1IKpd9oILFTl5QK+FpiPA==",
+ "requires": {
+ "chain-function": "1.0.0",
+ "classnames": "2.2.5",
+ "dom-helpers": "3.2.1",
+ "loose-envify": "1.3.1",
+ "prop-types": "15.6.0",
+ "warning": "3.0.0"
+ }
+ },
"read-all-stream": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz",
@@ -19954,6 +19977,14 @@
"integrity": "sha1-oW0CXrkxvQO1LzCMrtD0D86+lTI=",
"dev": true
},
+ "warning": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz",
+ "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=",
+ "requires": {
+ "loose-envify": "1.3.1"
+ }
+ },
"watchpack": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz",
diff --git a/package.json b/package.json
index e09eefb2113..bd8ff389691 100644
--- a/package.json
+++ b/package.json
@@ -120,6 +120,7 @@
"react-dnd-html5-backend": "^2.1.2",
"react-dom": "^15.5.4",
"react-select": "^0.9.1",
+ "react-transition-group": "^2.2.1",
"snazzy": "^7.0.0",
"string.prototype.endswith": "^0.2.0",
"string.prototype.startswith": "^0.2.0",