Fix avatar focus highlight
This commit is contained in:
parent
f5cce73611
commit
f4b0bade80
6 changed files with 74 additions and 90 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
margin-top: 4px;
|
||||
|
||||
&__name {
|
||||
@include font-title-2;
|
||||
|
|
|
@ -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={{
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue