Skip to content

Commit

Permalink
Update Accordion
Browse files Browse the repository at this point in the history
Update to follow conventions of GOVUK Frontend 4.0
Remove custom CSS for condensed layout, this is not in use on GOVK and goes against Design system Guidance. Additionally the accessibility impact has not been reviewed in depth.

- Maintain existing GemAccoridon features of manuals-frontend that allow a user to navigation through this section. [1]
- Layering on features on-top of Design System Accoridon
- Remove condensed layout, CSS and testing

[1] #1937
  • Loading branch information
Chris Yoong committed Jan 24, 2022
1 parent e26b0ef commit 534623a
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 154 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,85 @@
/* global nodeListForEach */
// = require ../vendor/polyfills/common.js
// This component relies on JavaScript from GOV.UK Frontend
// = require govuk/components/accordion/accordion.js
window.GOVUK = window.GOVUK || {}
window.GOVUK.Modules = window.GOVUK.Modules || {}
window.GOVUK.Modules.Accordion = window.GOVUKFrontend
window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;

(function (Modules) {
function GemAccordion ($module) {
this.$module = $module
this.sectionClass = 'govuk-accordion__section'
this.sectionHeaderClass = 'govuk-accordion__section-header'
this.sectionInnerContent = 'govuk-accordion__section-content'

// Translated component content and language attribute pulled from data attributes
this.$module.actions = {}
this.$module.actions.locale = this.$module.getAttribute('data-locale')
this.$module.actions.showText = this.$module.getAttribute('data-show-text')
this.$module.actions.hideText = this.$module.getAttribute('data-hide-text')
this.$module.actions.showAllText = this.$module.getAttribute('data-show-all-text')
this.$module.actions.hideAllText = this.$module.getAttribute('data-hide-all-text')
this.$module.actions.thisSectionVisuallyHidden = this.$module.getAttribute('data-this-section-visually-hidden')
}

GemAccordion.prototype.init = function () {
// Indicate that JavaScript has worked
this.$module.classList.add('gem-c-accordion--active')

// Feature flag for anchor tag navigation used on manuals
if (this.$module.getAttribute('data-anchor-navigation') === 'true') {
this.openByAnchorOnLoad()
this.addEventListenersForAnchors()
}
}

// Navigate to and open accordions with anchored content on page load if a hash is present
GemAccordion.prototype.openByAnchorOnLoad = function () {
var splitHash = window.location.hash.split('#')[1]

if (window.location.hash && document.getElementById(splitHash)) {
this.openForAnchor(splitHash)
}
}

// Add event listeners for links to open accordion sections when navigated to using said anchor links on the page
// Adding an event listener to all anchor link a tags in an accordion is risky but we circumvent this risk partially by only being a layer of accordion behaviour instead of any sort of change to link behaviour
GemAccordion.prototype.addEventListenersForAnchors = function () {
var links = this.$module.querySelectorAll('.' + this.sectionInnerContent + ' a[href*="#"]')
nodeListForEach(links, function (link) {
if (link.pathname === window.location.pathname) {
link.addEventListener('click', this.openForAnchor.bind(this, link.hash.split('#')[1]))
}

}.bind(this))
}

// Find the parent accordion section for the given id and open it
GemAccordion.prototype.openForAnchor = function (hash) {
var target = document.getElementById(hash)
var $section = this.getContainingSection(target)
var $header = $section.querySelector('.' + this.sectionHeaderClass)
// Pass the selected section to "Accordion.prototype.onSectionToggle" to open
$header.click()
}

// Loop through the given id's ancestors until the parent section class is found
GemAccordion.prototype.getContainingSection = function (target) {
while (!target.classList.contains(this.sectionClass)) {
target = target.parentElement
}
return target
}

GemAccordion.prototype.filterLocale = function (key) {
if (this.$module.actions.locale && this.$module.actions.locale.indexOf('{') !== -1) {
var locales = JSON.parse(this.$module.actions.locale)
return locales[key]
} else if (this.$module.actions.locale) {
return this.$module.actions.locale
}
}

Modules.GemAccordion = GemAccordion
})(window.GOVUK.Modules)
Original file line number Diff line number Diff line change
@@ -1,25 +1,2 @@
@import "mixins/prefixed-transform";
@import "govuk/components/accordion/accordion";

