diff --git a/app/assets/stylesheets/layout/locale_switcher.scss b/app/assets/stylesheets/layout/locale_switcher.scss index 424e7c793..c3f7c2be3 100644 --- a/app/assets/stylesheets/layout/locale_switcher.scss +++ b/app/assets/stylesheets/layout/locale_switcher.scss @@ -1,25 +1,25 @@ .locale { - @include has-fa-icon(angle-down, solid, after); float: left; margin-bottom: $line-height / 4; margin-top: $line-height / 4; position: relative; - &::after { - color: #808080; - font-size: $small-font-size; - margin-right: 0; - pointer-events: none; - position: absolute; - right: 2px; - top: 50%; - transform: translateY(-50%); - } - .locale-form { + @include has-fa-icon(angle-down, solid, after); display: inline-block; position: relative; + &::after { + color: #808080; + font-size: $small-font-size; + margin-right: 0; + pointer-events: none; + position: absolute; + right: 2px; + top: 50%; + transform: translateY(-50%); + } + label { color: #fff; font-size: $tiny-font-size; @@ -51,4 +51,31 @@ } } } + + p { + @include element-invisible; + } + + ul { + $gap: 0.75em; + display: flex; + flex-wrap: wrap; + margin-left: -$gap; + + > * { + margin-left: $gap; + } + + li::after { + content: none; + } + + a { + margin-left: 0; + } + + [aria-current] { + font-weight: bold; + } + } } diff --git a/app/components/layout/locale_switcher_component.html.erb b/app/components/layout/locale_switcher_component.html.erb index dfb1c2c39..0ff9aac9a 100644 --- a/app/components/layout/locale_switcher_component.html.erb +++ b/app/components/layout/locale_switcher_component.html.erb @@ -1,10 +1,14 @@
-
- - -
+ <% if many_locales? %> +
+ + +
+ <% else %> +

<%= label %>

+ + <%= link_list(*language_links, "aria-labelledby": label_id) %> + <% end %>
diff --git a/app/components/layout/locale_switcher_component.rb b/app/components/layout/locale_switcher_component.rb index 1983e176b..4e7408adf 100644 --- a/app/components/layout/locale_switcher_component.rb +++ b/app/components/layout/locale_switcher_component.rb @@ -1,5 +1,5 @@ class Layout::LocaleSwitcherComponent < ApplicationComponent - delegate :name_for_locale, :current_path_with_query_params, to: :helpers + delegate :name_for_locale, :link_list, :current_path_with_query_params, to: :helpers def render? locales.size > 1 @@ -7,13 +7,36 @@ class Layout::LocaleSwitcherComponent < ApplicationComponent private + def many_locales? + locales.size > 4 + end + def locales I18n.available_locales end - def language_options + def label + t("layouts.header.locale") + end + + def label_id + "locale_switcher_label" + end + + def language_links locales.map do |locale| - [name_for_locale(locale), current_path_with_query_params(locale: locale), lang: locale] + [ + name_for_locale(locale), + current_path_with_query_params(locale: locale), + locale == I18n.locale, + lang: locale + ] + end + end + + def language_options + language_links.map do |text, path, _, options| + [text, path, options] end end end diff --git a/spec/components/layout/locale_switcher_component_spec.rb b/spec/components/layout/locale_switcher_component_spec.rb index c4ae8b1be..5d1462e49 100644 --- a/spec/components/layout/locale_switcher_component_spec.rb +++ b/spec/components/layout/locale_switcher_component_spec.rb @@ -28,6 +28,7 @@ describe Layout::LocaleSwitcherComponent, type: :component do expect(page).to have_css "form" expect(page).to have_select "Language:", options: %w[Deutsch English Español Français Nederlands] + expect(page).not_to have_css "ul" end it "selects the current locale" do @@ -53,4 +54,27 @@ describe Layout::LocaleSwitcherComponent, type: :component do end end end + + context "with a few languages" do + before do + allow(I18n).to receive(:available_locales).and_return(%i[en es fr]) + end + + it "renders a list of links" do + render_inline component + + expect(page).to have_css "ul" + expect(page).to have_link "English", href: "/?locale=en" + expect(page).to have_link "Español", href: "/?locale=es" + expect(page).to have_link "Français", href: "/?locale=fr" + expect(page).not_to have_css "form" + end + + it "marks the current locale" do + render_inline component + + expect(page).to have_css "[aria-current]", count: 1 + expect(page).to have_css "[aria-current]", exact_text: "English" + end + end end