A11Y: makes user notifications list more accessible (#11992)

Previous markup used to be

```
<div>
  <div>
    <li>
```

Instead we will now have:

```
<ul>
  <li>
    <div>
```

Note this commit also adds two things:
- ability to override tagName of a widget when attaching it
- ability to pass opts and otherOpts to {{attach}}, it could be useful in templates but is mostly useful to test `tagName` for now
This commit is contained in:
Joffrey JAFFEUX 2021-02-08 08:45:14 +01:00 committed by GitHub
parent dbb015f03e
commit 8957e4d9d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 43 additions and 6 deletions

View File

@ -3,6 +3,8 @@ import { dateNode } from "discourse/helpers/node";
import { h } from "virtual-dom";
createWidget("large-notification-item", {
tagName: "li",
buildClasses(attrs) {
const result = ["item", "notification", "large-notification"];
if (!attrs.get("read")) {
@ -21,7 +23,10 @@ createWidget("large-notification-item", {
`${notificationName.dasherize()}-notification-item`,
attrs,
{},
{ fallbackWidgetName: "default-notification-item" }
{
fallbackWidgetName: "default-notification-item",
tagName: "div",
}
),
h("span.time", dateNode(attrs.created_at)),
];
@ -29,6 +34,8 @@ createWidget("large-notification-item", {
});
export default createWidget("user-notifications-large", {
tagName: "ul.notifications.large-notifications",
html(attrs) {
const notifications = attrs.notifications;
const username = notifications.findArgs.username;

View File

@ -265,6 +265,11 @@ export default class Widget {
const result = new WidgetClass(attrs, this.register, opts);
result.parentWidget = this;
result.dirtyKeys = this.dirtyKeys;
if (otherOpts.tagName) {
result.tagName = otherOpts.tagName;
}
return result;
} else {
throw new Error(

View File

@ -418,4 +418,23 @@ discourseModule("Integration | Component | Widget | base", function (hooks) {
assert.equal(queryAll("div.test").text(), "Hello eviltrout");
},
});
componentTest("tagName", {
template: hbs`{{mount-widget widget="tag-name-override-test"}}`,
beforeEach() {
createWidget("test-override", { tagName: "div.not-override" });
createWidget("tag-name-override-test", {
template: widgetHbs`{{attach widget="test-override" attrs=attrs otherOpts=(hash tagName="section.override")}}`,
});
},
test(assert) {
assert.ok(
queryAll("section.override").length,
"renders container with overrided tagName"
);
},
});
});

View File

@ -705,6 +705,10 @@
}
}
.large-notifications {
margin: 0;
}
.large-notification {
display: flex;
align-items: center;

View File

@ -90,11 +90,13 @@ function mustacheValue(node, state) {
node.hash.pairs.find((p) => p.key === "widget")
);
let attrs = node.hash.pairs.find((p) => p.key === "attrs");
if (attrs) {
return `this.attach(${widgetName}, ${argValue(attrs)})`;
}
return `this.attach(${widgetName}, attrs)`;
const attrs = node.hash.pairs.find((p) => p.key === "attrs");
const opts = node.hash.pairs.find((p) => p.key === "opts");
const otherOpts = node.hash.pairs.find((p) => p.key === "otherOpts");
return `this.attach(${widgetName}, ${attrs ? argValue(attrs) : attrs}, ${
opts ? argValue(opts) : opts
}, ${otherOpts ? argValue(otherOpts) : otherOpts})`;
break;
case "yield":