.gem-c-accordion {
.govuk-accordion__section-heading {
// this is a temporary addition to fix the line height when it
// is being overridden by styles from govuk-template in collections
@include govuk-media-query($until: desktop) {
@include govuk-font(24, $weight: bold, $line-height: 1.6);
}
}
}

.govuk-accordion--condensed {
.govuk-accordion__section-button {
@include govuk-media-query($from: tablet) {
@include govuk-font($size: 19, $weight: bold);
}
}

.govuk-accordion__section-summary {
@include govuk-media-query($from: tablet) {
@include govuk-font($size: 16);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@
.govuk-accordion__section-summary {
@include govuk-typography-common;
@include govuk-typography-responsive($size: 16, $important: true);

.govuk-accordion--condensed & {
@include govuk-typography-responsive($size: 14, $important: true);
}
}

// Hide the unusable "Open all" button and the "+" icons.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@

id ||= "default-id-#{SecureRandom.hex(4)}"
items ||= []
condensed ||= false
anchor_navigation ||= false

accordion_classes = %w(gem-c-accordion govuk-accordion)
accordion_classes << 'govuk-accordion--condensed' if condensed
accordion_classes << (shared_helper.get_margin_bottom)

translations = {
Expand All @@ -22,7 +20,24 @@
locales = {}

data_attributes ||= {}
data_attributes[:module] = 'govuk-accordion'
data_attributes[:module] = 'govuk-accordion gem-accordion'
data_attributes[:anchor_navigation] = anchor_navigation

translations.each do |key, translation|
locales[key] = shared_helper.t_locale(translation)
data_attributes[key] = t(translation)
end

unique_locales = locales.values.uniq

if unique_locales.length > 1
data_attributes[:locale] = locales
else
if unique_locales[0] != I18n.locale
data_attributes[:locale] = unique_locales[0]
end
end

%>
<% if items.any? %>
<%= tag.div(class: accordion_classes, id: id, data: data_attributes) do %>
Expand All @@ -46,8 +61,16 @@
<%=
content_tag(
shared_helper.get_heading_level,
content_tag('span', item[:heading][:text], class: "govuk-accordion__section-button", id: "#{id}-heading-#{index}", data: item[:data_attributes]),
class: 'govuk-accordion__section-heading'
content_tag(
'span',
item[:heading][:text],
class: "govuk-accordion__section-button",
id: "#{id}-heading-#{index}"

),
class: 'govuk-accordion__section-heading',
id: item[:heading][:id],
data: item[:data_attributes]
)
%>
<%= tag.div(item[:summary][:text], id: "#{id}-summary-#{index}", class: summary_classes) if item[:summary].present? %>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,98 +309,3 @@ examples:
text: How people read
content:
html: <p class="govuk-body">This is the content for How people read.</p>
condensed_layout:
description: |
This layout is for when a smaller accordion is required. Since smaller screens trigger a single column layout, this modifier only makes the accordion smaller when viewed on large screens.
data:
condensed: true
items:
- heading:
text: Understanding agile project management
content:
html:
'<ul class="govuk-list">
<li>
<a class="govuk-link govuk-body-s" href="#">Agile and government services: an introduction</a>
</li>
<li>
<a class="govuk-link govuk-body-s" href="#">Agile methods: an introduction</a>
</li>
<li>
<a class="govuk-link govuk-body-s" href="#">Core principles of agile</a>
</li>
</ul>'
- heading:
text: Working with agile methods
summary:
text: Workspaces, tools and techniques, user stories, planning.
content:
html:
'<ul class="govuk-list">
<li>
<a class="govuk-link govuk-body-s" href="#">Creating an agile working environment</a>
</li>
<li>
<a class="govuk-link govuk-body-s" href="#">Agile tools and techniques</a>
</li>
<li>
<a class="govuk-link govuk-body-s" href="#">Set up a team wall</a>
</li>
<li>
<a class="govuk-link govuk-body-s" href="#">Writing user stories</a>
</li>
<li>
<a class="govuk-link govuk-body-s" href="#">Planning in agile</a>
</li>
<li>
<a class="govuk-link govuk-body-s" href="#">Deciding on priorities</a>
</li>
<li>
<a class="govuk-link govuk-body-s" href="#">Developing a roadmap</a>
</li>
</ul>'
- heading:
text: Governing agile services
content:
html:
'<ul class="govuk-list">
<li>
<a class="govuk-link govuk-body-s" href="#">Governance principles for agile service delivery</a>
</li>
<li>
<a class="govuk-link govuk-body-s" href="#">Measuring and reporting progress</a>
</li>
<li>
<a class="govuk-link govuk-body-s" href="#">Spend controls: check if you need approval to spend money on a service</a>
</li>
<li>
<a class="govuk-link govuk-body-s" href="#">Spend controls: apply for approval to spend money on a service</a>
</li>
<li>
<a class="govuk-link govuk-body-s" href="#">Spend controls: the new pipeline process</a>
</li>
<li>
<a class="govuk-link govuk-body-s" href="#">Working across organisational boundaries</a>
</li>
</ul>'
- heading:
text: Phases of an agile project
content:
html:
'<ul class="govuk-list">
<li>
<a class="govuk-link govuk-body-s" href="#">How the discovery phase works</a>
</li>
<li>
<a class="govuk-link govuk-body-s" href="#">How the alpha phase works</a>
</li>
<li>
<a class="govuk-link govuk-body-s" href="#">How the beta phase works</a>
</li>
<li>
<a class="govuk-link govuk-body-s" href="#">How the live phase works</a>
</li>
<li>
<a class="govuk-link govuk-body-s" href="#">Retiring your service</a>
</li>
</ul>'
32 changes: 7 additions & 25 deletions spec/components/accordion_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ def component_name
],
}
render_component(test_data)
assert_select "[data-module='govuk-accordion']", count: 1
assert_select "[data-module='govuk-accordion gem-c-accordion']", count: 1
end

it '`data-module="govuk-accordion"` attribute is present when custom data attributes given' do
Expand All @@ -216,7 +216,7 @@ def component_name
],
}
render_component(test_data)
assert_select "[data-module='govuk-accordion']", count: 1
assert_select "[data-module='govuk-accordion gem-c-accordion']", count: 1
assert_select "[data-gtm]", count: 2
assert_select "[data-gtm='this-is-gtm']", count: 1
assert_select "[data-gtm='this-is-a-second-gtm']", count: 1
Expand All @@ -225,8 +225,7 @@ def component_name

