A11Y: multiple fixes to user stream items (#18368)
- in group activity, allows avatars to be selectable by tabbing or screen readers - in user activity > drafts, fixes a bug where for draft replies, the wrong avatar was being shown in the user card - in both group and user activity, fixes the order of focusable items
This commit is contained in:
parent
b97cb222c2
commit
217274f2c1
|
@ -3,6 +3,7 @@ import discourseComputed from "discourse-common/utils/decorators";
|
||||||
import getURL from "discourse-common/lib/get-url";
|
import getURL from "discourse-common/lib/get-url";
|
||||||
import { prioritizeNameInUx } from "discourse/lib/settings";
|
import { prioritizeNameInUx } from "discourse/lib/settings";
|
||||||
import { propertyEqual } from "discourse/lib/computed";
|
import { propertyEqual } from "discourse/lib/computed";
|
||||||
|
import { userPath } from "discourse/lib/url";
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
classNameBindings: [
|
classNameBindings: [
|
||||||
|
@ -35,4 +36,9 @@ export default Component.extend({
|
||||||
return `group-${postUser.primary_group_name}`;
|
return `group-${postUser.primary_group_name}`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@discourseComputed("post.user.username")
|
||||||
|
userUrl(username) {
|
||||||
|
return userPath(username.toLowerCase());
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,6 +2,8 @@ import Component from "@ember/component";
|
||||||
import { actionDescription } from "discourse/widgets/post-small-action";
|
import { actionDescription } from "discourse/widgets/post-small-action";
|
||||||
import { computed } from "@ember/object";
|
import { computed } from "@ember/object";
|
||||||
import { propertyEqual } from "discourse/lib/computed";
|
import { propertyEqual } from "discourse/lib/computed";
|
||||||
|
import { userPath } from "discourse/lib/url";
|
||||||
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
tagName: "li",
|
tagName: "li",
|
||||||
|
@ -28,4 +30,9 @@ export default Component.extend({
|
||||||
"item.created_at",
|
"item.created_at",
|
||||||
"item.action_code_who"
|
"item.action_code_who"
|
||||||
),
|
),
|
||||||
|
|
||||||
|
@discourseComputed("item.draft_username", "item.username")
|
||||||
|
userUrl(draftUsername, username) {
|
||||||
|
return userPath((draftUsername || username).toLowerCase());
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { and, equal, or } from "@ember/object/computed";
|
import { equal, or } from "@ember/object/computed";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
import categoryFromId from "discourse-common/utils/category-macro";
|
import categoryFromId from "discourse-common/utils/category-macro";
|
||||||
import RestModel from "discourse/models/rest";
|
import RestModel from "discourse/models/rest";
|
||||||
|
@ -108,7 +108,6 @@ const UserAction = RestModel.extend({
|
||||||
mentionType: equal("action_type", UserActionTypes.mentions),
|
mentionType: equal("action_type", UserActionTypes.mentions),
|
||||||
isPM: or("messageSentType", "messageReceivedType"),
|
isPM: or("messageSentType", "messageReceivedType"),
|
||||||
postReplyType: or("postType", "replyType"),
|
postReplyType: or("postType", "replyType"),
|
||||||
removableBookmark: and("bookmarkType", "sameUser"),
|
|
||||||
|
|
||||||
addChild(action) {
|
addChild(action) {
|
||||||
let groups = this.childGroups;
|
let groups = this.childGroups;
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
<div class="clearfix info">
|
<div class="user-stream-item__header info">
|
||||||
<a href={{this.post.user.userUrl}} data-user-card={{this.post.user.username}} class="avatar-link">
|
<a href={{this.userUrl}} data-user-card={{this.post.user.username}} class="avatar-link">
|
||||||
{{avatar this.post.user imageSize="large" extraClasses="actor" ignoreTitle="true"}}
|
{{avatar this.post.user imageSize="large" extraClasses="actor" ignoreTitle="true"}}
|
||||||
</a>
|
</a>
|
||||||
<span class="time">{{format-date this.post.created_at leaveAgo="true"}}</span>
|
|
||||||
<ExpandPost @item={{this.post}} />
|
|
||||||
|
|
||||||
<div class="stream-topic-details">
|
<div class="user-stream-item__details">
|
||||||
<div class="stream-topic-title">
|
<div class="stream-topic-title">
|
||||||
<span class="title">
|
<span class="title">
|
||||||
<a href={{this.postUrl}}>{{html-safe this.post.topic.fancyTitle}}</a>
|
<a href={{this.postUrl}}>{{html-safe this.post.topic.fancyTitle}}</a>
|
||||||
|
@ -20,6 +18,9 @@
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<ExpandPost @item={{this.post}} />
|
||||||
|
<span class="time">{{format-date this.post.created_at leaveAgo="true"}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="excerpt">
|
<div class="excerpt">
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
<div class="clearfix info">
|
<div class="user-stream-item__header info">
|
||||||
<a href={{@item.userUrl}} data-user-card={{@item.username}} class="avatar-link"><div class="avatar-wrapper">{{avatar @item imageSize="large" extraClasses="actor" ignoreTitle="true"}}</div></a>
|
<a href={{this.userUrl}} data-user-card={{(or @item.draft_username @item.username)}} class="avatar-link">
|
||||||
<span class="time">{{format-date @item.created_at}}</span>
|
<div class="avatar-wrapper">
|
||||||
{{#if @item.draftType}}
|
{{avatar @item imageSize="large" extraClasses="actor" ignoreTitle="true"}}
|
||||||
<span class="draft-type">{{html-safe @item.draftType}}</span>
|
</div>
|
||||||
{{else}}
|
</a>
|
||||||
<ExpandPost @item={{@item}} />
|
|
||||||
{{/if}}
|
<div class="user-stream-item__details">
|
||||||
<div class="stream-topic-details">
|
|
||||||
<div class="stream-topic-title">
|
<div class="stream-topic-title">
|
||||||
<TopicStatus @topic={{@item}} @disableActions={{true}} />
|
<TopicStatus @topic={{@item}} @disableActions={{true}} />
|
||||||
<span class="title">
|
<span class="title">
|
||||||
|
@ -20,6 +19,13 @@
|
||||||
<div class="category">{{category-link @item.category}}</div>
|
<div class="category">{{category-link @item.category}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{#if @item.draftType}}
|
||||||
|
<span class="draft-type">{{html-safe @item.draftType}}</span>
|
||||||
|
{{else}}
|
||||||
|
<ExpandPost @item={{@item}} />
|
||||||
|
{{/if}}
|
||||||
|
<span class="time">{{format-date @item.created_at}}</span>
|
||||||
|
|
||||||
{{#if @item.deleted_by}}
|
{{#if @item.deleted_by}}
|
||||||
<span class="delete-info">
|
<span class="delete-info">
|
||||||
{{d-icon "far-trash-alt"}}
|
{{d-icon "far-trash-alt"}}
|
||||||
|
@ -50,12 +56,12 @@
|
||||||
<div class="user-stream-item-actions child-actions">
|
<div class="user-stream-item-actions child-actions">
|
||||||
{{d-icon child.icon class="icon"}}
|
{{d-icon child.icon class="icon"}}
|
||||||
{{#each child.items as |grandChild|}}
|
{{#each child.items as |grandChild|}}
|
||||||
{{#if grandChild.removableBookmark}}
|
<a href={{grandChild.userUrl}} data-user-card={{grandChild.username}} class="avatar-link">
|
||||||
<DButton @class="btn-default remove-bookmark" @action={{action @removeBookmark grandChild}} @icon="times" @label="bookmarks.remove" />
|
<div class="avatar-wrapper">
|
||||||
{{else}}
|
{{avatar grandChild imageSize="tiny" extraClasses="actor" ignoreTitle="true" avatarTemplatePath="acting_avatar_template"}}
|
||||||
<a href={{grandChild.userUrl}} data-user-card={{grandChild.username}} class="avatar-link"><div class="avatar-wrapper">{{avatar grandChild imageSize="tiny" extraClasses="actor" ignoreTitle="true" avatarTemplatePath="acting_avatar_template"}}</div></a>
|
</div>
|
||||||
|
</a>
|
||||||
{{#if grandChild.edit_reason}} — <span class="edit-reason">{{grandChild.edit_reason}}</span>{{/if}}
|
{{#if grandChild.edit_reason}} — <span class="edit-reason">{{grandChild.edit_reason}}</span>{{/if}}
|
||||||
{{/if}}
|
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
|
@ -283,6 +283,13 @@ acceptance("Group - Authenticated", function (needs) {
|
||||||
);
|
);
|
||||||
|
|
||||||
await click(".dialog-footer .btn-default");
|
await click(".dialog-footer .btn-default");
|
||||||
|
|
||||||
|
await visit("/g/discourse/activity/posts");
|
||||||
|
|
||||||
|
assert.ok(
|
||||||
|
".user-stream-item a.avatar-link[href='/u/awesomerobot']",
|
||||||
|
"avatar link contains href (is tabbable)"
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Moderator Viewing Group", async function (assert) {
|
test("Moderator Viewing Group", async function (assert) {
|
||||||
|
|
|
@ -62,5 +62,12 @@ acceptance("User Drafts", function (needs) {
|
||||||
),
|
),
|
||||||
"shows the excerpt"
|
"shows the excerpt"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert.ok(
|
||||||
|
query(".user-stream-item:nth-child(2) a.avatar-link").href.endsWith(
|
||||||
|
"/u/eviltrout"
|
||||||
|
),
|
||||||
|
"has correct avatar link"
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -26,7 +26,7 @@ export default {
|
||||||
draft_key: "topic_280",
|
draft_key: "topic_280",
|
||||||
sequence: 0,
|
sequence: 0,
|
||||||
draft_username: "eviltrout",
|
draft_username: "eviltrout",
|
||||||
avatar_template: "/letter_avatar_proxy/v2/letter/p/a87d85/{size}.png",
|
avatar_template: "/user_avatar/localhost/eviltrout/{size}/2_1.png",
|
||||||
data: '{"reply":"The last reply to this topic was 6 months ago. Your reply will bump the topic to the top of its list.","action":"reply","categoryId":8,"archetypeId":"regular","metaData":null,"composerTime":139499,"typingTime":6100}',
|
data: '{"reply":"The last reply to this topic was 6 months ago. Your reply will bump the topic to the top of its list.","action":"reply","categoryId":8,"archetypeId":"regular","metaData":null,"composerTime":139499,"typingTime":6100}',
|
||||||
topic_id: 280,
|
topic_id: 280,
|
||||||
username: "zogstrip",
|
username: "zogstrip",
|
||||||
|
|
|
@ -26,6 +26,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.user-stream-item__header {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-stream-item__details {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.type,
|
.type,
|
||||||
span.name {
|
span.name {
|
||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
|
@ -34,9 +43,10 @@
|
||||||
.time,
|
.time,
|
||||||
.delete-info,
|
.delete-info,
|
||||||
.draft-type {
|
.draft-type {
|
||||||
float: right;
|
line-height: var(--line-height-small);
|
||||||
color: var(--primary-medium);
|
color: var(--primary-medium);
|
||||||
font-size: $font-down-2;
|
font-size: $font-down-2;
|
||||||
|
padding-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notification .time {
|
.notification .time {
|
||||||
|
@ -44,30 +54,21 @@
|
||||||
float: none;
|
float: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.draft-type {
|
|
||||||
clear: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.delete-info .d-icon {
|
.delete-info .d-icon {
|
||||||
font-size: $font-0;
|
font-size: $font-0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.expand-item,
|
.expand-item,
|
||||||
.collapse-item {
|
.collapse-item {
|
||||||
float: right;
|
|
||||||
margin-right: 0.5em;
|
margin-right: 0.5em;
|
||||||
line-height: $line-height-small;
|
margin-left: 0.25em;
|
||||||
|
line-height: var(--line-height-small);
|
||||||
|
padding-top: 3px;
|
||||||
color: var(--primary-medium);
|
color: var(--primary-medium);
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar-link {
|
.avatar-link {
|
||||||
float: left;
|
margin-right: 0.5em;
|
||||||
margin-right: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
@include ellipsis;
|
|
||||||
display: block;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.name {
|
.name {
|
||||||
|
@ -81,10 +82,8 @@
|
||||||
padding: 3px 5px 5px 5px;
|
padding: 3px 5px 5px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remove-bookmark,
|
|
||||||
.remove-draft {
|
.remove-draft {
|
||||||
float: right;
|
float: right;
|
||||||
margin-top: -4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.notification {
|
.notification {
|
||||||
|
|
Loading…
Reference in New Issue