Skip to content

Commit 50947a8

Browse files
authored
Merge pull request #617 from nextcloud/feat/new-design
feat: new title bar design
2 parents b38c82b + fd1c9b7 commit 50947a8

File tree

11 files changed

+120
-109
lines changed

11 files changed

+120
-109
lines changed

src/authentication/authentication.window.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,17 @@ function createAuthenticationWindow() {
4444
preload: AUTHENTICATION_WINDOW_PRELOAD_WEBPACK_ENTRY,
4545
},
4646
icon: getBrowserWindowIcon(),
47+
titleBarStyle: 'hidden',
48+
titleBarOverlay: {
49+
color: '#00669E00', // Transparent
50+
symbolColor: '#FFFFFF', // White
51+
height: 50,
52+
},
53+
// Position of the top left corner of the traffic light on Mac
54+
trafficLightPosition: {
55+
x: 12, // Same as on Talk Window
56+
y: (50 - 16) / 2, // 16 is the default traffic light button diameter
57+
},
4758
})
4859

4960
// TODO: return this on release

src/authentication/renderer/AuthenticationApp.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ export default {
219219
flex-direction: column;
220220
align-items: center;
221221
user-select: none;
222+
app-region: drag;
222223
}
223224
224225
.spacer {
@@ -246,6 +247,7 @@ export default {
246247
border-radius: var(--border-radius-large);
247248
box-shadow: 0 0 10px var(--color-box-shadow);
248249
width: 300px;
250+
app-region: no-drag;
249251
}
250252
251253
.login-box__header {

src/talk/renderer/DesktopHeader.vue

Lines changed: 58 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -20,74 +20,59 @@
2020
-->
2121

2222
<template>
23-
<header class="header">
24-
<!-- Nextcloud Apps use #header selector to get its height -->
25-
<!-- This is invisible stub with the same height -->
26-
<div id="header" class="header-stub" />
27-
28-
<a class="header__root-link" @click.prevent="pushToRoot">
29-
<img class="header__logo" src="~@talk/img/app.svg" alt="Talk Logo">
30-
</a>
31-
32-
<div>
33-
<span class="header__title">Nextcloud Talk</span>
34-
<span class="header__preview-badge">Preview</span>
35-
</div>
36-
37-
<div class="spacer" />
38-
39-
<div class="header__item">
40-
<NcButton :aria-label="t('talk_desktop', 'Search')"
41-
type="tertiary-no-background"
42-
class="header__button"
43-
@click="showNotSupportedAlert('Search')">
44-
<template #icon>
45-
<MdiMagnify />
46-
</template>
47-
</NcButton>
48-
</div>
49-
50-
<div class="header__item">
51-
<NcButton :aria-label="t('talk_desktop', 'Notifications')"
52-
type="tertiary-no-background"
53-
class="header__button"
54-
@click="showNotSupportedAlert('Notifications')">
55-
<template #icon>
56-
<MdiBell />
57-
</template>
58-
</NcButton>
59-
</div>
60-
61-
<div class="header__item">
62-
<UserMenu :user="$options.userMetadata" @logout="logout" />
23+
<header id="header" class="header">
24+
<div class="header__inner">
25+
<div v-if="!OS.isMac"
26+
class="header__title-wrapper"
27+
role="button"
28+
tabindex="0"
29+
@click="pushToRoot">
30+
<span class="header__title">Nextcloud Talk</span>
31+
<span class="header__preview-badge">Preview</span>
32+
</div>
33+
34+
<div class="spacer" />
35+
36+
<div class="header__item">
37+
<UserMenu :user="user" @logout="logout" />
38+
</div>
6339
</div>
6440
</header>
6541
</template>
6642

6743
<script>
68-
import MdiBell from 'vue-material-design-icons/Bell.vue'
69-
import MdiMagnify from 'vue-material-design-icons/Magnify.vue'
70-
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
7144
import UserMenu from './components/UserMenu.vue'
7245
import { appData } from '../../app/AppData.js'
7346
7447
export default {
7548
name: 'DesktopHeader',
7649
77-
userMetadata: appData.userMetadata,
78-
7950
components: {
80-
MdiBell,
81-
MdiMagnify,
82-
NcButton,
8351
UserMenu,
8452
},
8553
86-
inject: ['router'],
54+
setup() {
55+
return {
56+
user: appData.userMetadata,
57+
OS: window.OS,
58+
}
59+
},
60+
61+
mounted() {
62+
window.addEventListener('keydown', (event) => {
63+
if (event.key === 'Escape' && document.activeElement === document.body) {
64+
this.pushToRoot()
65+
}
66+
}, { capture: true })
67+
},
8768
8869
methods: {
70+
getTalkRouter() {
71+
return window.OCA.Talk.instance.$router
72+
},
73+
8974
pushToRoot() {
90-
this.router.push({ name: 'root' }).catch(() => {})
75+
this.getTalkRouter().push({ name: 'root' }).catch(() => {})
9176
},
9277
9378
logout() {
@@ -102,25 +87,22 @@ export default {
10287
</script>
10388

10489
<style scoped>
105-
.header__root-link {
106-
cursor: pointer;
107-
}
108-
109-
.header-stub {
110-
height: 100%;
111-
position: absolute;
112-
z-index: -1;
113-
}
114-
11590
.header {
11691
height: 50px;
11792
box-sizing: border-box;
11893
margin-bottom: -50px;
11994
color: #FFF;
95+
user-select: none;
96+
}
97+
98+
.header__inner {
12099
padding: 0 calc(var(--body-container-margin) + 4px) 0 var(--body-container-margin);
121100
display: flex;
122101
align-items: center;
123-
user-select: none;
102+
height: 100%;
103+
/* Save space for native title bar buttons */
104+
margin-inline-start: env(titlebar-area-x, 0);
105+
width: env(titlebar-area-width, 100%);
124106
}
125107
126108
.header__item {
@@ -129,35 +111,31 @@ export default {
129111
justify-content: center;
130112
}
131113
132-
.header__logo {
133-
height: 32px;
134-
margin: 0 14px 0 20px;
114+
.header__title-wrapper {
115+
display: flex;
116+
align-items: center;
117+
height: 100%;
118+
margin-inline-start: calc(var(--default-grid-baseline) * 3);
119+
position: relative;
120+
121+
&:focus-visible::after {
122+
bottom: 0;
123+
}
135124
}
136125
137126
.header__title {
138-
font-size: 20px;
127+
font-size: 18px;
139128
font-weight: bold;
140129
}
141130
142131
.header__preview-badge {
143-
margin-left: var(--default-grid-baseline);
144-
}
145-
146-
.header__button {
147-
opacity: .85;
148-
/* We have to use !important here because NcButton already has !important */
149-
color: inherit !important;
150-
transition: opacity ease var(--animation-quick) !important;
151-
}
152-
153-
.header__button:hover,
154-
.header__button:active,
155-
.header__button:focus-visible {
156-
color: inherit !important;
157-
opacity: 1;
132+
margin-inline-start: var(--default-grid-baseline);
158133
}
159134
160135
.spacer {
161136
flex: 1 0 auto;
137+
height: 100%;
138+
/* Allow to drag the window using header */
139+
app-region: drag;
162140
}
163141
</style>

src/talk/renderer/Viewer/ViewerApp.vue

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
id="viewer"
2525
:show.sync="isOpen"
2626
class="viewer-modal"
27+
:class="{ 'viewer-modal--open': isOpen }"
2728
:name="file.basename"
2829
size="full"
2930
:close-button-contained="false"
@@ -97,7 +98,21 @@ export default {
9798
}
9899
</script>
99100
101+
<style>
102+
.header {
103+
transition: background-color 250ms; /* Same as NcModal transition timing */
104+
}
105+
106+
body:has(.viewer-modal--open) .header {
107+
background: black;
108+
}
109+
</style>
110+
100111
<style scoped>
112+
.viewer-modal {
113+
top: 50px !important;
114+
}
115+
101116
.viewer-modal :deep(.modal-container) {
102117
background: none !important;
103118
}

src/talk/renderer/assets/overrides.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@
2828
}
2929

3030
#content-vue {
31-
border-radius: var(--body-container-radius) var(--body-container-radius) 0 0 !important;
31+
border-radius: 0 !important;
3232
}

src/talk/renderer/components/UserMenu.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ export default {
202202
.user-menu__trigger {
203203
display: flex;
204204
align-items: center;
205+
margin: 0 !important; /* Re-define server default styles */
205206
}
206207
207208
.user-menu__avatar {

src/talk/renderer/desktop.app.js

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,8 @@ Vue.prototype.t = translate
2727
Vue.prototype.n = translatePlural
2828

2929
/**
30-
* @param {import('VueRouter').Router} router - Vue Router instance
3130
* @return {import('vue').ComponentPublicInstance}
3231
*/
33-
export function createDesktopApp(router) {
34-
// eslint-disable-next-line vue/require-name-property
35-
return new Vue({
36-
provide() {
37-
return {
38-
router,
39-
}
40-
},
41-
42-
render: (h) => h(DesktopHeader),
43-
}).$mount('#desktop-header')
32+
export function createDesktopApp() {
33+
return new Vue(DesktopHeader).$mount('#desktop-header')
4434
}

src/talk/renderer/init.js

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,9 @@ import { appData } from '../../app/AppData.js'
2424
import { getCapabilities } from '../../shared/ocs.service.js'
2525

2626
/**
27-
* Initialize Talk application: styles, localization etc.
28-
*
29-
* @return {Promise<object>}
27+
* @return {Promise<void>}
3028
*/
31-
export async function init() {
29+
export async function initServerStyles() {
3230
// Load application styles from server
3331
await Promise.all([
3432
loadServerCss('/apps/theming/css/default.css'),
@@ -53,16 +51,14 @@ export async function init() {
5351
window.TALK_DESKTOP.quit()
5452
}
5553
})
54+
}
5655

56+
/**
57+
* @return {Promise<void>}
58+
*/
59+
export async function initLocalStyles() {
5760
// Load styles overrides
5861
await import('./assets/overrides.css')
59-
60-
// Get Talk's modules
61-
const { default: router } = await import('@talk/src/router/router.js')
62-
63-
return {
64-
router,
65-
}
6662
}
6763

6864
/**

src/talk/renderer/talk.main.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ import '@talk/css/icons.css'
2323
import './assets/styles.css'
2424

2525
import 'regenerator-runtime' // TODO: Why isn't it added on bundling
26-
import { init, initTalkHashIntegration } from './init.js'
26+
import { initLocalStyles, initServerStyles, initTalkHashIntegration } from './init.js'
2727
import { setupWebPage } from '../../shared/setupWebPage.js'
2828
import { createViewer } from './Viewer/Viewer.js'
29+
import { createDesktopApp } from './desktop.app.js'
2930

3031
// Initially open the welcome page, if not specified
3132
if (!window.location.hash) {
@@ -34,10 +35,10 @@ if (!window.location.hash) {
3435

3536
await setupWebPage()
3637

37-
const { router } = await init()
38+
await initServerStyles()
39+
await initLocalStyles()
3840

39-
const { createDesktopApp } = await import('./desktop.app.js')
40-
createDesktopApp(router)
41+
createDesktopApp()
4142

4243
window.OCA.Viewer = createViewer()
4344

src/talk/talk.window.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,23 @@ function createTalkWindow() {
3434
const talkWindowOptions = {
3535
minWidth: 600,
3636
minHeight: 400,
37-
backgroundColor: '#171717',
37+
backgroundColor: '#00669E',
3838
autoHideMenuBar: true,
3939
webPreferences: {
4040
preload: TALK_WINDOW_PRELOAD_WEBPACK_ENTRY,
4141
},
4242
icon: getBrowserWindowIcon(),
43+
titleBarStyle: 'hidden',
44+
titleBarOverlay: {
45+
color: '#00669E00', // Transparent
46+
symbolColor: '#FFFFFF', // White
47+
height: 50,
48+
},
49+
// Position of the top left corner of the traffic light on Mac
50+
trafficLightPosition: {
51+
x: 12, // In line with SearchBox
52+
y: (50 - 16) / 2, // 16 is the default traffic light button diameter
53+
},
4354
}
4455

4556
const window = new BrowserWindow({

0 commit comments

Comments
 (0)