it "section has class added when expanded flag is present" do
test_data = {
id: "condensed-layout",
condensed: true,
id: "test-for-expanded-layout",
items: [
{
heading: { text: "Heading 1" },
Expand All @@ -248,8 +247,7 @@ def component_name

it "adds id to heading when attribute passed" do
test_data = {
id: "condensed-layout",
condensed: true,
anchor_navigation: true,
items: [
{
heading: { text: "Heading 1", id: "heading-with-id" },
Expand All @@ -264,25 +262,9 @@ def component_name
],
}
render_component(test_data)
assert_select ".gem-c-accordion__section-heading", count: 2
assert_select ".gem-c-accordion__section-heading#heading-with-id", count: 1
assert_select ".gem-c-accordion__section-heading:not([id])", count: 1
end

it "condensed class added correctly" do
test_data = {
id: "condensed-layout",
condensed: true,
items: [
{
heading: { text: "Heading 1" },
summary: { text: "Summary 1." },
content: { html: "<p>Content 1.</p>" },
},
],
}
render_component(test_data)
assert_select ".govuk-accordion.govuk-accordion--condensed", count: 1
assert_select ".govuk-accordion__section-heading", count: 2
assert_select ".govuk-accordion__section-heading#heading-with-id", count: 1
assert_select ".govuk-accordion__section-heading:not([id])", count: 1
end

it "loop index starts at one, not zero (thanks Nunjucks.)" do
Expand Down

0 comments on commit 534623a

Please sign in to comment.