Merge pull request #5895 from consuldemocracy/aria_progressbar_name

Add ARIA labels to progressbars
This commit is contained in:
Javi Martín
2025-04-02 15:24:45 +02:00
committed by GitHub
13 changed files with 148 additions and 117 deletions

View File

@@ -27,6 +27,7 @@
@import "layout/**/*";
@import "machine_learning/**/*";
@import "management/**/*";
@import "milestones/**/*";
@import "moderation/**/*";
@import "polls/**/*";
@import "proposals/**/*";

View File

@@ -1,40 +1,3 @@
$progress-bar-background: #fef0e2;
$progress-bar-color: #fea230;
.tab-milestones {
.progress-bars {
margin-bottom: $line-height * 2;
margin-top: $line-height;
h5 {
font-size: rem-calc(24);
}
.progress {
background: $progress-bar-background;
border-radius: rem-calc(6);
position: relative;
}
.progress-meter {
background: $progress-bar-color;
border-radius: rem-calc(6);
}
.progress-meter-text {
color: color-pick-contrast($progress-bar-background);
right: 12px;
text-align: right;
transform: translate(0%, -50%);
}
.milestone-progress .row {
margin-bottom: calc($line-height / 2);
}
}
}
.tab-milestones .timeline li {
margin: 0 auto;
position: relative;

View File

@@ -0,0 +1,36 @@
$progress-bar-background: #fef0e2;
$progress-bar-color: #fea230;
.tab-milestones {
.progress-bars {
margin-bottom: $line-height * 2;
margin-top: $line-height;
h5 {
font-size: rem-calc(24);
}
.progress {
background: $progress-bar-background;
border-radius: rem-calc(6);
position: relative;
}
.progress-meter {
background: $progress-bar-color;
border-radius: rem-calc(6);
}
.progress-meter-text {
color: color-pick-contrast($progress-bar-background);
right: 12px;
text-align: right;
transform: translate(0%, -50%);
}
.milestone-progress .row {
margin-bottom: calc($line-height / 2);
}
}
}

View File

@@ -0,0 +1,22 @@
<section class="progress-bars">
<h5><%= t("milestones.index.progress") %></h5>
<div class="margin">
<%= progress_tag_for(primary_progress_bar, label: t("milestones.index.progress")) %>
</div>
<% if secondary_progress_bars.any? %>
<div class="milestone-progress">
<% secondary_progress_bars.each do |progress_bar| %>
<div class="row margin-bottom">
<div class="small-12 medium-6 large-4 column">
<%= progress_bar.title %>
</div>
<div class="small-12 medium-6 large-8 column end">
<%= progress_tag_for(progress_bar, label: progress_bar.title) %>
</div>
</div>
<% end %>
</div>
<% end %>
</section>

View File

@@ -0,0 +1,37 @@
class Milestones::ProgressBarsComponent < ApplicationComponent
attr_reader :milestoneable
def initialize(milestoneable)
@milestoneable = milestoneable
end
def render?
primary_progress_bar
end
private
def primary_progress_bar
milestoneable.primary_progress_bar
end
def secondary_progress_bars
milestoneable.secondary_progress_bars
end
def progress_tag_for(progress_bar, label:)
text = number_to_percentage(progress_bar.percentage, precision: 0)
tag.div class: "progress",
role: "progressbar",
"aria-label": label,
"aria-valuenow": progress_bar.percentage,
"aria-valuetext": "#{progress_bar.percentage}%",
"aria-valuemax": ProgressBar::RANGE.max,
"aria-valuemin": "0",
tabindex: "0" do
tag.span(class: "progress-meter", style: "width: #{progress_bar.percentage}%;") +
tag.p(text, class: "progress-meter-text")
end
end
end

View File

@@ -1,16 +0,0 @@
module MilestonesHelper
def progress_tag_for(progress_bar)
text = number_to_percentage(progress_bar.percentage, precision: 0)
tag.div class: "progress",
role: "progressbar",
"aria-valuenow": progress_bar.percentage,
"aria-valuetext": "#{progress_bar.percentage}%",
"aria-valuemax": ProgressBar::RANGE.max,
"aria-valuemin": "0",
tabindex: "0" do
tag.span(class: "progress-meter", style: "width: #{progress_bar.percentage}%;") +
tag.p(text, class: "progress-meter-text")
end
end
end

View File

@@ -2,7 +2,7 @@
<%= sanitize(ballot.amount_progress(heading)) %>
</p>
<div class="progress" role="progressbar" tabindex="0"
<div class="progress" role="progressbar" tabindex="0" aria-labelledby="total_amount"
aria-valuenow="<%= ballot.percentage_spent(heading) %>" aria-valuemin="0" aria-valuemax="100">
<div class="progress-meter"
style="width: <%= ballot.percentage_spent(heading) %>%">

View File

@@ -37,7 +37,8 @@
<%= next_goal_progress %>%
</div>
<div class="progress" role="progressbar" tabindex="0" aria-valuenow="0" aria-valuemin="0"
aria-valuetext="<%= "#{next_goal_progress}%" %>" aria-valuemax="100">
aria-valuetext="<%= "#{next_goal_progress}%" %>" aria-valuemax="100"
aria-label="<%= t("layouts.dashboard.proposal_totals.current_goal") %>">
<div class="progress-meter" style="width: <%= next_goal_progress %>%"></div>
</div>
</div>

View File

@@ -1,6 +1,6 @@
<div class="row">
<div class="small-12 column">
<%= render "milestones/progress_bars", milestoneable: milestoneable %>
<%= render Milestones::ProgressBarsComponent.new(milestoneable) %>
<% if milestoneable.milestones.blank? %>
<div class="callout primary text-center margin-top">

View File

@@ -1,24 +0,0 @@
<% if milestoneable.primary_progress_bar %>
<section class="progress-bars">
<h5><%= t("milestones.index.progress") %></h5>
<div class="margin">
<%= progress_tag_for(milestoneable.primary_progress_bar) %>
</div>
<% if milestoneable.secondary_progress_bars.any? %>
<div class="milestone-progress">
<% milestoneable.secondary_progress_bars.each do |progress_bar| %>
<div class="row margin-bottom">
<div class="small-12 medium-6 large-4 column">
<%= progress_bar.title %>
</div>
<div class="small-12 medium-6 large-8 column end">
<%= progress_tag_for(progress_bar) %>
</div>
</div>
<% end %>
</div>
<% end %>
</section>
<% end %>

View File

@@ -0,0 +1,36 @@
require "rails_helper"
describe Milestones::ProgressBarsComponent do
let(:milestoneable) { create(:legislation_process) }
it "is not rendered without a main progress bar" do
create(:progress_bar, :secondary, progressable: milestoneable, title: "Defeat Evil Lords")
render_inline Milestones::ProgressBarsComponent.new(milestoneable)
expect(page).not_to be_rendered
end
it "renders a main progress bar" do
create(:progress_bar, progressable: milestoneable)
render_inline Milestones::ProgressBarsComponent.new(milestoneable)
expect(page).to have_content "Progress"
expect(page).to have_css "[role=progressbar]", count: 1
expect(page).to have_css "[role=progressbar][aria-label='Progress']"
end
it "renders both main and secondary progress bars" do
create(:progress_bar, progressable: milestoneable)
create(:progress_bar, :secondary, progressable: milestoneable, title: "Build laboratory")
render_inline Milestones::ProgressBarsComponent.new(milestoneable)
expect(page).to have_content "Progress"
expect(page).to have_content "Build laboratory"
expect(page).to have_css "[role=progressbar]", count: 2
expect(page).to have_css "[role=progressbar][aria-label='Progress']"
expect(page).to have_css "[role=progressbar][aria-label='Build laboratory']"
end
end

View File

@@ -103,15 +103,23 @@ describe "Ballots" do
end
context "Adding and Removing Investments" do
scenario "Add a investment" do
scenario "Add an investment" do
create(:budget_investment, :selected, heading: new_york, price: 10000, title: "Bring back King Kong")
create(:budget_investment, :selected, heading: new_york, price: 20000, title: "Paint cabs black")
visit budget_investments_path(budget, heading_id: new_york)
within("#progress_bar") do
expect(page).to have_css "#total_amount", exact_text: "AMOUNT SPENT €0 / TOTAL BUDGET €1,000,000"
expect(page).to have_css "[role=progressbar][aria-labelledby='total_amount']"
end
add_to_ballot("Bring back King Kong")
expect(page).to have_css("#total_amount", text: "€10,000")
expect(page).to have_css("#amount_available", text: "990,000")
within("#progress_bar") do
expect(page).to have_css("#total_amount", text: "10,000")
expect(page).to have_css("#amount_available", text: "€990,000")
end
within("#sidebar") do
expect(page).to have_content "Bring back King Kong"
@@ -268,18 +276,6 @@ describe "Ballots" do
expect(page).to have_content("You have active votes in another heading: District 1")
end
end
scenario "Display progress bar after first vote" do
create(:budget_investment, :selected, heading: new_york, price: 10000, title: "Park expansion")
visit budget_investments_path(budget, heading_id: new_york.id)
add_to_ballot("Park expansion")
within("#progress_bar") do
expect(page).to have_css("#total_amount", text: "€10,000")
end
end
end
context "Groups" do

View File

@@ -430,17 +430,7 @@ describe "Legislation" do
end
end
scenario "With main progress bar" do
create(:progress_bar, progressable: process)
visit milestones_legislation_process_path(process)
within(".tab-milestones") do
expect(page).to have_content "Progress"
end
end
scenario "With main and secondary progress bar" do
scenario "With progress bars" do
create(:progress_bar, progressable: process)
create(:progress_bar, :secondary, progressable: process, title: "Build laboratory")
@@ -451,17 +441,6 @@ describe "Legislation" do
expect(page).to have_content "Build laboratory"
end
end
scenario "No main progress bar" do
create(:progress_bar, :secondary, progressable: process, title: "Defeat Evil Lords")
visit milestones_legislation_process_path(process)
within(".tab-milestones") do
expect(page).not_to have_content "Progress"
expect(page).not_to have_content "Defeat Evil Lords"
end
end
end
end
end