Name lists on invite dialog (#8046)

* Place room tiles with grid

Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com>

* Set padding inside of name stack

Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com>

* Remove overflow:hidden (to be cancelled)

Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com>

* Replace text-align with margin

Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com>

* Style invite failure dialog with display:grid

Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com>

* Merge style rules of room tiles and tiles on invitation failure dialog

Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com>

* Normalize avatar size for multiInviterError

Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com>

* Set text overflow with ellipsis

Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com>

* Use spacing variables

Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com>

* Set narrow gap to nameStack

Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com>

* Rename mx_InviteDialog_inviterErrorTile_error

Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com>

* Create mx_InviteDialog_tile

Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com>

* Set padding to room tiles only

Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com>

* Remove space between name / userID and time (there is gap by default)

Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com>

* Remove the margin from the last child

Signed-off-by: Suguru Hirahara <luixxiul@users.noreply.github.com>
This commit is contained in:
Suguru Hirahara 2022-06-09 12:45:33 +00:00 committed by GitHub
parent 67cace7de7
commit 12dd5a7ef0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 138 additions and 135 deletions

View file

@ -146,94 +146,6 @@ limitations under the License.
}
}
.mx_InviteDialog_roomTile {
cursor: pointer;
padding: 5px 10px;
&:hover {
background-color: $header-panel-bg-color;
border-radius: 4px;
}
* {
vertical-align: middle;
}
.mx_InviteDialog_roomTile_avatarStack {
display: inline-block;
position: relative;
width: 36px;
height: 36px;
& > * {
position: absolute;
top: 0;
left: 0;
}
}
.mx_InviteDialog_roomTile_selected {
width: 36px;
height: 36px;
border-radius: 36px;
background-color: $username-variant1-color;
display: inline-block;
position: relative;
&::before {
content: "";
width: 24px;
height: 24px;
grid-column: 1;
grid-row: 1;
mask-image: url("$(res)/img/feather-customised/check.svg");
mask-size: 100%;
mask-repeat: no-repeat;
position: absolute;
top: 6px; // 50%
left: 6px; // 50%
background-color: #ffffff; // this is fine without a var because it's for both themes
}
}
.mx_InviteDialog_roomTile_nameStack {
display: inline-block;
overflow: hidden;
}
.mx_InviteDialog_roomTile_name {
font-weight: 600;
font-size: $font-14px;
color: $primary-content;
margin-left: 7px;
}
.mx_InviteDialog_roomTile_userId {
font-size: $font-12px;
color: $muted-fg-color;
margin-left: 7px;
}
.mx_InviteDialog_roomTile_name,
.mx_InviteDialog_roomTile_userId {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.mx_InviteDialog_roomTile_time {
text-align: right;
font-size: $font-12px;
color: $muted-fg-color;
float: right;
line-height: $font-36px; // Height of the avatar to keep the time vertically aligned
}
.mx_InviteDialog_roomTile_highlight {
font-weight: 900;
}
}
// Many of these styles are stolen from mx_UserPill, but adjusted for the invite dialog.
.mx_InviteDialog_userTile {
margin-right: 8px;
@ -414,6 +326,125 @@ limitations under the License.
mask-image: url('$(res)/img/voip/tab-dialpad.svg');
}
.mx_InviteDialog_tile {
cursor: pointer;
display: grid;
gap: $spacing-8 $spacing-12;
align-items: center;
&.mx_InviteDialog_tile--room {
grid-template-columns: min-content auto auto; // mx_InviteDialog_tile_avatarStack, mx_InviteDialog_tile_nameStack, time
padding: $spacing-4 $spacing-8;
&:hover {
background-color: $header-panel-bg-color;
border-radius: 4px;
}
.mx_InviteDialog_tile--room_selected {
border-radius: 36px;
background-color: $username-variant1-color;
&::before {
content: "";
width: 24px;
height: 24px;
grid-column: 1;
grid-row: 1;
mask-image: url("$(res)/img/feather-customised/check.svg");
mask-size: 100%;
mask-repeat: no-repeat;
position: absolute;
top: 6px; // 50%
left: 6px; // 50%
background-color: #ffffff; // this is fine without a var because it's for both themes
}
}
.mx_InviteDialog_tile--room_time {
margin-inline-start: auto;
width: max-content;
font-size: $font-12px;
color: $muted-fg-color;
}
.mx_InviteDialog_tile--room_highlight {
font-weight: 900;
}
}
&.mx_InviteDialog_tile--inviterError {
grid-template-columns: max-content auto; // max-content = avatar width
margin-bottom: $spacing-24;
&:last-child {
margin-bottom: 0;
}
.mx_InviteDialog_tile--inviterError_errorText {
grid-row-start: 2;
grid-column-start: 2;
font-size: $font-15px;
color: $alert;
}
}
* {
vertical-align: middle;
}
.mx_InviteDialog_tile_avatarStack,
.mx_InviteDialog_tile--room_selected {
width: 36px;
height: 36px;
display: inline-block;
position: relative;
}
.mx_InviteDialog_tile_avatarStack {
grid-row-start: 1;
grid-column-start: 1;
& > * {
position: absolute;
top: 0;
left: 0;
}
}
.mx_InviteDialog_tile_nameStack {
grid-row-start: 1;
grid-column-start: 2;
display: flex;
flex-flow: column;
align-self: center;
align-items: baseline;
gap: 2px 0;
overflow: hidden;
.mx_InviteDialog_tile_nameStack_name,
.mx_InviteDialog_tile_nameStack_userId {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 100%;
}
.mx_InviteDialog_tile_nameStack_name {
font-size: $font-15px;
font-weight: $font-semi-bold;
color: $primary-content;
}
.mx_InviteDialog_tile_nameStack_userId {
font-size: $font-12px;
color: $muted-fg-color;
}
}
}
.mx_InviteDialog_multiInviterError {
> h4 {
font-size: $font-15px;
@ -421,36 +452,6 @@ limitations under the License.
color: $secondary-content;
font-weight: normal;
}
> div {
.mx_InviteDialog_multiInviterError_entry {
margin-bottom: 24px;
.mx_InviteDialog_multiInviterError_entry_userProfile {
.mx_InviteDialog_multiInviterError_entry_name {
margin-left: 6px;
font-size: $font-15px;
line-height: $font-24px;
font-weight: $font-semi-bold;
color: $primary-content;
}
.mx_InviteDialog_multiInviterError_entry_userId {
margin-left: 6px;
font-size: $font-12px;
line-height: $font-15px;
color: $tertiary-content;
}
}
.mx_InviteDialog_multiInviterError_entry_error {
margin-left: 32px;
font-size: $font-15px;
line-height: $font-24px;
color: $alert;
}
}
}
}
.mx_InviteDialog_identityServer {

View file

@ -153,19 +153,21 @@ export function showAnyInviteErrors(
const user = userMap?.get(addr) || cli.getUser(addr);
const name = (user as Member).name || (user as User).rawDisplayName;
const avatarUrl = (user as Member).getMxcAvatarUrl?.() || (user as User).avatarUrl;
return <div key={addr} className="mx_InviteDialog_multiInviterError_entry">
<div className="mx_InviteDialog_multiInviterError_entry_userProfile">
return <div key={addr} className="mx_InviteDialog_tile mx_InviteDialog_tile--inviterError">
<div className="mx_InviteDialog_tile_avatarStack">
<BaseAvatar
url={avatarUrl ? mediaFromMxc(avatarUrl).getSquareThumbnailHttp(24) : null}
name={name}
idName={user.userId}
width={24}
height={24}
width={36}
height={36}
/>
<span className="mx_InviteDialog_multiInviterError_entry_name">{ name }</span>
<span className="mx_InviteDialog_multiInviterError_entry_userId">{ user.userId }</span>
</div>
<div className="mx_InviteDialog_multiInviterError_entry_error">
<div className="mx_InviteDialog_tile_nameStack">
<span className="mx_InviteDialog_tile_nameStack_name">{ name }</span>
<span className="mx_InviteDialog_tile_nameStack_userId">{ user.userId }</span>
</div>
<div className="mx_InviteDialog_tile--inviterError_errorText">
{ inviter.getErrorText(addr) }
</div>
</div>;

View file

@ -178,7 +178,7 @@ class DMRoomTile extends React.PureComponent<IDMRoomTileProps> {
// Highlight the word the user entered
const substr = str.substring(i, filterStr.length + i);
result.push(<span className='mx_InviteDialog_roomTile_highlight' key={i + 'bold'}>{ substr }</span>);
result.push(<span className='mx_InviteDialog_tile--room_highlight' key={i + 'bold'}>{ substr }</span>);
i += substr.length;
}
@ -194,7 +194,7 @@ class DMRoomTile extends React.PureComponent<IDMRoomTileProps> {
let timestamp = null;
if (this.props.lastActiveTs) {
const humanTs = humanizeTime(this.props.lastActiveTs);
timestamp = <span className='mx_InviteDialog_roomTile_time'>{ humanTs }</span>;
timestamp = <span className='mx_InviteDialog_tile--room_time'>{ humanTs }</span>;
}
const avatarSize = 36;
@ -216,13 +216,13 @@ class DMRoomTile extends React.PureComponent<IDMRoomTileProps> {
let checkmark = null;
if (this.props.isSelected) {
// To reduce flickering we put the 'selected' room tile above the real avatar
checkmark = <div className='mx_InviteDialog_roomTile_selected' />;
checkmark = <div className='mx_InviteDialog_tile--room_selected' />;
}
// To reduce flickering we put the checkmark on top of the actual avatar (prevents
// the browser from reloading the image source when the avatar remounts).
const stackedAvatar = (
<span className='mx_InviteDialog_roomTile_avatarStack'>
<span className='mx_InviteDialog_tile_avatarStack'>
{ avatar }
{ checkmark }
</span>
@ -237,11 +237,11 @@ class DMRoomTile extends React.PureComponent<IDMRoomTileProps> {
: this.highlightName(userIdentifier);
return (
<div className='mx_InviteDialog_roomTile' onClick={this.onClick}>
<div className='mx_InviteDialog_tile mx_InviteDialog_tile--room' onClick={this.onClick}>
{ stackedAvatar }
<span className="mx_InviteDialog_roomTile_nameStack">
<div className='mx_InviteDialog_roomTile_name'>{ this.highlightName(this.props.member.name) }</div>
<div className='mx_InviteDialog_roomTile_userId'>{ caption }</div>
<span className="mx_InviteDialog_tile_nameStack">
<div className='mx_InviteDialog_tile_nameStack_name'>{ this.highlightName(this.props.member.name) }</div>
<div className='mx_InviteDialog_tile_nameStack_userId'>{ caption }</div>
</span>
{ timestamp }
</div>

View file

@ -68,7 +68,7 @@ export async function createDm(session: ElementSession, invitees: string[]): Pro
await session.replaceInputText(inviteesEditor, target);
await session.delay(1000); // give it a moment to figure out a suggestion
// find the suggestion and accept it
const suggestions = await session.queryAll('.mx_InviteDialog_roomTile_userId');
const suggestions = await session.queryAll('.mx_InviteDialog_tile_nameStack_userId');
const suggestionTexts = await Promise.all(suggestions.map(s => session.innerText(s)));
const suggestionIndex = suggestionTexts.indexOf(target);
if (suggestionIndex === -1) {

View file

@ -35,7 +35,7 @@ export async function invite(session: ElementSession, userId: string): Promise<v
await inviteButton.click();
const inviteTextArea = await session.query(".mx_InviteDialog_editor input");
await inviteTextArea.type(userId);
const selectUserItem = await session.query(".mx_InviteDialog_roomTile");
const selectUserItem = await session.query(".mx_InviteDialog_tile--room");
await selectUserItem.click();
const confirmButton = await session.query(".mx_InviteDialog_goButton");
await confirmButton.click();