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

Commit 321281b

Browse files
committed
UI bug fixing
- tabs can now respond beautifully to intersections - Also BEMify tabs Auditors: @bsclifton, @luixxiul fix #6716 fix #7301 fix #7730 fix #7765 fix #7925 fix #10123 fix #10509 fix #10544 fix #10582 fix #10611 fix #10838
1 parent f17046d commit 321281b

File tree

5 files changed

+110
-89
lines changed

5 files changed

+110
-89
lines changed

app/renderer/components/styles/commonStyles.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ const styles = StyleSheet.create({
161161
notificationBar__notificationItem: {
162162
backgroundColor: globalStyles.color.notificationItemColor,
163163
boxSizing: 'border-box',
164-
borderTop: `1px solid ${globalStyles.color.tabsToolbarBorderColor}`,
164+
boxShadow: `0 -1px 0 ${globalStyles.color.tabsToolbarBorderColor}`,
165165
lineHeight: '24px',
166166
padding: '8px 20px'
167167
},

app/renderer/components/styles/global.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const globalStyles = {
2525
breakpointExtensionButtonPadding: '720px',
2626
breakpointSmallWin32: '650px',
2727
breakpointTinyWin32: '500px',
28-
breakpointNewPrivateTab: '890px'
28+
breakpointNewPrivateTab: '890px' // page's breakpoint for the private tab page
2929
},
3030
intersection: {
3131
// whereas 1 === 100%
@@ -162,7 +162,7 @@ const globalStyles = {
162162
aboutPageDetailsPageWidth: '704px',
163163
aboutPageSectionPadding: '24px',
164164
aboutPageSectionMargin: '10px',
165-
defaultTabPadding: '0 4px',
165+
defaultTabMargin: '6px',
166166
defaultIconPadding: '2px',
167167
iconSize: '16px',
168168
sessionIconSize: '15px',
@@ -214,6 +214,7 @@ const globalStyles = {
214214
zindexWindowIsPreview: '1100',
215215
zindexDownloadsBar: '1000',
216216
zindexTabs: '1000',
217+
zindexTabsAudioTopBorder: '10001',
217218
zindexTabsThumbnail: '1100',
218219
zindexTabsDragIndicator: '1100',
219220
zindexNavigationBar: '2000',

app/renderer/components/tabs/tab.js

+96-82
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
/* This Source Code Form is subject to the terms of the Mozilla Public
2-
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
3-
* You can obtain one at http://mozilla.org/MPL/2.0/. */
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
* You can obtain one at http://mozilla.org/MPL/2.0/. */
44

55
const React = require('react')
6-
const {StyleSheet, css} = require('aphrodite')
6+
const {StyleSheet, css} = require('aphrodite/no-important')
77
const Immutable = require('immutable')
88

99
// Components
@@ -23,7 +23,8 @@ const windowActions = require('../../../../js/actions/windowActions')
2323
// Store
2424
const windowStore = require('../../../../js/stores/windowStore')
2525

26-
// State
26+
// State helpers
27+
const privateState = require('../../../common/state/tabContentState/privateState')
2728
const audioState = require('../../../common/state/tabContentState/audioState')
2829
const tabUIState = require('../../../common/state/tabUIState')
2930
const tabState = require('../../../common/state/tabState')
@@ -33,6 +34,7 @@ const dragTypes = require('../../../../js/constants/dragTypes')
3334

3435
// Styles
3536
const globalStyles = require('../styles/global')
37+
const {theme} = require('../styles/theme')
3638

3739
// Utils
3840
const cx = require('../../../../js/lib/classSet')
@@ -119,10 +121,17 @@ class Tab extends React.Component {
119121
}
120122

121123
onDragStart (e) {
124+
// showing up the sentinel while dragging leads to show the shadow
125+
// of the next tab. See 10691#issuecomment-329854096
126+
// this is added back when dragEnd event happens
127+
this.tabSentinel.style.display = 'none'
128+
122129
dnd.onDragStart(dragTypes.TAB, this.frame, e)
123130
}
124131

125132
onDragEnd (e) {
133+
// re-enable the tabSentinel after drag ends
134+
this.tabSentinel.style.display = 'block'
126135
dnd.onDragEnd(dragTypes.TAB, this.frame, e)
127136
}
128137

@@ -186,9 +195,11 @@ class Tab extends React.Component {
186195
}
187196

188197
componentDidMount () {
189-
// do not observe pinned tabs
198+
// unobserve tabs that we don't need. This will
199+
// likely be made by onObserve method but added again as
200+
// just to double-check
190201
if (this.props.isPinned) {
191-
this.observer.unobserve(this.tabSentinel)
202+
this.observer && this.observer.unobserve(this.tabSentinel)
192203
}
193204
const threshold = Object.values(globalStyles.intersection)
194205
// At this moment Chrome can't handle unitless zeroes for rootMargin
@@ -200,20 +211,11 @@ class Tab extends React.Component {
200211
this.tabNode.addEventListener('auxclick', this.onAuxClick.bind(this))
201212
}
202213

203-
componentDidUpdate () {
204-
// if a tab was just pinned, unobserve its intersection
205-
// this gives us some more performance boost
206-
if (this.props.isPinnedTab) {
207-
this.observer.unobserve(this.tabSentinel)
208-
}
209-
}
210-
211214
componentWillUnmount () {
212215
this.observer.unobserve(this.tabSentinel)
213216
}
214217

215218
onObserve (entries) {
216-
// avoid observing pinned tabs
217219
if (this.props.isPinnedTab) {
218220
return
219221
}
@@ -234,27 +236,32 @@ class Tab extends React.Component {
234236
mergeProps (state, ownProps) {
235237
const currentWindow = state.get('currentWindow')
236238
const frame = frameStateUtil.getFrameByKey(currentWindow, ownProps.frameKey) || Immutable.Map()
239+
const frameKey = ownProps.frameKey
240+
const tabId = frame.get('tabId', tabState.TAB_ID_NONE)
241+
const isPinned = tabState.isTabPinned(state, tabId)
242+
const partOfFullPageSet = ownProps.partOfFullPageSet
243+
244+
// TODO: this should have its own method
237245
const notifications = state.get('notifications')
238246
const notificationOrigins = notifications ? notifications.map(bar => bar.get('frameOrigin')) : false
239247
const notificationBarActive = frame.get('location') && notificationOrigins &&
240248
notificationOrigins.includes(UrlUtil.getUrlOrigin(frame.get('location')))
241-
const tabId = frame.get('tabId', tabState.TAB_ID_NONE)
242249

243250
const props = {}
244-
// used in renderer
245-
props.frameKey = ownProps.frameKey
246-
props.isPrivateTab = frame.get('isPrivate')
251+
// TODO: this should have its own method
247252
props.notificationBarActive = notificationBarActive
248-
props.isActive = frameStateUtil.isFrameKeyActive(currentWindow, props.frameKey)
253+
props.frameKey = frameKey
254+
props.isPinnedTab = isPinned
255+
props.isPrivateTab = privateState.isPrivateTab(currentWindow, frameKey)
256+
props.isActive = frameStateUtil.isFrameKeyActive(currentWindow, frameKey)
249257
props.tabWidth = currentWindow.getIn(['ui', 'tabs', 'fixTabWidth'])
250-
props.isPinnedTab = tabState.isTabPinned(state, tabId)
251-
props.canPlayAudio = audioState.canPlayAudio(currentWindow, props.frameKey)
252-
props.themeColor = tabUIState.getThemeColor(currentWindow, props.frameKey)
258+
props.themeColor = tabUIState.getThemeColor(currentWindow, frameKey)
253259
props.title = frame.get('title')
254-
props.partOfFullPageSet = ownProps.partOfFullPageSet
260+
props.partOfFullPageSet = partOfFullPageSet
261+
props.showAudioTopBorder = audioState.showAudioTopBorder(currentWindow, frameKey, isPinned)
262+
props.centralizeTabIcons = tabUIState.centralizeTabIcons(currentWindow, frameKey, isPinned)
255263

256264
// used in other functions
257-
props.totalTabs = state.get('tabs').size
258265
props.dragData = state.getIn(['dragData', 'type']) === dragTypes.TAB && state.get('dragData')
259266
props.tabId = tabId
260267
props.previewMode = currentWindow.getIn(['ui', 'tabs', 'previewMode'])
@@ -265,7 +272,7 @@ class Tab extends React.Component {
265272
render () {
266273
// we don't want themeColor if tab is private
267274
const perPageStyles = !this.props.isPrivateTab && StyleSheet.create({
268-
themeColor: {
275+
tab_themeColor: {
269276
color: this.props.themeColor ? getTextColorForBackground(this.props.themeColor) : 'inherit',
270277
background: this.props.themeColor ? this.props.themeColor : 'inherit',
271278
':hover': {
@@ -301,13 +308,15 @@ class Tab extends React.Component {
301308
className={css(
302309
styles.tab,
303310
// Windows specific style
304-
isWindows && styles.tabForWindows,
305-
this.props.isPinnedTab && styles.isPinned,
306-
this.props.isActive && styles.active,
307-
this.props.isActive && this.props.themeColor && perPageStyles.themeColor,
311+
isWindows && styles.tab_forWindows,
312+
this.props.isPinnedTab && styles.tab_pinned,
313+
this.props.isActive && styles.tab_active,
314+
this.props.showAudioTopBorder && styles.tab_audioTopBorder,
315+
this.props.isActive && this.props.themeColor && perPageStyles.tab_themeColor,
308316
// Private color should override themeColor
309-
this.props.isPrivateTab && styles.private,
310-
this.props.isActive && this.props.isPrivateTab && styles.activePrivateTab
317+
this.props.isPrivateTab && styles.tab_private,
318+
this.props.isActive && this.props.isPrivateTab && styles.tab_active_private,
319+
this.props.centralizeTabIcons && styles.tab__content_centered
311320
)}
312321
data-test-id='tab'
313322
data-frame-key={this.props.frameKey}
@@ -323,7 +332,10 @@ class Tab extends React.Component {
323332
ref={(node) => { this.tabSentinel = node }}
324333
className={css(styles.tab__sentinel)}
325334
/>
326-
<div className={css(styles.tabId)}>
335+
<div className={css(
336+
styles.tab__identity,
337+
this.props.centralizeTabIcons && styles.tab__content_centered
338+
)}>
327339
<Favicon tabId={this.props.tabId} />
328340
<AudioTabIcon tabId={this.props.tabId} />
329341
<TabTitle tabId={this.props.tabId} />
@@ -337,34 +349,39 @@ class Tab extends React.Component {
337349
}
338350

339351
const styles = StyleSheet.create({
340-
// Windows specific style
341-
tabForWindows: {
342-
color: '#555'
343-
},
344-
345352
tab: {
346353
borderWidth: '0 1px 0 0',
347354
borderStyle: 'solid',
348355
borderColor: '#bbb',
349356
boxSizing: 'border-box',
350-
color: '#5a5a5a',
357+
color: theme.tab.color,
351358
display: 'flex',
352359
marginTop: '0',
353-
transition: `transform 200ms ease, ${globalStyles.transition.tabBackgroundTransition}`,
360+
transition: theme.tab.transition,
354361
left: '0',
355362
opacity: '1',
356-
width: '100%',
363+
height: '-webkit-fill-available',
364+
width: '-webkit-fill-available',
357365
alignItems: 'center',
358366
justifyContent: 'space-between',
359-
padding: globalStyles.spacing.defaultTabPadding,
367+
padding: 0,
360368
position: 'relative',
361369

362-
// globalStyles.spacing.tabHeight has been set to globalStyles.spacing.tabsToolbarHeight,
363-
// which is 1px extra due to the border-top of .tabsToolbar
364-
height: '-webkit-fill-available',
370+
':hover': {
371+
background: theme.tab.hover.background
372+
}
373+
},
374+
375+
// Windows specific style
376+
tab_forWindows: {
377+
color: theme.tab.forWindows.color
378+
},
379+
380+
tab_active: {
381+
background: theme.tab.active.background,
365382

366383
':hover': {
367-
background: 'linear-gradient(to bottom, rgba(255, 255, 255, 0.8), rgba(250, 250, 250, 0.4))'
384+
background: theme.tab.active.background
368385
}
369386
},
370387

@@ -380,59 +397,56 @@ const styles = StyleSheet.create({
380397
width: globalStyles.spacing.sentinelSize
381398
},
382399

383-
tabId: {
384-
justifyContent: 'center',
400+
tab_audioTopBorder: {
401+
'::before': {
402+
content: `''`,
403+
display: 'block',
404+
position: 'absolute',
405+
top: 0,
406+
left: 0,
407+
right: 0,
408+
height: '2px',
409+
background: 'lightskyblue'
410+
}
411+
},
412+
413+
tab__identity: {
414+
justifyContent: 'flex-start',
385415
alignItems: 'center',
386416
display: 'flex',
387417
flex: '1',
388-
389-
// @see https://bugzilla.mozilla.org/show_bug.cgi?id=1108514#c5
390-
minWidth: '0',
391-
392-
// prevent the icons wrapper from being the target of mouse events.
393-
pointerEvents: 'none'
418+
minWidth: '0', // @see https://bugzilla.mozilla.org/show_bug.cgi?id=1108514#c5
419+
marginLeft: globalStyles.spacing.defaultTabMargin
394420
},
395421

396-
isPinned: {
422+
tab__content_centered: {
423+
justifyContent: 'center',
424+
flex: 'auto',
397425
padding: 0,
398-
width: `calc(${globalStyles.spacing.tabsToolbarHeight} * 1.1)`,
399-
justifyContent: 'center'
426+
margin: 0
400427
},
401428

402-
active: {
403-
background: `rgba(255, 255, 255, 1.0)`,
404-
marginTop: '0',
405-
borderWidth: '0 1px 0 0',
406-
borderStyle: 'solid',
407-
borderColor: '#bbb',
408-
color: '#000',
409-
410-
':hover': {
411-
background: `linear-gradient(to bottom, #fff, ${globalStyles.color.chromePrimary})`
412-
}
429+
tab_pinned: {
430+
padding: 0,
431+
width: '28px',
432+
justifyContent: 'center'
413433
},
414434

415-
activePrivateTab: {
416-
background: globalStyles.color.privateTabBackgroundActive,
435+
tab_active_private: {
436+
background: theme.tab.active.private.background,
437+
color: theme.tab.active.private.color,
417438

418439
':hover': {
419-
background: globalStyles.color.privateTabBackgroundActive
440+
background: theme.tab.active.private.background
420441
}
421442
},
422443

423-
private: {
424-
background: 'rgba(75, 60, 110, 0.2)',
444+
tab_private: {
445+
background: theme.tab.private.background,
425446

426447
':hover': {
427-
background: globalStyles.color.privateTabBackgroundActive
428-
}
429-
},
430-
431-
dragging: {
432-
':hover': {
433-
closeTab: {
434-
opacity: '0'
435-
}
448+
color: theme.tab.active.private.color,
449+
background: theme.tab.active.private.background
436450
}
437451
}
438452
})

less/tabs.less

+9-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
flex: 1;
1111
overflow: auto;
1212
padding: 0;
13-
height: @tabsToolbarHeight;
13+
height: -webkit-fill-available;
1414
position: relative;
1515
white-space: nowrap;
1616
z-index: @zindexTabs;
@@ -59,6 +59,7 @@
5959
position: relative;
6060
vertical-align: top;
6161
overflow: hidden;
62+
height: -webkit-fill-available;
6263
// There's a special case that tabs should span the full width
6364
// if there are a full set of them.
6465
&:not(.partOfFullPageSet) {
@@ -123,14 +124,17 @@
123124
box-sizing: border-box;
124125
background: @tabsBackground;
125126
display: flex;
126-
height: @tabsToolbarHeight;
127+
// This element is set as border-box so it does not
128+
// take into account the borders as width gutter, so we
129+
// increase its size by 1px to include the top border
130+
height: calc(~'@{tabsToolbarHeight} + 1px');
127131
border-top: 1px solid @tabsToolbarBorderColor;
128132
user-select: none;
129133
}
130134

131135
.tabsToolbarButtons {
132136
box-sizing: border-box;
133-
height: @tabHeight;
137+
height: -webkit-fill-available;
134138
padding-right: 5px;
135139

136140
.browserButton {
@@ -222,6 +226,8 @@
222226
}
223227

224228
.pinnedTabs {
229+
height: -webkit-fill-available;
230+
box-sizing: border-box;
225231
margin-left: 0;
226232
margin-top: 0;
227233
background: @tabsBackgroundInactive;

0 commit comments

Comments
 (0)