diff --git a/app/assets/stylesheets/utilities.css b/app/assets/stylesheets/utilities.css
index 62f98c2c5..a9fa653f4 100644
--- a/app/assets/stylesheets/utilities.css
+++ b/app/assets/stylesheets/utilities.css
@@ -263,6 +263,7 @@
}
/* Accessibility */
+.visually-hidden,
.for-screen-reader {
block-size: 1px;
clip-path: inset(50%);
diff --git a/app/helpers/avatars_helper.rb b/app/helpers/avatars_helper.rb
index a3ebd619a..2a6d927f4 100644
--- a/app/helpers/avatars_helper.rb
+++ b/app/helpers/avatars_helper.rb
@@ -10,8 +10,10 @@ module AvatarsHelper
AVATAR_COLORS[Zlib.crc32(user.to_param) % AVATAR_COLORS.size]
end
- def avatar_tag(user, **options)
- link_to user_path(user), title: user.name, class: "btn avatar", data: { turbo_frame: "_top" } do
+ def avatar_tag(user, hidden_for_screen_reader: false, **options)
+ link_to user_path(user), title: user.name, class: "btn avatar", data: { turbo_frame: "_top" },
+ aria: { hidden: hidden_for_screen_reader, label: user.name },
+ tabindex: hidden_for_screen_reader ? -1 : nil do
avatar_image_tag(user, **options)
end
end
diff --git a/app/helpers/messages_helper.rb b/app/helpers/messages_helper.rb
index 0fc940b37..bac9af789 100644
--- a/app/helpers/messages_helper.rb
+++ b/app/helpers/messages_helper.rb
@@ -3,6 +3,7 @@ module MessagesHelper
turbo_frame_tag dom_id(bubble, :messages),
class: "comments align-center center borderless margin flex flex-column gap-half",
style: "--bubble-color: <%= bubble.color %>",
+ role: "group", aria: { label: "Messages" },
data: {
controller: "created-by-current-user",
created_by_current_user_mine_class: "comment--mine"
diff --git a/app/javascript/controllers/reaction_delete_controller.js b/app/javascript/controllers/reaction_delete_controller.js
index f4672d693..3c89ec00d 100644
--- a/app/javascript/controllers/reaction_delete_controller.js
+++ b/app/javascript/controllers/reaction_delete_controller.js
@@ -6,14 +6,15 @@ export default class extends Controller {
static values = { reacterId: Number }
connect() {
- if (this.#currentUserIsreacter) {
+ if (this.#currentUserIsReacter) {
this.#setAccessibleAttributes()
}
}
reveal() {
- if (this.#currentUserIsreacter) {
+ if (this.#currentUserIsReacter) {
this.element.classList.toggle(this.revealClass)
+ this.contentTarget.ariaExpanded = this.element.classList.contains(this.revealClass)
this.buttonTarget.focus()
}
}
@@ -23,11 +24,12 @@ export default class extends Controller {
}
#setAccessibleAttributes() {
- this.contentTarget.setAttribute('tabindex', '0')
- this.contentTarget.setAttribute('aria-describedby', 'delete_reaction_accessible_label')
+ this.contentTarget.role = "button"
+ this.contentTarget.tabIndex = 0
+ this.contentTarget.ariaExpanded = false
}
- get #currentUserIsreacter() {
+ get #currentUserIsReacter() {
return Current.user.id === this.reacterIdValue
}
}
diff --git a/app/views/boosts/_boosts.html.erb b/app/views/boosts/_boosts.html.erb
index a8055b5ac..d6361200f 100644
--- a/app/views/boosts/_boosts.html.erb
+++ b/app/views/boosts/_boosts.html.erb
@@ -1,4 +1,5 @@
<%= tag.div class: "bubble__detail bubble__boosts",
+ role: "group", aria: { label: "Boosts" },
data: {
controller: "animation toggle-class",
animation_play_class: "boosting",
@@ -8,7 +9,7 @@
<%= form_with url: bucket_bubble_boosts_path(bubble.bucket, bubble),
class: "boost__form",
data: { action: "toggle-class#toggle" } do %>
- <%= text_field_tag :boost_count, bubble.boosts_count, min: 1, class: "input borderless boost__input", autocomplete: "off" %>
- <%= tag.button "+", class: "btn btn--plain boost__btn", type: :submit %>
+ <%= text_field_tag :boost_count, bubble.boosts_count, min: 1, class: "input borderless boost__input", autocomplete: "off", aria: { label: "Boost count" } %>
+ <%= tag.button "+", class: "btn btn--plain boost__btn", type: :submit, aria: { label: "Boost" } %>
<% end %>
<% end %>
diff --git a/app/views/bubbles/_assignments.html.erb b/app/views/bubbles/_assignments.html.erb
index 6bdc12c6d..999afd098 100644
--- a/app/views/bubbles/_assignments.html.erb
+++ b/app/views/bubbles/_assignments.html.erb
@@ -1,8 +1,8 @@
<% bubble.assignees.each do |assignee| %>
- <%= assignee.name %>
- <%= avatar_image_tag assignee, loading: :lazy, class: "avatar flex-item-no-shrink" %>
+ <%= assignee.name %>
+ <%= avatar_image_tag assignee, loading: :lazy, class: "avatar flex-item-no-shrink", aria: { hidden: true } %>
Assigned to <%= assignee.name %>
diff --git a/app/views/bubbles/_bubble.html.erb b/app/views/bubbles/_bubble.html.erb
index 841ac2dbf..a5017954f 100644
--- a/app/views/bubbles/_bubble.html.erb
+++ b/app/views/bubbles/_bubble.html.erb
@@ -1,19 +1,22 @@
<% cache bubble do %>
-
"
- style="view-transition-name: bubble-<%= bubble.id -%>; --bubble-color: <%= bubble.color %>; <%= bubble_rotation(bubble) %>"
- data-bubble-size-target="bubble"
- data-activity-score="<%= bubble.activity_score %>"
- data-activity-score-at="<%= bubble.activity_score_at.to_i %>"
- data-controller="animation upload-preview"
- data-animation-play-class="bubble--wobble"
- data-animation-play-on-load-value="true"
- data-action="mouseover->animation#play">
-
+ <%= tag.div class: [ "bubble", drafted: bubble.drafted?, popped: bubble.popped? ],
+ style: "view-transition-name: bubble-#{bubble.id}; --bubble-color: #{bubble.color}; #{bubble_rotation(bubble)}",
+ role: "group", aria: { label: bubble.title },
+ data: {
+ bubble_size_target: "bubble",
+ activity_score: bubble.activity_score,
+ activity_score_at: bubble.activity_score_at.to_i,
+ controller: "animation upload-preview",
+ animation_play_class: "bubble--wobble",
+ animation_play_on_load_value: true,
+ action: "mouseover->animation#play" } do %>
-
+
<% if bubble.published? %>
<%= turbo_frame_tag bubble, :edit do %>
- <%= link_to bubble_title(bubble), edit_bucket_bubble_path(bubble.bucket, bubble), class: "txt-undecorated bubble__title-rendered" %>
+ <%= link_to bubble_title(bubble), edit_bucket_bubble_path(bubble.bucket, bubble),
+ class: "txt-undecorated bubble__title-rendered",
+ role: "button", aria: { label: "Edit name: #{bubble.title}" } %>
<% end %>
<% else %>
<%= form_with model: bubble, url: bucket_bubble_path(bubble.bucket, bubble), id: "bubble_form", data: { controller: "auto-save" } do |form| %>
@@ -30,14 +33,16 @@
- <%= link_to bucket_bubble_path(bubble.bucket, bubble), class: "bubble__link" do %>
- <%= bubble.title %>
- <% end %>
+
+ <%= link_to bucket_bubble_path(bubble.bucket, bubble), class: "bubble__link" do %>
+ <%= bubble.title %>
+ <% end %>
+
<%= render "bubbles/assignments", bubble: bubble %>
<%= render "bubbles/boosts", bubble: bubble %>
<%= render "bubbles/comments", bubble: bubble %>
<%= render "bubbles/date", bubble: bubble %>
<%= render "bubbles/image", bubble: bubble %>
-
+ <% end %>
<% end %>
diff --git a/app/views/bubbles/_comments.html.erb b/app/views/bubbles/_comments.html.erb
index b2d3dad5d..6a60cdaeb 100644
--- a/app/views/bubbles/_comments.html.erb
+++ b/app/views/bubbles/_comments.html.erb
@@ -1,5 +1,6 @@
<% if bubble.messages.comments.any? %>
-<% end %>
\ No newline at end of file
+<% end %>
diff --git a/app/views/bubbles/_date.html.erb b/app/views/bubbles/_date.html.erb
index b9fb46a61..bbcc9d4c1 100644
--- a/app/views/bubbles/_date.html.erb
+++ b/app/views/bubbles/_date.html.erb
@@ -1,9 +1,9 @@
<% if bubble.due_on.present? %>
<%= form_with model: bubble, url: bucket_bubble_path(bubble.bucket, bubble), data: { controller: "form" } do |form| %>
+ Change the due date
<%= html_escape bubble.due_on.strftime("%b %d").html_safe %>
<%= form.date_field :due_on, class: "input input--hidden", data: { action: "change->form#submit click->form#showPicker" } %>
- Change the due date
<% end %>
<% end %>
diff --git a/app/views/bubbles/_image.html.erb b/app/views/bubbles/_image.html.erb
index f92dfc107..8cab87923 100644
--- a/app/views/bubbles/_image.html.erb
+++ b/app/views/bubbles/_image.html.erb
@@ -1,3 +1,3 @@
- <%= image_tag bubble.image.presence || "", data: { upload_preview_target: "image" } %>
+ <%= image_tag bubble.image.presence || "", data: { upload_preview_target: "image" }, aria: { hidden: true } %>
diff --git a/app/views/bubbles/list/_bubble.html.erb b/app/views/bubbles/list/_bubble.html.erb
index 7a6b4e2b4..2afa6d87f 100644
--- a/app/views/bubbles/list/_bubble.html.erb
+++ b/app/views/bubbles/list/_bubble.html.erb
@@ -1,6 +1,7 @@
" style="--bubble-color: <%= bubble.color %>; <%= bubble_rotation(bubble) %>"
data-controller="animation" data-animation-play-class="bubble--wobble" data-animation-play-on-load-value="true" data-action="mouseover->animation#play">
- <%= link_to bucket_bubble_path(bubble.bucket, bubble), class: "flex-item-no-shrink" do %>
+ <%= link_to bucket_bubble_path(bubble.bucket, bubble), class: "flex-item-no-shrink",
+ aria: { hidden: true }, tabindex: -1 do %>
<% end %>
@@ -14,13 +15,18 @@
<% end %>
<% if bubble.messages.comments.many? %>
- (<%= bubble.messages.comments.count %>)
+
+ (<%= bubble.messages.comments.count %>)
+ <%= pluralize(bubble.messages.comments.count, "comment") %>
+
<% end %>
-
+
<% bubble.assignees.each do |assignee| %>
- <%= link_to bubbles_path(@filter.as_params.merge(assignee_ids: [ assignee.id ])), class: "btn avatar", style: "font-size: 0.4em;" do %>
- <%= avatar_image_tag assignee, loading: :lazy %>
+ <%= link_to bubbles_path(@filter.as_params.merge(assignee_ids: [ assignee.id ])),
+ class: "btn avatar", style: "font-size: 0.4em;",
+ aria: { label: assignee.name } do %>
+ <%= avatar_image_tag assignee, loading: :lazy, aria: { hidden: true } %>
<% end %>
<% end %>
@@ -31,7 +37,8 @@
<% if bubble.due_on.present? %>
- <%= local_datetime_tag bubble.due_on, style: :shortdate %>
+ Due on <%= local_datetime_tag bubble.due_on, style: :shortdate %>
+ <%= local_datetime_tag bubble.due_on, style: :shortdate %>
<% end %>
@@ -41,4 +48,4 @@
<%= render "bubbles/tags", bubble: bubble %>
-
\ No newline at end of file
+
diff --git a/app/views/bubbles/list/_divider.html.erb b/app/views/bubbles/list/_divider.html.erb
index d60b67de8..96cc95754 100644
--- a/app/views/bubbles/list/_divider.html.erb
+++ b/app/views/bubbles/list/_divider.html.erb
@@ -1,10 +1,10 @@
Drag up or down
-
+
<%= image_tag "drag.svg", aria: { hidden: true }, size: 24, class: "colorize--white" %>
10 Bubbled up
-
+
diff --git a/app/views/bubbles/show.html.erb b/app/views/bubbles/show.html.erb
index 9c618e4d5..5262eef6f 100644
--- a/app/views/bubbles/show.html.erb
+++ b/app/views/bubbles/show.html.erb
@@ -56,11 +56,11 @@
<%= form_with model: @bubble, url: bucket_bubble_path(@bubble.bucket, @bubble), data: { controller: "form" } do |form| %>
<%= image_tag "picture-add.svg", aria: { hidden: true }, size: 24 %>
- Background
- <%= form.file_field :image, class: "input",
+ Background
+ <%= form.file_field :image, class: "input visually-hidden",
accept: "image/png, image/jpeg, image/jpg, image/webp",
- data: { action: "upload-preview#previewImage form#submit", upload_preview_target: "input" },
- hidden: true %>
+ aria: { label: "Upload background image" },
+ data: { action: "upload-preview#previewImage form#submit", upload_preview_target: "input" } %>
<% end %>
<% end %>
diff --git a/app/views/buckets/_bucket.html.erb b/app/views/buckets/_bucket.html.erb
index 16550c55f..d6a589ac5 100644
--- a/app/views/buckets/_bucket.html.erb
+++ b/app/views/buckets/_bucket.html.erb
@@ -1,5 +1,7 @@
- <%= link_to bubbles_path(bucket_ids: [ bucket ]), class: "border border-radius margin-block-end-half bubbles__container flex justify-center align-center position-relative" do %>
+ <%= link_to bubbles_path(bucket_ids: [ bucket ]),
+ class: "border border-radius margin-block-end-half bubbles__container flex justify-center align-center position-relative",
+ aria: { hidden: true }, tabindex: -1 do %>
<% bucket.bubbles.active.published_or_drafted_by(Current.user).ordered_by_activity.limit(10).each do |bubble| %>
" style="--bubble-color: <%= bubble.color %>; <%= bubble_rotation(bubble) %>"
diff --git a/app/views/buckets/index.html.erb b/app/views/buckets/index.html.erb
index 9197893aa..41e8cd81a 100644
--- a/app/views/buckets/index.html.erb
+++ b/app/views/buckets/index.html.erb
@@ -22,11 +22,11 @@
<% end %>
-
+
<%= render @buckets, cached: true %>
-
-
+
<%= render "notifications/tray" %>
diff --git a/app/views/comments/_body.html.erb b/app/views/comments/_body.html.erb
index 14b976386..c9cebe0ff 100644
--- a/app/views/comments/_body.html.erb
+++ b/app/views/comments/_body.html.erb
@@ -2,12 +2,16 @@
<%= turbo_frame_tag dom_id(comment) do %>
-
Press enter to delete this reaction
-<% end %>
\ No newline at end of file
+<% end %>
diff --git a/app/views/comments/reactions/_reactions.html.erb b/app/views/comments/reactions/_reactions.html.erb
index 9f4fe4b4b..67bee5e9c 100644
--- a/app/views/comments/reactions/_reactions.html.erb
+++ b/app/views/comments/reactions/_reactions.html.erb
@@ -7,7 +7,7 @@
<%= turbo_frame_tag comment, :new_reaction do %>
- <%= link_to new_bucket_bubble_comment_reaction_path(comment.bubble.bucket, comment.bubble, comment),
+ <%= link_to new_bucket_bubble_comment_reaction_path(comment.bubble.bucket, comment.bubble, comment), role: "button",
class: "txt-small btn reaction__action", action: "soft-keyboard#open" do %>
<%= image_tag "reaction.svg", size: 20, aria: { hidden: "true" } %>
Add a reaction
@@ -15,4 +15,4 @@
<% end %>
-<% end %>
\ No newline at end of file
+<% end %>
diff --git a/app/views/comments/reactions/new.html.erb b/app/views/comments/reactions/new.html.erb
index e2ca711d3..e22cd1db8 100644
--- a/app/views/comments/reactions/new.html.erb
+++ b/app/views/comments/reactions/new.html.erb
@@ -1,14 +1,15 @@
<%= turbo_frame_tag dom_id(@comment, :new_reaction) do %>
<%= form_with url: bucket_bubble_comment_reactions_path(@comment.bubble.bucket, @comment.bubble, @comment),
class: "reaction reaction__form flex-inline postion--relative max-width align-center fill-white gap expanded",
+ html: { aria: { label: "New reaction" } },
data: { controller: "form", turbo_frame: dom_id(@comment, :reacting), action: "keydown.esc->form#cancel" } do |form| %>
-
+
<%= avatar_tag Current.user %>
- <%= Current.user.name %>
<%= form.text_field :content, name: "reaction[content]", autofocus: true, autocomplete: "off", autocorrect: "off", maxlength: 16,
- required: true, pattern: /\S+.*/, class: "input reaction__input txt-small" %>
+ required: true, pattern: /\S+.*/, class: "input reaction__input txt-small",
+ aria: { label: "Add a reaction" } %>
<%= form.button class: "btn btn--reversed", type: "submit" do %>
@@ -16,10 +17,10 @@
Submit
<% end %>
- <%= link_to bucket_bubble_comment_reactions_path(@comment.bubble.bucket, @comment.bubble, @comment),
+ <%= link_to bucket_bubble_comment_reactions_path(@comment.bubble.bucket, @comment.bubble, @comment), role: "button",
data: { turbo_frame: dom_id(@comment, :reactions), form_target: "cancel" }, class: "btn btn--negative" do %>
<%= image_tag "minus.svg", aria: { hidden: "true" } %>
Cancel
<% end %>
<% end %>
-<% end %>
\ No newline at end of file
+<% end %>
diff --git a/app/views/filters/_assignees.html.erb b/app/views/filters/_assignees.html.erb
index ddf1399d0..8dfdc7f9d 100644
--- a/app/views/filters/_assignees.html.erb
+++ b/app/views/filters/_assignees.html.erb
@@ -11,20 +11,22 @@
-
+
<%= form_with url: bubbles_path, method: :get, class: "flex flex-column full-width popup__list",
data: { controller: "form" } do |form| %>
<% filter.as_params.except(:assignee_ids, :assignment_status).each do |key, value| %>
<%= filter_hidden_field_tag key, value %>
<% end %>
-
+
<%= link_to bubbles_path(filter.as_params.except(:assignee_ids, :assignment_status)), class: "btn popup__item" do %>
Clear all
<% end %>
-
+
<% Current.account.users.active.order(:name).each do |user| %>
<% end %>
<% end %>
-
\ No newline at end of file
+
diff --git a/app/views/filters/_buckets.html.erb b/app/views/filters/_buckets.html.erb
index 32c9fee56..1142a9c96 100644
--- a/app/views/filters/_buckets.html.erb
+++ b/app/views/filters/_buckets.html.erb
@@ -10,31 +10,34 @@
-
+
<%= form_with url: bubbles_path, method: :get, class: "flex flex-column full-width popup__list",
data: { controller: "form" } do |form| %>
<% filter.as_params.except(:bucket_ids).each do |key, value| %>
<%= filter_hidden_field_tag key, value %>
<% end %>
-
+
<%= link_to bubbles_path(filter.as_params.except(:bucket_ids)), class: "btn popup__item" do %>
Clear all
<% end %>
-
+
<% filter.buckets.order(:name).each do |bucket| %>
<% end %>
<% end %>
-<% end %>
\ No newline at end of file
+<% end %>
diff --git a/app/views/filters/_creators.html.erb b/app/views/filters/_creators.html.erb
index aa8befe24..83fc7c69f 100644
--- a/app/views/filters/_creators.html.erb
+++ b/app/views/filters/_creators.html.erb
@@ -12,42 +12,45 @@
+ aria-label="Added by…" aria-description="Added by…"
+ data-dialog-target="dialog" data-action="turbo:before-cache@document->dialog#close">
<%= form_with url: bubbles_path, method: :get, class: "flex flex-column full-width popup__list",
data: { controller: "form" } do |form| %>
<% filter.as_params.except(:creator_ids).each do |key, value| %>
<%= filter_hidden_field_tag key, value %>
<% end %>
-
+
<%= link_to bubbles_path(filter.as_params.except(:creator_ids)), class: "btn popup__item" do %>
Clear all
<% end %>
-
+
<% Current.account.users.active.without(Current.user).order(:name).each do |user| %>
<% end %>
<% end %>
-<% end %>
\ No newline at end of file
+<% end %>
diff --git a/app/views/filters/_dialog.html.erb b/app/views/filters/_dialog.html.erb
index 73e764c79..611549072 100644
--- a/app/views/filters/_dialog.html.erb
+++ b/app/views/filters/_dialog.html.erb
@@ -1,4 +1,4 @@
-
+
@@ -25,7 +25,7 @@
<%= search_field_tag "terms[]", nil, class: "input full-width", placeholder: "By keyword…", id: nil %>
- Apply
+ Apply
<%= image_tag "arrow-right.svg", aria: { hidden: true }, size: 24 %>
<% end %>
@@ -37,127 +37,130 @@
<% end %>
-
<% end %>
diff --git a/app/views/filters/_filter.html.erb b/app/views/filters/_filter.html.erb
index bcf6cd7da..d76e0a232 100644
--- a/app/views/filters/_filter.html.erb
+++ b/app/views/filters/_filter.html.erb
@@ -1,6 +1,8 @@
<% cache_if filter.cacheable?, filter do %>
- <%= link_to bubbles_path(**filter.as_params), class: "border border-radius margin-block-end-half bubbles__container flex justify-center align-center position-relative" do %>
+ <%= link_to bubbles_path(**filter.as_params),
+ class: "border border-radius margin-block-end-half bubbles__container flex justify-center align-center position-relative",
+ aria: { hidden: true }, tabindex: -1 do %>
<% filter.bubbles.ordered_by_activity.limit(10).each do |bubble| %>
" style="--bubble-color: <%= bubble.color %>; <%= bubble_rotation(bubble) %>"
diff --git a/app/views/filters/_indexed_by.html.erb b/app/views/filters/_indexed_by.html.erb
index f42324bdf..34401948a 100644
--- a/app/views/filters/_indexed_by.html.erb
+++ b/app/views/filters/_indexed_by.html.erb
@@ -5,7 +5,9 @@
-
+
<%= form_with url: bubbles_path, method: :get, class: "flex flex-column full-width popup__list",
data: { controller: "form" } do |form| %>
@@ -35,4 +37,4 @@
<% end %>
<% end %>
-
\ No newline at end of file
+
diff --git a/app/views/filters/_stages.html.erb b/app/views/filters/_stages.html.erb
index 0e6c01d3a..0583a8ffa 100644
--- a/app/views/filters/_stages.html.erb
+++ b/app/views/filters/_stages.html.erb
@@ -10,35 +10,38 @@
-
+
<%= form_with url: bubbles_path, method: :get, class: "flex flex-column full-width popup__list",
data: { controller: "form" } do |form| %>
<% filter.as_params.except(:stage_ids).each do |key, value| %>
<%= filter_hidden_field_tag key, value %>
<% end %>
-
+
<%= link_to bubbles_path(filter.as_params.except(:stage_ids)), class: "btn popup__item" do %>
Clear all
<% end %>
-
+
<% Current.account.workflows.order(:name).each do |workflow| %>
-
-
- <% workflow.stages.order(:name).each do |stage| %>
+
+
+ <% workflow.stages.order(:name).each do |stage| %>
- <% end %>
+ <% end %>
<% end %>
<% end %>
-<% end %>
\ No newline at end of file
+<% end %>
diff --git a/app/views/filters/_tags.html.erb b/app/views/filters/_tags.html.erb
index 9e7d087f9..083e390cc 100644
--- a/app/views/filters/_tags.html.erb
+++ b/app/views/filters/_tags.html.erb
@@ -9,30 +9,33 @@
-
+
<%= form_with url: bubbles_path, method: :get, class: "flex flex-column full-width popup__list",
data: { controller: "form" } do |form| %>
<% filter.as_params.except(:tag_ids).each do |key, value| %>
<%= filter_hidden_field_tag key, value %>
<% end %>
-
+
<%= link_to bubbles_path(filter.as_params.except(:tag_ids)), class: "btn popup__item" do %>
Clear all
<% end %>
-
+
<% Current.account.tags.order(:title).each do |tag| %>
<% end %>
<% end %>
-
\ No newline at end of file
+