tangled
alpha
login
or
join now
nonbinary.computer
/
weaver
atproto blogging
24
fork
atom
overview
issues
2
pulls
pipelines
basic aria labels
Orual
1 month ago
b981b1a5
f51cda4a
+43
-9
10 changed files
expand all
collapse all
unified
split
crates
weaver-app
src
components
editor
component.rs
image_upload.rs
publish.rs
report.rs
sync.rs
toolbar.rs
login.rs
weaver-renderer
src
atproto
writer.rs
base_html.rs
static_site
writer.rs
+7
crates/weaver-app/src/components/editor/component.rs
···
1072
input {
1073
r#type: "text",
1074
class: "title-input",
0
1075
placeholder: "Entry title...",
1076
value: "{document.title()}",
1077
oninput: {
···
1090
input {
1091
r#type: "text",
1092
class: "path-input",
0
1093
placeholder: "url-slug",
1094
value: "{document.path()}",
1095
oninput: {
···
1110
"{tag}"
1111
button {
1112
class: "tag-remove",
0
1113
onclick: {
1114
let doc = document.clone();
1115
let tag_to_remove = tag.clone();
···
1124
input {
1125
r#type: "text",
1126
class: "tag-input",
0
1127
placeholder: "Add tag...",
1128
value: "{new_tag}",
1129
oninput: move |e| new_tag.set(e.value()),
···
1228
id: "{editor_id}",
1229
class: "editor-content",
1230
contenteditable: "true",
0
0
0
1231
1232
onkeydown: {
1233
let mut doc = document.clone();
···
1072
input {
1073
r#type: "text",
1074
class: "title-input",
1075
+
aria_label: "Entry title",
1076
placeholder: "Entry title...",
1077
value: "{document.title()}",
1078
oninput: {
···
1091
input {
1092
r#type: "text",
1093
class: "path-input",
1094
+
aria_label: "URL path",
1095
placeholder: "url-slug",
1096
value: "{document.path()}",
1097
oninput: {
···
1112
"{tag}"
1113
button {
1114
class: "tag-remove",
1115
+
aria_label: "Remove tag {tag}",
1116
onclick: {
1117
let doc = document.clone();
1118
let tag_to_remove = tag.clone();
···
1127
input {
1128
r#type: "text",
1129
class: "tag-input",
1130
+
aria_label: "Add tag",
1131
placeholder: "Add tag...",
1132
value: "{new_tag}",
1133
oninput: move |e| new_tag.set(e.value()),
···
1232
id: "{editor_id}",
1233
class: "editor-content",
1234
contenteditable: "true",
1235
+
role: "textbox",
1236
+
aria_multiline: "true",
1237
+
aria_label: "Document content",
1238
1239
onkeydown: {
1240
let mut doc = document.clone();
+1
crates/weaver-app/src/components/editor/image_upload.rs
···
108
label {
109
class: "toolbar-button",
110
title: "Image",
0
111
input {
112
r#type: "file",
113
accept: "image/*",
···
108
label {
109
class: "toolbar-button",
110
title: "Image",
111
+
aria_label: "Add image",
112
input {
113
r#type: "file",
114
accept: "image/*",
+5
-1
crates/weaver-app/src/components/editor/publish.rs
···
594
if show_dialog() {
595
div {
596
class: "publish-dialog-overlay",
0
0
0
597
onclick: close_dialog,
598
599
div {
600
class: "publish-dialog",
601
onclick: move |e| e.stop_propagation(),
602
603
-
h2 { "Publish Entry" }
604
605
if let Some(uri) = success_uri() {
606
{
···
663
input {
664
r#type: "text",
665
class: "publish-input",
0
666
placeholder: "Notebook title...",
667
value: "{notebook_title}",
668
oninput: move |e| notebook_title.set(e.value()),
···
594
if show_dialog() {
595
div {
596
class: "publish-dialog-overlay",
597
+
role: "dialog",
598
+
aria_modal: "true",
599
+
aria_labelledby: "publish-dialog-title",
600
onclick: close_dialog,
601
602
div {
603
class: "publish-dialog",
604
onclick: move |e| e.stop_propagation(),
605
606
+
h2 { id: "publish-dialog-title", "Publish Entry" }
607
608
if let Some(uri) = success_uri() {
609
{
···
666
input {
667
r#type: "text",
668
class: "publish-input",
669
+
aria_label: "Notebook title",
670
placeholder: "Notebook title...",
671
value: "{notebook_title}",
672
oninput: move |e| notebook_title.set(e.value()),
+5
-1
crates/weaver-app/src/components/editor/report.rs
···
140
if show_dialog() {
141
div {
142
class: "report-dialog-overlay",
0
0
0
143
onclick: close_dialog,
144
145
div {
146
class: "report-dialog",
147
onclick: move |e| e.stop_propagation(),
148
149
-
h2 { "Report a Bug" }
150
151
div { class: "report-section",
152
label { "Describe the issue:" }
153
textarea {
154
class: "report-comment",
0
155
placeholder: "What happened? What did you expect?",
156
value: "{comment}",
157
oninput: move |e| comment.set(e.value()),
···
140
if show_dialog() {
141
div {
142
class: "report-dialog-overlay",
143
+
role: "dialog",
144
+
aria_modal: "true",
145
+
aria_labelledby: "report-dialog-title",
146
onclick: close_dialog,
147
148
div {
149
class: "report-dialog",
150
onclick: move |e| e.stop_propagation(),
151
152
+
h2 { id: "report-dialog-title", "Report a Bug" }
153
154
div { class: "report-section",
155
label { "Describe the issue:" }
156
textarea {
157
class: "report-comment",
158
+
aria_label: "Describe the issue",
159
placeholder: "What happened? What did you expect?",
160
value: "{comment}",
161
oninput: move |e| comment.set(e.value()),
+2
crates/weaver-app/src/components/editor/sync.rs
···
1824
div {
1825
class: "{class}",
1826
title: "{title}",
0
0
1827
onclick: on_sync_click,
1828
onpointerdown: on_pointer_down,
1829
onpointerup: on_pointer_up,
···
1824
div {
1825
class: "{class}",
1826
title: "{title}",
1827
+
role: "status",
1828
+
aria_live: "polite",
1829
onclick: on_sync_click,
1830
onpointerdown: on_pointer_down,
1831
onpointerup: on_pointer_up,
+16
-1
crates/weaver-app/src/components/editor/toolbar.rs
···
13
on_image: EventHandler<UploadedImage>,
14
) -> Element {
15
rsx! {
16
-
div { class: "editor-toolbar",
0
0
0
0
17
button {
18
class: "toolbar-button",
19
title: "Bold (Ctrl+B)",
0
20
onclick: move |_| on_format.call(FormatAction::Bold),
21
"B"
22
}
23
button {
24
class: "toolbar-button",
25
title: "Italic (Ctrl+I)",
0
26
onclick: move |_| on_format.call(FormatAction::Italic),
27
"I"
28
}
29
button {
30
class: "toolbar-button",
31
title: "Strikethrough",
0
32
onclick: move |_| on_format.call(FormatAction::Strikethrough),
33
"S"
34
}
35
button {
36
class: "toolbar-button",
37
title: "Code",
0
38
onclick: move |_| on_format.call(FormatAction::Code),
39
"<>"
40
}
···
44
button {
45
class: "toolbar-button",
46
title: "Heading 1",
0
47
onclick: move |_| on_format.call(FormatAction::Heading(1)),
48
"H1"
49
}
50
button {
51
class: "toolbar-button",
52
title: "Heading 2",
0
53
onclick: move |_| on_format.call(FormatAction::Heading(2)),
54
"H2"
55
}
56
button {
57
class: "toolbar-button",
58
title: "Heading 3",
0
59
onclick: move |_| on_format.call(FormatAction::Heading(3)),
60
"H3"
61
}
···
65
button {
66
class: "toolbar-button",
67
title: "Bullet List",
0
68
onclick: move |_| on_format.call(FormatAction::BulletList),
69
"•"
70
}
71
button {
72
class: "toolbar-button",
73
title: "Numbered List",
0
74
onclick: move |_| on_format.call(FormatAction::NumberedList),
75
"1."
76
}
77
button {
78
class: "toolbar-button",
79
title: "Quote",
0
80
onclick: move |_| on_format.call(FormatAction::Quote),
81
"❝"
82
}
···
86
button {
87
class: "toolbar-button",
88
title: "Link",
0
89
onclick: move |_| on_format.call(FormatAction::Link),
90
"🔗"
91
}
···
13
on_image: EventHandler<UploadedImage>,
14
) -> Element {
15
rsx! {
16
+
div {
17
+
class: "editor-toolbar",
18
+
role: "toolbar",
19
+
aria_label: "Text formatting",
20
+
aria_orientation: "vertical",
21
button {
22
class: "toolbar-button",
23
title: "Bold (Ctrl+B)",
24
+
aria_label: "Bold (Ctrl+B)",
25
onclick: move |_| on_format.call(FormatAction::Bold),
26
"B"
27
}
28
button {
29
class: "toolbar-button",
30
title: "Italic (Ctrl+I)",
31
+
aria_label: "Italic (Ctrl+I)",
32
onclick: move |_| on_format.call(FormatAction::Italic),
33
"I"
34
}
35
button {
36
class: "toolbar-button",
37
title: "Strikethrough",
38
+
aria_label: "Strikethrough",
39
onclick: move |_| on_format.call(FormatAction::Strikethrough),
40
"S"
41
}
42
button {
43
class: "toolbar-button",
44
title: "Code",
45
+
aria_label: "Code",
46
onclick: move |_| on_format.call(FormatAction::Code),
47
"<>"
48
}
···
52
button {
53
class: "toolbar-button",
54
title: "Heading 1",
55
+
aria_label: "Heading 1",
56
onclick: move |_| on_format.call(FormatAction::Heading(1)),
57
"H1"
58
}
59
button {
60
class: "toolbar-button",
61
title: "Heading 2",
62
+
aria_label: "Heading 2",
63
onclick: move |_| on_format.call(FormatAction::Heading(2)),
64
"H2"
65
}
66
button {
67
class: "toolbar-button",
68
title: "Heading 3",
69
+
aria_label: "Heading 3",
70
onclick: move |_| on_format.call(FormatAction::Heading(3)),
71
"H3"
72
}
···
76
button {
77
class: "toolbar-button",
78
title: "Bullet List",
79
+
aria_label: "Bullet List",
80
onclick: move |_| on_format.call(FormatAction::BulletList),
81
"•"
82
}
83
button {
84
class: "toolbar-button",
85
title: "Numbered List",
86
+
aria_label: "Numbered List",
87
onclick: move |_| on_format.call(FormatAction::NumberedList),
88
"1."
89
}
90
button {
91
class: "toolbar-button",
92
title: "Quote",
93
+
aria_label: "Quote",
94
onclick: move |_| on_format.call(FormatAction::Quote),
95
"❝"
96
}
···
100
button {
101
class: "toolbar-button",
102
title: "Link",
103
+
aria_label: "Link",
104
onclick: move |_| on_format.call(FormatAction::Link),
105
"🔗"
106
}
+1
crates/weaver-app/src/components/login.rs
···
100
}
101
DialogTitle { "Sign In with AT Protocol" }
102
Input {
0
103
oninput: move |e: FormEvent| handle_input.set(e.value()),
104
onkeypress: move |k: KeyboardEvent| {
105
if k.key() == Key::Enter {
···
100
}
101
DialogTitle { "Sign In with AT Protocol" }
102
Input {
103
+
aria_label: "Handle",
104
oninput: move |e: FormEvent| handle_input.set(e.value()),
105
onkeypress: move |k: KeyboardEvent| {
106
if k.key() == Key::Enter {
+2
-2
crates/weaver-renderer/src/atproto/writer.rs
···
487
}
488
TaskListMarker(checked) => {
489
if checked {
490
-
self.write("<input disabled=\"\" type=\"checkbox\" checked=\"\"/>\n")?;
491
} else {
492
-
self.write("<input disabled=\"\" type=\"checkbox\"/>\n")?;
493
}
494
}
495
WeaverBlock(text) => {
···
487
}
488
TaskListMarker(checked) => {
489
if checked {
490
+
self.write("<input disabled=\"\" type=\"checkbox\" checked=\"\" aria-label=\"Completed task\"/>\n")?;
491
} else {
492
+
self.write("<input disabled=\"\" type=\"checkbox\" aria-label=\"Incomplete task\"/>\n")?;
493
}
494
}
495
WeaverBlock(text) => {
+2
-2
crates/weaver-renderer/src/base_html.rs
···
157
self.write("</a></sup>")?;
158
}
159
TaskListMarker(true) => {
160
-
self.write("<input disabled=\"\" type=\"checkbox\" checked=\"\"/>\n")?;
161
}
162
TaskListMarker(false) => {
163
-
self.write("<input disabled=\"\" type=\"checkbox\"/>\n")?;
164
}
165
WeaverBlock(_text) => {}
166
}
···
157
self.write("</a></sup>")?;
158
}
159
TaskListMarker(true) => {
160
+
self.write("<input disabled=\"\" type=\"checkbox\" checked=\"\" aria-label=\"Completed task\"/>\n")?;
161
}
162
TaskListMarker(false) => {
163
+
self.write("<input disabled=\"\" type=\"checkbox\" aria-label=\"Incomplete task\"/>\n")?;
164
}
165
WeaverBlock(_text) => {}
166
}
+2
-2
crates/weaver-renderer/src/static_site/writer.rs
···
546
self.pending_footnote = Some((name.into_static(), number));
547
}
548
TaskListMarker(true) => {
549
-
self.write("<input disabled=\"\" type=\"checkbox\" checked=\"\"/>\n")?;
550
}
551
TaskListMarker(false) => {
552
-
self.write("<input disabled=\"\" type=\"checkbox\"/>\n")?;
553
}
554
WeaverBlock(text) => {
555
// Buffer WeaverBlock content for parsing on End
···
546
self.pending_footnote = Some((name.into_static(), number));
547
}
548
TaskListMarker(true) => {
549
+
self.write("<input disabled=\"\" type=\"checkbox\" checked=\"\" aria-label=\"Completed task\"/>\n")?;
550
}
551
TaskListMarker(false) => {
552
+
self.write("<input disabled=\"\" type=\"checkbox\" aria-label=\"Incomplete task\"/>\n")?;
553
}
554
WeaverBlock(text) => {
555
// Buffer WeaverBlock content for parsing on End