Skip to content

Commit f1cc819

Browse files
authored
Merge pull request #46880 from nextcloud/fix/account-menu
fix: Make account menu follow the design (use nextcloud-vue components)
2 parents 119543e + f7dd3c5 commit f1cc819

18 files changed

Lines changed: 359 additions & 402 deletions

apps/user_status/src/UserStatus.vue

Lines changed: 26 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,42 @@
44
-->
55

66
<template>
7-
<component :is="inline ? 'div' : 'li'">
8-
<!-- User Status = Status modal toggle -->
9-
<button v-if="!inline"
7+
<Fragment>
8+
<NcListItem v-if="!inline"
109
class="user-status-menu-item"
11-
@click.stop="openModal">
12-
<NcUserStatusIcon class="user-status-icon"
13-
:status="statusType"
14-
aria-hidden="true" />
15-
{{ visibleMessage }}
16-
</button>
17-
18-
<!-- Dashboard Status -->
19-
<NcButton v-else
10+
compact
11+
:name="visibleMessage"
2012
@click.stop="openModal">
2113
<template #icon>
2214
<NcUserStatusIcon class="user-status-icon"
2315
:status="statusType"
2416
aria-hidden="true" />
2517
</template>
26-
{{ visibleMessage }}
27-
</NcButton>
28-
18+
</NcListItem>
19+
20+
<div v-else>
21+
<!-- Dashboard Status -->
22+
<NcButton @click.stop="openModal">
23+
<template #icon>
24+
<NcUserStatusIcon class="user-status-icon"
25+
:status="statusType"
26+
aria-hidden="true" />
27+
</template>
28+
{{ visibleMessage }}
29+
</NcButton>
30+
</div>
2931
<!-- Status management modal -->
3032
<SetStatusModal v-if="isModalOpen"
3133
:inline="inline"
3234
@close="closeModal" />
33-
</component>
35+
</Fragment>
3436
</template>
3537

