Skip to content

Commit 4908bee

Browse files
authored
Merge pull request #7260 from nextcloud-libraries/backport/6004/stable8
[stable8] fix(NcAvatar): orbital best-fit adaptive status icon
2 parents bef3df7 + 5383719 commit 4908bee

File tree

2 files changed

+123
-76
lines changed

2 files changed

+123
-76
lines changed

src/components/NcAvatar/NcAvatar.vue

Lines changed: 118 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -41,44 +41,24 @@ export default {
4141
### Avatar with preloaded status
4242
```
4343
<template>
44-
<div class="grid">
45-
<NcAvatar user="janedoe"
46-
display-name="Jane Doe"
47-
:size="44"
48-
:preloaded-user-status="status.online">
49-
</NcAvatar>
50-
<NcAvatar user="janedoe"
51-
display-name="Jane Doe"
52-
:size="44"
53-
:preloaded-user-status="status.away">
54-
</NcAvatar>
55-
<NcAvatar user="janedoe"
56-
display-name="Jane Doe"
57-
:size="44"
58-
:preloaded-user-status="status.dnd">
59-
</NcAvatar>
60-
<NcAvatar user="janedoe"
61-
display-name="Jane Doe"
62-
:size="44"
63-
:preloaded-user-status="status.custom">
64-
</NcAvatar>
65-
<NcAvatar user="janedoe"
66-
display-name="Jane Doe"
67-
:preloaded-user-status="status.online">
68-
</NcAvatar>
69-
<NcAvatar user="janedoe"
70-
display-name="Jane Doe"
71-
:preloaded-user-status="status.away">
72-
</NcAvatar>
73-
<NcAvatar user="janedoe"
74-
display-name="Jane Doe"
75-
:preloaded-user-status="status.dnd">
76-
</NcAvatar>
77-
<NcAvatar user="janedoe"
78-
display-name="Jane Doe"
79-
:preloaded-user-status="status.custom">
80-
</NcAvatar>
81-
</div>
44+
<div>
45+
<NcAvatar user="janedoe"
46+
display-name="Jane Doe"
47+
:preloaded-user-status="status.online">
48+
</NcAvatar>
49+
<NcAvatar user="janedoe"
50+
display-name="Jane Doe"
51+
:preloaded-user-status="status.away">
52+
</NcAvatar>
53+
<NcAvatar user="janedoe"
54+
display-name="Jane Doe"
55+
:preloaded-user-status="status.dnd">
56+
</NcAvatar>
57+
<NcAvatar user="janedoe"
58+
display-name="Jane Doe"
59+
:preloaded-user-status="status.custom">
60+
</NcAvatar>
61+
</div>
8262
</template>
8363

8464
<script>
@@ -111,16 +91,6 @@ export default {
11191
},
11292
}
11393
</script>
114-
<style>
115-
.grid {
116-
width: fit-content;
117-
display: grid;
118-
justify-content: center;
119-
align-items: center;
120-
gap: 8px;
121-
grid-template-columns: repeat(4, 1fr);
122-
}
123-
</style>
12494
```
12595

12696
### Avatar for non-users
@@ -150,6 +120,72 @@ export default {
150120
</style>
151121
```
152122

123+
### Avatar size
124+
125+
```vue
126+
<template>
127+
<div>
128+
<div v-for="size in [15, 24, 34, 44, 180]">
129+
<span>
130+
{{ size }}px
131+
</span>
132+
<NcAvatar user="alice-smith"
133+
display-name="Alice Smith"
134+
:size="size"
135+
:preloaded-user-status="status.online" />
136+
<NcAvatar user="bob-doe"
137+
display-name="Bob Doe"
138+
:size="size"
139+
:preloaded-user-status="status.meeting" />
140+
</div>
141+
<div>
142+
<div>
143+
Custom: {{ customSize }}px
144+
</div>
145+
<NcAvatar user="alice-smith"
146+
display-name="Alice Smith"
147+
:size="customSize"
148+
:preloaded-user-status="status.online" />
149+
<NcAvatar user="bob-doe"
150+
display-name="Bob Doe"
151+
:size="customSize"
152+
:preloaded-user-status="status.meeting" />
153+
</div>
154+
<div>
155+
<input type="range" v-model="customSize" :min="15" :max="180" step="1" />
156+
</div>
157+
</div>
158+
</template>
159+
160+
<script>
161+
import AccountMultiple from 'vue-material-design-icons/AccountMultiple.vue'
162+
163+
export default {
164+
components: {
165+
AccountMultiple,
166+
},
167+
168+
data() {
169+
return {
170+
customSize: 20,
171+
status: {
172+
online: {
173+
icon: '',
174+
status: 'online',
175+
message: 'Available',
176+
},
177+
meeting: {
178+
icon: '📆',
179+
status: 'online',
180+
message: 'In a meeting',
181+
},
182+
},
183+
}
184+
},
185+
}
186+
</script>
187+
```
188+
153189
</docs>
154190
<template>
155191
<span v-click-outside="closeMenu"
@@ -527,7 +563,7 @@ export default {
527563
528564
avatarStyle() {
529565
return {
530-
'--size': this.size + 'px',
566+
'--avatar-size': this.size + 'px',
531567
lineHeight: this.showInitials ? (this.size + 'px') : 0,
532568
fontSize: Math.round(this.size * 0.45) + 'px',
533569
}
@@ -839,8 +875,8 @@ export default {
839875
.avatardiv {
840876
position: relative;
841877
display: inline-block;
842-
width: var(--size);
843-
height: var(--size);
878+
width: var(--avatar-size);
879+
height: var(--avatar-size);
844880
845881
&--unknown {
846882
position: relative;
@@ -882,24 +918,24 @@ export default {
882918
:deep() {
883919
.button-vue,
884920
.button-vue__icon {
885-
height: var(--size);
886-
min-height: var(--size);
887-
width: var(--size) !important;
888-
min-width: var(--size);
921+
height: var(--avatar-size);
922+
min-height: var(--avatar-size);
923+
width: var(--avatar-size) !important;
924+
min-width: var(--avatar-size);
889925
}
890926
}
891927
& > :deep(.button-vue),
892928
& > :deep(.action-item .button-vue) {
893-
--button-radius: calc(var(--size) / 2);
929+
--button-radius: calc(var(--avatar-size) / 2);
894930
}
895931
}
896932
897933
.avatardiv__initials-wrapper {
898934
display: block;
899-
height: var(--size);
900-
width: var(--size);
935+
height: var(--avatar-size);
936+
width: var(--avatar-size);
901937
background-color: var(--color-main-background);
902-
border-radius: calc(var(--size) / 2);
938+
border-radius: calc(var(--avatar-size) / 2);
903939
904940
.avatardiv__initials {
905941
position: absolute;
@@ -921,28 +957,38 @@ export default {
921957
}
922958
923959
.material-design-icon {
924-
width: var(--size);
925-
height: var(--size);
960+
width: var(--avatar-size);
961+
height: var(--avatar-size);
926962
}
927963
928964
.avatardiv__user-status {
965+
// Size of the status icon to make it:
966+
// - 💫 Orbital: the status icon's center is positioned on the avatar circle
967+
// - ⏹️ Best-fit: the status icon is as large as possible without exceeding the avatar box
968+
// See PR for math explanation: PR #6004
969+
--avatar-status-size-orbital: calc(var(--avatar-size) * (1 - 1 / sqrt(2)));
970+
// Limit the status icon size to the status of a small clickable avatar
971+
// Ideally avatars with a smaller should not be used with the status icon at all
972+
--avatar-status-size-min: calc(var(--default-clickable-area) * (1 - 1 / sqrt(2)));
973+
--avatar-status-size: max(var(--avatar-status-size-orbital), var(--avatar-status-size-min));
974+
// Because the status icon size is limited, smaller avatar requires a position offset to keep the status icon orbital
975+
--avatar-status-icon-position: min(0px, (var(--avatar-status-size-orbital) - var(--avatar-status-size)) / 2);
929976
box-sizing: border-box;
930977
position: absolute;
931-
inset-inline-end: -4px;
932-
bottom: -4px;
933-
min-height: 14px;
934-
min-width: 14px;
935-
max-height: 18px;
936-
max-width: 18px;
937-
height: 40%;
938-
width: 40%;
978+
inset-inline-end: var(--avatar-status-icon-position);
979+
inset-block-end: var(--avatar-status-icon-position);
980+
height: var(--avatar-status-size);
981+
width: var(--avatar-status-size);
939982
line-height: 1;
940-
font-size: clamp(var(--font-size-small, 13px), 85%, var(--default-font-size));
983+
font-size: calc(var(--avatar-status-size) / 1.2);
941984
background-color: var(--color-main-background);
942985
background-repeat: no-repeat;
943-
background-size: 16px;
986+
background-size: var(--avatar-status-size);
944987
background-position: center;
945988
border-radius: 50%;
989+
display: flex;
990+
align-items: center;
991+
justify-content: center;
946992
947993
.acli:hover & {
948994
border-color: var(--color-background-hover);
@@ -967,7 +1013,7 @@ export default {
9671013
9681014
.avatar-class-icon {
9691015
display: block;
970-
border-radius: calc(var(--size) / 2);
1016+
border-radius: calc(var(--avatar-size) / 2);
9711017
background-color: var(--color-background-darker);
9721018
height: 100%;
9731019
}

src/components/NcUserStatusIcon/NcUserStatusIcon.vue

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,13 +175,14 @@ export default {
175175
display: flex;
176176
justify-content: center;
177177
align-items: center;
178-
min-width: 16px;
179-
min-height: 16px;
180-
max-width: 20px;
181-
max-height: 20px;
182178
183179
&--invisible {
184180
filter: var(--background-invert-if-dark);
185181
}
182+
183+
:deep(svg) {
184+
width: 100%;
185+
height: 100%;
186+
}
186187
}
187188
</style>

0 commit comments

Comments
 (0)