mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 14:38:17 +08:00
UX: Stop avatar flicker when opening user menu on Safari (#26511)
When opening the user menu, we display old cached data, and then replace it with fresh data immediately afterwards. The vast majority of the time the data is unchanged, and so there is no visible change. When rendering HTML elements directly, Ember realizes that there is no change, and does not make any changes to the DOM. Great! However, our `avatar` helper returns a blob of HTML. With raw HTML, Ember does not make any attempt to 'diff' the existing DOM. Instead, it replaces the old string with the new string. That can be a little wasteful, but normally it's not a big deal. But, when it comes to `<img lazy="lazy"`, re-rendering the `img` element causes a visible flicker in Safari. To work around that, this commit replaces the `{{avatar}}` helper with an ember-rendered `<img` element. Now that Ember is responsible for rendering, it can detect there is no real change to the attributes and skip it, thereby avoiding the flicker. If we find ourselves doing this more frequently, we may want to consider creating an `<Avatar` component. But for now, I think it's simple enough to justify building the `<img` manually in this case.
This commit is contained in:
parent
eda4b12260
commit
37ae1708a5
|
@ -1,10 +1,24 @@
|
|||
import avatar from "discourse/helpers/bound-avatar-template";
|
||||
import concatClass from "discourse/helpers/concat-class";
|
||||
import icon from "discourse-common/helpers/d-icon";
|
||||
import { avatarUrl, translateSize } from "discourse-common/lib/avatar-utils";
|
||||
|
||||
const avatarPx = translateSize("small");
|
||||
|
||||
const IconAvatar = <template>
|
||||
<div class={{concatClass "icon-avatar" @data.classNames}}>
|
||||
{{avatar @data.avatarTemplate "small"}}
|
||||
{{!--
|
||||
avoiding {{avatar}} helper because its html would be fully
|
||||
re-rendered whenever arguments change, even if the argument values
|
||||
are identical. On some browsers, re-rendering a lazy-loaded image
|
||||
causes a visible flicker.
|
||||
--}}
|
||||
<img
|
||||
lazy="lazy"
|
||||
src={{avatarUrl @data.avatarTemplate "small"}}
|
||||
width={{avatarPx}}
|
||||
height={{avatarPx}}
|
||||
class="avatar"
|
||||
/>
|
||||
<div class="icon-avatar__icon-wrapper">
|
||||
{{icon @data.icon}}
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue
Block a user