3638
<script>
3739
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
40+
import { Fragment } from 'vue-frag'
3841
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
42+
import NcListItem from '@nextcloud/vue/dist/Components/NcListItem.js'
3943
import NcUserStatusIcon from '@nextcloud/vue/dist/Components/NcUserStatusIcon.js'
4044
import debounce from 'debounce'
4145
@@ -46,7 +50,9 @@ export default {
4650
name: 'UserStatus',
4751
4852
components: {
53+
Fragment,
4954
NcButton,
55+
NcListItem,
5056
NcUserStatusIcon,
5157
SetStatusModal: () => import(/* webpackChunkName: 'user-status-modal' */'./components/SetStatusModal.vue'),
5258
},
@@ -166,40 +172,12 @@ export default {
166172
</script>
167173
168174
<style lang="scss" scoped>
169-
.user-status-menu-item {
170-
// Ensure the maxcontrast color is set for the background
171-
--color-text-maxcontrast: var(--color-text-maxcontrast-background-blur, var(--color-main-text));
172-
173-
width: auto;
174-
min-width: 44px;
175-
height: 44px;
176-
margin: 0;
177-
border: 0;
178-
border-radius: var(--border-radius-pill);
179-
background-color: var(--color-main-background-blur);
180-
font-size: inherit;
181-
font-weight: normal;
182-
183-
-webkit-backdrop-filter: var(--background-blur);
184-
backdrop-filter: var(--background-blur);
185-
186-
&:active,
187-
&:hover,
188-
&:focus-visible {
189-
background-color: var(--color-background-hover);
190-
}
191-
&:focus-visible {
192-
box-shadow: 0 0 0 4px var(--color-main-background) !important;
193-
outline: 2px solid var(--color-main-text) !important;
194-
}
195-
}
196-
197175
.user-status-icon {
198-
width: 16px;
199-
height: 16px;
200-
margin-right: 10px;
176+
width: 20px;
177+
height: 20px;
178+
margin: calc((var(--default-clickable-area) - 20px) / 2); // 20px icon size
201179
opacity: 1 !important;
202-
background-size: 16px;
180+
background-size: 20px;
203181
vertical-align: middle !important;
204182
}
205183
</style>

core/src/components/UserMenu/UserMenuEntry.vue renamed to core/src/components/AccountMenu/AccountMenuEntry.vue

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,39 @@
44
-->
55

66
<template>
7-
<li :id="id"
8-
class="menu-entry">
9-
<a v-if="href"
10-
:href="href"
11-
:class="{ active }"
12-
@click.exact="handleClick">
13-
<NcLoadingIcon v-if="loading"
14-
class="menu-entry__loading-icon"
15-
:size="18" />
16-
<img v-else :src="cachedIcon" alt="">
17-
{{ name }}
18-
</a>
19-
<button v-else>
20-
<img :src="cachedIcon" alt="">
21-
{{ name }}
22-
</button>
23-
</li>
7+
<NcListItem :id="href ? undefined : id"
8+
:anchor-id="id"
9+
:active="active"
10+
class="account-menu-entry"
11+
compact
12+
:href="href"
13+
:name="name"
14+
target="_self">
15+
<template #icon>
16+
<img class="account-menu-entry__icon"
17+
:class="{ 'account-menu-entry__icon--active': active }"
18+
:src="iconSource"
19+
alt="">
20+
</template>
21+
<template v-if="loading" #indicator>
22+
<NcLoadingIcon />
23+
</template>
24+
</NcListItem>
2425
</template>
2526

2627
<script>
2728
import { loadState } from '@nextcloud/initial-state'
2829
30+
import NcListItem from '@nextcloud/vue/dist/Components/NcListItem.js'
2931
import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
3032
3133
const versionHash = loadState('core', 'versionHash', '')
3234
3335
export default {
34-
name: 'UserMenuEntry',
36+
name: 'AccountMenuEntry',
3537
3638
components: {
39+
NcListItem,
3740
NcLoadingIcon,
3841
},
3942
@@ -67,7 +70,7 @@ export default {
6770
},
6871
6972
computed: {
70-
cachedIcon() {
73+
iconSource() {
7174
return `${this.icon}?v=${versionHash}`
7275
},
7376
},
@@ -81,9 +84,20 @@ export default {
8184
</script>
8285

8386
<style lang="scss" scoped>
84-
.menu-entry {
85-
&__loading-icon {
86-
margin-right: 8px;
87+
.account-menu-entry {
88+
&__icon {
89+
height: 16px;
90+
width: 16px;
91+
margin: calc((var(--default-clickable-area) - 16px) / 2); // 16px icon size
92+
filter: var(--background-invert-if-dark);
93+
94+
&--active {
95+
filter: var(--primary-invert-if-dark);
96+
}
97+
}
98+
99+
:deep(.list-item-content__main) {
100+
width: fit-content;
87101
}
88102
}
89103
</style>

core/src/components/UserMenu/ProfileUserMenuEntry.vue renamed to core/src/components/AccountMenu/AccountMenuProfileEntry.vue

Lines changed: 31 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,38 @@
44
-->
55

66
<template>
7-
<li :id="id"
8-
class="menu-entry">
9-
<component :is="profileEnabled ? 'a' : 'span'"
10-
class="menu-entry__wrapper"
11-
:class="{
12-
active,
13-
'menu-entry__wrapper--link': profileEnabled,
14-
}"
15-
:href="profileEnabled ? href : undefined"
16-
@click.exact="handleClick">
17-
<span class="menu-entry__content">
18-
<span class="menu-entry__displayname">{{ displayName }}</span>
19-
<NcLoadingIcon v-if="loading" :size="18" />
20-
</span>
21-
<span v-if="profileEnabled">{{ name }}</span>
22-
</component>
23-
</li>
7+
<NcListItem :id="profileEnabled ? undefined : id"
8+
:anchor-id="id"
9+
:active="active"
10+
compact
11+
:href="profileEnabled ? href : undefined"
12+
:name="displayName"
13+
target="_self">
14+
<template v-if="profileEnabled" #subname>
15+
{{ name }}
16+
</template>
17+
<template v-if="loading" #indicator>
18+
<NcLoadingIcon />
19+
</template>
20+
</NcListItem>
2421
</template>
2522

26-
<script>
23+
<script lang="ts">
2724
import { loadState } from '@nextcloud/initial-state'
2825
import { getCurrentUser } from '@nextcloud/auth'
2926
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
27+
import { defineComponent } from 'vue'
3028
29+
import NcListItem from '@nextcloud/vue/dist/Components/NcListItem.js'
3130
import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
3231
33-
const { profileEnabled } = loadState('user_status', 'profileEnabled', false)
32+
const { profileEnabled } = loadState('user_status', 'profileEnabled', { profileEnabled: false })
3433
35-
export default {
36-
name: 'ProfileUserMenuEntry',
34+
export default defineComponent({
35+
name: 'AccountMenuProfileEntry',
3736
3837
components: {
38+
NcListItem,
3939
NcLoadingIcon,
4040
},
4141
@@ -58,10 +58,15 @@ export default {
5858
},
5959
},
6060
61-
data() {
61+
setup() {
6262
return {
6363
profileEnabled,
64-
displayName: getCurrentUser().displayName,
64+
displayName: getCurrentUser()!.displayName,
65+
}
66+
},
67+
68+
data() {
69+
return {
6570
loading: false,
6671
}
6772
},
@@ -83,41 +88,13 @@ export default {
8388
}
8489
},
8590
86-
handleProfileEnabledUpdate(profileEnabled) {
91+
handleProfileEnabledUpdate(profileEnabled: boolean) {
8792
this.profileEnabled = profileEnabled
8893
},
8994
90-
handleDisplayNameUpdate(displayName) {
95+
handleDisplayNameUpdate(displayName: string) {
9196
this.displayName = displayName
9297
},
9398
},
94-
}
99+
})
95100
</script>
96-
97-
<style lang="scss" scoped>
98-
.menu-entry {
99-
&__wrapper {
100-
box-sizing: border-box;
101-
display: inline-flex;
102-
flex-direction: column;
103-
align-items: flex-start !important;
104-
padding: 10px 12px 5px 12px !important;
105-
height: var(--header-menu-item-height);
106-
color: var(--color-text-maxcontrast);
107-
108-
&--link {
109-
height: calc(var(--header-menu-item-height) * 1.5) !important;
110-
color: var(--color-main-text);
111-
}
112-
}
113-
114-
&__content {
115-
display: inline-flex;
116-
gap: 0 10px;
117-
}
118-
119-
&__displayname {
120-
font-weight: bold;
121-
}
122-
}
123-
</style>

core/src/components/UserMenu.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55

66
import Vue from 'vue'
77

8-
import UserMenu from '../views/UserMenu.vue'
8+
import AccountMenu from '../views/AccountMenu.vue'
99

1010
export const setUp = () => {
1111
const mountPoint = document.getElementById('user-menu')
1212
if (mountPoint) {
1313
// eslint-disable-next-line no-new
1414
new Vue({
1515
el: mountPoint,
16-
render: h => h(UserMenu),
16+
render: h => h(AccountMenu),
1717
})
1818
}
1919
}

0 commit comments

Comments
 (0)