Skip to content
This repository has been archived by the owner on Jan 3, 2024. It is now read-only.

Commit

Permalink
Improve share type description in Avatar Group
Browse files Browse the repository at this point in the history
  • Loading branch information
pascalwengerter committed May 5, 2021
1 parent ce4bfdb commit a4306ec
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 49 deletions.
8 changes: 8 additions & 0 deletions changelog/unreleased/enhancement-a11y-avatar
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Enhancement: Lazy img loading & accessibility for OcAvatar

- Add lazy loading to OcImg component
- Internalize former dependency vue-avatar into OcAvatar
- Make OcAvatar use OcImg component, using lazy loading
- Change OcAvatar to be a11y compliant (color contrasts, DOM structure)

https://github.com/owncloud/owncloud-design-system/pull/1282
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@
"uikit": "3.5.16",
"url-loader": "^4.1.1",
"vue": "^2.6.11",
"vue-avatar": "^2.2.0",
"vue-datetime": "^1.0.0-beta.10",
"vue-gettext": "^2.1.12",
"vue-inline-svg": "^2.0.0",
Expand Down Expand Up @@ -146,7 +145,6 @@
"postcss-url": "^9.0.0",
"uikit": "3.5.16",
"vue": "^2.6.11",
"vue-avatar": "^2.2.0",
"vue-datetime": "^1.0.0-beta.10",
"vue-inline-svg": "^2.0.0",
"vue-select": "^3.11.2",
Expand Down
10 changes: 9 additions & 1 deletion src/components/OcImage.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<img :src="src" :alt="alt" :title="title" />
<img :src="src" :alt="alt" :aria-hidden="!alt" :title="title" />
</template>
<script>
/**
Expand Down Expand Up @@ -36,6 +36,14 @@ export default {
required: false,
default: null,
},
loadingType: {
type: String,
required: false,
default: "eager",
validator: value => {
return value.match(/(eager|lazy)/)
},
},
},
}
</script>
Expand Down
2 changes: 1 addition & 1 deletion src/components/__snapshots__/OcSidebar.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ exports[`OcSidebar displays a logo image if its source is specified 1`] = `
<div class="oc-sidebar-content-wrapper">
<!---->
<router-link-stub tag="a" to="/" class="oc-sidebar-logo">
<oc-img-stub src="examples/placeholder_brand_logo.svg" alt="ownCloud" class="oc-sidebar-logo-img"></oc-img-stub>
<oc-img-stub src="examples/placeholder_brand_logo.svg" alt="ownCloud" loadingtype="eager" class="oc-sidebar-logo-img"></oc-img-stub>
</router-link-stub>
<!---->
<nav class="oc-sidebar-nav">
Expand Down
143 changes: 128 additions & 15 deletions src/components/avatars/OcAvatar.vue
Original file line number Diff line number Diff line change
@@ -1,31 +1,50 @@
<template>
<avatar
class="oc-avatar"
:username="userName"
:size="width"
:src="src"
<span
class="vue-avatar--wrapper oc-avatar"
:style="[style]"
:width="width"
:aria-label="accessibleLabel === '' ? null : accessibleLabel"
:aria-hidden="accessibleLabel === '' ? 'true' : null"
:focusable="accessibleLabel === '' ? 'false' : null"
:role="accessibleLabel === '' ? null : 'img'"
/>
>
<oc-img v-if="isImage" loading="lazy" class="avatarImg" :src="src" @error="onImgError" />
<span v-show="!isImage" class="avatarInitials">{{ userInitial }}</span>
</span>
</template>

<script>
import Avatar from "vue-avatar"
import OcImg from "../OcImage.vue"
/**
* Avatar is a thumbnail representing user or group
*/
const getInitials = userName => {
let parts = userName.split(/[ -]/)
let initials = ""
for (var i = 0; i < parts.length; i++) {
initials += parts[i].charAt(0)
}
if (initials.length > 3 && initials.search(/[A-Z]/) !== -1) {
initials = initials.replace(/[a-z]+/g, "")
}
initials = initials.substr(0, 3).toUpperCase()
return initials
}
export default {
name: "OcAvatar",
status: "review",
release: "1.0.0",
components: {
Avatar,
},
components: { OcImg },
props: {
/**
* Source of the avatar
* Source of the avatar img. If none is provided, the avatar's initials get rendered on a colorful background
*/
src: {
type: String,
Expand All @@ -48,18 +67,112 @@ export default {
required: false,
default: "",
},
/**
* The size of the avatar in pixels
*/
width: {
type: Number,
required: false,
default: 50,
},
},
data() {
return {
backgroundColors: [
"#b82015",
"#c21c53",
"#9C27B0",
"#673AB7",
"#3F51B5",
"#106892",
"#055c68",
"#009688",
"#1a761d",
"#476e1a",
"#636d0b",
"#8e5c11",
"#795548",
"#465a64",
],
imgError: false,
}
},
computed: {
background() {
if (!this.isImage) {
return this.randomBackgroundColor(this.userName.length, this.backgroundColors)
}
return ""
},
isImage() {
return !this.imgError && Boolean(this.src)
},
style() {
const style = {
width: `${this.width}px`,
height: `${this.width}px`,
lineHeight: `${this.width + Math.floor(this.width / 20)}px`,
}
const initialBackgroundAndFontStyle = {
backgroundColor: this.background,
font: `${Math.floor(this.width / 2.5)}px/${this.width}px Helvetica, Arial, sans-serif`,
color: "white",
}
Object.assign(style, initialBackgroundAndFontStyle)
return style
},
userInitial() {
if (!this.isImage) {
const initials = getInitials(this.userName)
return initials
}
return ""
},
},
mounted() {
if (!this.isImage) {
this.$emit("avatar-initials", this.userName, this.userInitial)
}
},
methods: {
onImgError() {
this.imgError = true
},
randomBackgroundColor(seed, colors) {
return colors[seed % colors.length]
},
},
}
</script>

<style lang="scss">
.oc-avatar {
font-weight: bold;
align-items: center;
justify-content: center;
text-align: center;
user-select: none;
display: flex;
border-radius: 50%;
.avatarImg {
width: 100%;
height: auto;
border-radius: 50%;
}
}
</style>

<docs>
```
<oc-avatar src="https://picsum.photos/50/50?image=1074" accessibleLabel="Lion" />
<oc-avatar userName="Bruce Lee" accessibleLabel="Lion" />
```js
<oc-avatar src="https://picsum.photos/50/50?image=1074" accessible-label="Lion" />
<oc-avatar user-name="Bruce Lee" accessible-label="Lion" />
```
</docs>
Loading

0 comments on commit a4306ec

Please sign in to comment.