Fix avatar focus highlight

This commit is contained in:
Evan Hahn 2021-10-12 14:07:58 -05:00 committed by GitHub
parent f5cce73611
commit f4b0bade80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 74 additions and 90 deletions

View File

@ -570,14 +570,17 @@
@mixin avatar-colors {
@each $color, $value in $avatar-colors {
&--#{$color} {
background-color: map-get($value, 'bg');
color: map-get($value, 'fg');
--bg: #{map-get($value, 'bg')};
--fg: #{map-get($value, 'fg')};
background-color: var(--bg);
color: var(--fg);
&--icon {
background-color: map-get($value, 'fg');
background-color: var(--fg);
@include dark-theme {
// For specificity
background-color: map-get($value, 'fg');
background-color: var(--fg);
}
}
}

View File

@ -1267,22 +1267,6 @@
}
}
.module-message__author-avatar {
@include button-reset;
cursor: pointer;
&:focus {
outline: none;
.module-Avatar {
@include keyboard-mode {
box-shadow: 0 0 0 3px $color-ultramarine;
}
}
}
}
.module-message__typing-container {
height: 16px;

View File

@ -2,39 +2,46 @@
// SPDX-License-Identifier: AGPL-3.0-only
.module-Avatar {
align-items: center;
border-radius: 100%;
display: inline-flex;
justify-content: center;
line-height: 0;
overflow: hidden;
position: relative;
user-select: none;
vertical-align: middle;
&__button {
@include button-reset;
align-items: center;
display: flex;
height: 100%;
justify-content: center;
&__contents {
@include avatar-colors;
position: relative;
overflow: hidden;
border-radius: 100%;
width: 100%;
height: 100%;
border: 0;
padding: 0;
margin: 0;
outline: none;
@include keyboard-mode {
&:focus {
box-shadow: 0px 0px 0px 2px $color-ultramarine;
@at-root button#{&} {
@include keyboard-mode {
&:focus {
box-shadow: 0 0 0 3px $color-ultramarine;
}
}
}
}
&__image,
&__label,
&__icon,
&__spinner-container,
&__click-to-view {
width: 100%;
height: 100%;
}
&__image {
background-position: center center;
background-size: cover;
display: flex;
height: 100%;
transition: filter 100ms ease-out;
width: 100%;
}
&__click-to-view {
@ -44,12 +51,10 @@
color: $color-white;
display: flex;
flex-direction: column;
height: 100%;
justify-content: center;
left: 0;
position: absolute;
top: 0;
width: 100%;
&::before {
@include color-svg(
@ -78,27 +83,22 @@
}
&__icon {
@mixin avatar-icon($icon) {
-webkit-mask: url($icon) no-repeat center;
-webkit-mask-size: 100%;
}
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center;
-webkit-mask-size: 62%;
background-color: var(--fg);
&--direct {
@include avatar-icon('../images/icons/v2/profile-outline-20.svg');
height: 60%;
width: 60%;
-webkit-mask-image: url('../images/icons/v2/profile-outline-20.svg');
-webkit-mask-size: 60%;
}
&--group {
@include avatar-icon('../images/icons/v2/group-outline-24.svg');
height: 62%;
width: 62%;
-webkit-mask-image: url('../images/icons/v2/group-outline-24.svg');
}
&--note-to-self {
@include avatar-icon('../images/icons/v2/note-24.svg');
height: 62%;
width: 62%;
-webkit-mask-image: url('../images/icons/v2/note-24.svg');
}
}
@ -106,8 +106,6 @@
padding: 4px;
}
@include avatar-colors();
&--undefined {
background-color: $color-gray-15;
color: $color-gray-75;

View File

@ -6,6 +6,7 @@
display: flex;
flex-direction: column;
justify-content: center;
margin-top: 4px;
&__name {
@include font-title-2;

View File

@ -3,6 +3,8 @@
import React, {
FunctionComponent,
MouseEvent,
ReactChild,
ReactNode,
useEffect,
useState,
@ -53,7 +55,7 @@ export type Props = {
title: string;
unblurredAvatarPath?: string;
onClick?: () => unknown;
onClick?: (event: MouseEvent<HTMLButtonElement>) => unknown;
// Matches Popper's RefHandler type
innerRef?: React.Ref<HTMLDivElement>;
@ -118,10 +120,10 @@ export const Avatar: FunctionComponent<Props> = ({
const shouldUseInitials =
!hasImage && conversationType === 'direct' && Boolean(initials);
let contents: ReactNode;
let contentsChildren: ReactNode;
if (loading) {
const svgSize = size < 40 ? 'small' : 'normal';
contents = (
contentsChildren = (
<div className="module-Avatar__spinner-container">
<Spinner
size={`${size - 8}px`}
@ -141,7 +143,7 @@ export const Avatar: FunctionComponent<Props> = ({
const isBlurred =
blur === AvatarBlur.BlurPicture ||
blur === AvatarBlur.BlurPictureWithClickToView;
contents = (
contentsChildren = (
<>
<div
className="module-Avatar__image"
@ -156,17 +158,16 @@ export const Avatar: FunctionComponent<Props> = ({
</>
);
} else if (noteToSelf) {
contents = (
contentsChildren = (
<div
className={classNames(
'module-Avatar__icon',
`module-Avatar--${color}--icon`,
'module-Avatar__icon--note-to-self'
)}
/>
);
} else if (shouldUseInitials) {
contents = (
contentsChildren = (
<div
aria-hidden="true"
className="module-Avatar__label"
@ -176,23 +177,29 @@ export const Avatar: FunctionComponent<Props> = ({
</div>
);
} else {
contents = (
contentsChildren = (
<div
className={classNames(
'module-Avatar__icon',
`module-Avatar--${color}--icon`,
`module-Avatar__icon--${conversationType}`
)}
/>
);
}
let contents: ReactChild;
const contentsClassName = classNames(
'module-Avatar__contents',
`module-Avatar__contents--${color}`
);
if (onClick) {
contents = (
<button className="module-Avatar__button" type="button" onClick={onClick}>
{contents}
<button className={contentsClassName} type="button" onClick={onClick}>
{contentsChildren}
</button>
);
} else {
contents = <div className={contentsClassName}>{contentsChildren}</div>;
}
return (
@ -201,9 +208,6 @@ export const Avatar: FunctionComponent<Props> = ({
className={classNames(
'module-Avatar',
hasImage ? 'module-Avatar--with-image' : 'module-Avatar--no-image',
{
[`module-Avatar--${color}`]: !hasImage,
},
className
)}
style={{

View File

@ -1206,33 +1206,27 @@ export class Message extends React.PureComponent<Props, State> {
'module-message__author-avatar-container--with-reactions': this.hasReactions(),
})}
>
<button
type="button"
className="module-message__author-avatar"
onClick={(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
<Avatar
acceptedMessageRequest={author.acceptedMessageRequest}
avatarPath={author.avatarPath}
color={author.color}
conversationType="direct"
i18n={i18n}
isMe={author.isMe}
name={author.name}
onClick={event => {
event.stopPropagation();
event.preventDefault();
showContactModal(author.id);
}}
tabIndex={0}
>
<Avatar
acceptedMessageRequest={author.acceptedMessageRequest}
avatarPath={author.avatarPath}
color={author.color}
conversationType="direct"
i18n={i18n}
isMe={author.isMe}
name={author.name}
phoneNumber={author.phoneNumber}
profileName={author.profileName}
sharedGroupNames={author.sharedGroupNames}
size={28}
title={author.title}
unblurredAvatarPath={author.unblurredAvatarPath}
/>
</button>
phoneNumber={author.phoneNumber}
profileName={author.profileName}
sharedGroupNames={author.sharedGroupNames}
size={28}
title={author.title}
unblurredAvatarPath={author.unblurredAvatarPath}
/>
</div>
);
}