Skip to content

Commit

Permalink
Merge pull request #294 from alphagov/iterate-subscription-links-comp…
Browse files Browse the repository at this point in the history
…onent

Modify subscription links component
  • Loading branch information
andysellick authored May 4, 2018
2 parents 3dd8505 + 0ddaaa2 commit d4800f2
Show file tree
Hide file tree
Showing 8 changed files with 249 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Unreleased

* Add department colours to components (PR #296)
* Modify subscription links component (PR #294)

# 7.1.0

Expand Down
69 changes: 69 additions & 0 deletions app/assets/javascripts/govuk_publishing_components/lib/toggle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
Toggle the display of elements
This is a straight copy of the same file from static.
Use `data-controls` and `data-expanded` to indicate the
starting state and the IDs of the elements that the toggle
controls. This is synonymous with ARIA attributes, which
get added when starting.
*/

window.GOVUK.Modules = window.GOVUK.Modules || {};

(function (Modules) {
'use strict'

Modules.GemToggle = function () {
this.start = function ($el) {
var toggleSelector = '[data-controls][data-expanded]'

$el.on('click', toggleSelector, toggle)
$el.find(toggleSelector).each(addAriaAttrs)

// Add the ARIA attributes with JavaScript
// If the JS fails and there's no interactive elements, having
// no aria attributes is an accurate representation.
function addAriaAttrs () {
var $toggle = $(this)
$toggle.attr('role', 'button')
$toggle.attr('aria-controls', $toggle.data('controls'))
$toggle.attr('aria-expanded', $toggle.data('expanded'))

var $targets = getTargetElements($toggle)
$targets.attr('aria-live', 'polite')
$targets.attr('role', 'region')
$toggle.data('$targets', $targets)
}

function toggle (event) {
var $toggle = $(event.target),
expanded = $toggle.attr('aria-expanded') === 'true',
$targets = $toggle.data('$targets')

if (expanded) {
$toggle.attr('aria-expanded', false)
$targets.addClass('js-hidden')
} else {
$toggle.attr('aria-expanded', true)
$targets.removeClass('js-hidden')
}

var toggledText = $toggle.data('toggled-text')
if (typeof toggledText === 'string') {
$toggle.data('toggled-text', $toggle.text())
$toggle.text(toggledText)
}

event.preventDefault()
}

function getTargetElements ($toggle) {
var ids = $toggle.attr('aria-controls').split(' '),
selector = '#' + ids.join(', #')

return $el.find(selector)
}
}
}
})(window.GOVUK.Modules)
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@

.gem-c-subscription-links__link--feed {
background-image: image-url("govuk_publishing_components/feed-icon-black.png");

// if this is a toggle, only show if js is enabled
&[data-controls] {
display: none;

.js-enabled & {
display: block;
}
}
}

.gem-c-subscription-links__link--email-alerts {
Expand All @@ -37,4 +46,15 @@
background-size: 20px 14px;
}
}

.gem-c-subscription-links__feed-box {
padding: $gutter-half;
margin-bottom: $gutter-half;
background: $grey-3;
}

.gem-c-subscription-links__feed-description {
font-weight: bold;
}
}

Original file line number Diff line number Diff line change
@@ -1,21 +1,50 @@
<%
email_signup_link ||= false
email_signup_link_text ||= t("govuk_component.subscription_links.email_signup_link_text", default: "Get email alerts")
feed_link ||= false
feed_link_text ||= t("govuk_component.subscription_links.feed_link_text", default: "Subscribe to feed")
feed_link_box_value ||= false
feed_link_data = false

if feed_link_box_value
feed_link = "#"
feed_link_data = {
controls: "feed-reader",
expanded: "false"
}
end
%>
<% if email_signup_link || feed_link %>
<section class="gem-c-subscription-links">
<h2 class="visuallyhidden">Subscriptions</h2>
<% if email_signup_link || feed_link || feed_link_box_value %>
<section class="gem-c-subscription-links" data-module="gem-toggle">
<h2 class="visuallyhidden"><%= t("govuk_component.subscription_links.subscriptions", default: "Subscriptions") %></h2>
<ul class="gem-c-subscription-links__list">
<% if email_signup_link.present? %>
<li class="gem-c-subscription-links__list-item">
<%= link_to "Get email alerts", email_signup_link, class: "gem-c-subscription-links__link gem-c-subscription-links__link--email-alerts" %>
<%= link_to email_signup_link_text, email_signup_link, class: "gem-c-subscription-links__link gem-c-subscription-links__link--email-alerts" %>
</li>
<% end %>
<% if feed_link.present? %>

<% if feed_link_box_value || feed_link.present? %>
<li class="gem-c-subscription-links__list-item">
<%= link_to "Subscribe to feed", feed_link, class: "gem-c-subscription-links__link gem-c-subscription-links__link--feed" %>
<%= link_to feed_link_text, feed_link,
class: "gem-c-subscription-links__link gem-c-subscription-links__link--feed",
data: feed_link_data
%>
</li>
<% end %>
</ul>

<% if feed_link_box_value %>
<div class="gem-c-subscription-links__feed-box js-hidden" id="feed-reader">
<p class="gem-c-subscription-links__feed-description js-hidden"><%= feed_link_text %></p>
<%= render "govuk_publishing_components/components/input", {
label: {
text: "Copy and paste this URL into your feed reader"
},
name: "feed-reader-box",
value: feed_link_box_value
} %>
</div>
<% end %>
</section>
<% end %>
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ name: Subscription links
description: Links to ‘Get email alerts’ and ‘Subscribe to feed’
accessibility_criteria: |
Icons in subscription links must be presentational and ignored by screen readers.
Toggle elements in the component must:
- be usable with a keyboard
- be usable with touch
- be recognised by screen readers as a button
- announce to screen readers whether they are expanded or collapsed
- show hidden elements by default when Javascript is disabled
shared_accessibility_criteria:
- link
examples:
Expand All @@ -15,3 +23,17 @@ examples:
with_only_feed_link:
data:
feed_link: '/foreign-travel-advice/singapore.atom'
with_custom_text:
data:
email_signup_link: '/foreign-travel-advice/singapore/email-signup'
email_signup_link_text: 'Get notifications'
feed_link: '/foreign-travel-advice/singapore.atom'
feed_link_text: 'View feed'
with_copyable_feed_link:
description: |
This option changes the feed link to a toggle control, which opens a hidden element containing an input prepopulated with the value passed to the component, usually a URL to an atom feed. This uses the [form input](/component-guide/input) component.
Note that this option overrides the feed_link option, so if both are passed feed_link is ignored. Note that a value for email_signup_link can also be passed as normal.
data:
email_signup_link: '/foreign-travel-advice/singapore/email-signup'
feed_link_box_value: 'https://www.gov.uk/government/organisations/attorney-generals-office.atom'
4 changes: 4 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ en:
hide_all: "Hide all"
step_by_step_nav_related:
part_of: "Part of"
subscription_links:
email_signup_link_text: "Get email alerts"
feed_link_text: "Subscribe to feed"
subscriptions: "Subscriptions"
taxonomy_navigation:
collections: "Collection"
policies: "Policy"
Expand Down
12 changes: 12 additions & 0 deletions spec/components/subscription_links_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,16 @@ def component_name
assert_select ".gem-c-subscription-links__link--email-alerts[href=\"email-signup\"]", text: "Get email alerts"
assert_select ".gem-c-subscription-links__link--feed[href=\"singapore.atom\"]", text: "Subscribe to feed"
end

it "renders custom texts" do
render_component(email_signup_link: 'email-signup', feed_link: 'singapore.atom', email_signup_link_text: 'Get email!', feed_link_text: 'View feed!')
assert_select ".gem-c-subscription-links__link--email-alerts[href=\"email-signup\"]", text: "Get email!"
assert_select ".gem-c-subscription-links__link--feed[href=\"singapore.atom\"]", text: "View feed!"
end

it "renders with a feed link box" do
render_component(feed_link_box_value: 'http://www.gov.uk', feed_link: 'singapore.atom')
assert_select ".gem-c-subscription-links__link--feed[href=\"singapore.atom\"]", false
assert_select ".gem-c-subscription-links__feed-box input[name='feed-reader-box'][value='http://www.gov.uk']"
end
end
86 changes: 86 additions & 0 deletions spec/javascripts/components/toggle-spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
describe('A toggle module', function () {
'use strict'

var toggle,
element

beforeEach(function () {
toggle = new GOVUK.Modules.GemToggle()
})

describe('when starting', function () {
var element = $('\
<div>\
<a href="#" class="my-toggle" data-expanded="false" data-controls="target">Toggle</a>\
<div id="target">Target</div>\
</div>')

it('adds aria attributes to toggles', function () {
toggle.start(element)

var $toggle = element.find('.my-toggle')
expect($toggle.attr('role')).toBe('button')
expect($toggle.attr('aria-expanded')).toBe('false')
expect($toggle.attr('aria-controls')).toBe('target')
})
})

describe('when clicking a toggle', function () {
var element

beforeEach(function () {
element = $('\
<div>\
<a href="#" class="my-toggle" data-expanded="false" data-controls="target" data-toggled-text="Show fewer">Toggle</a>\
<div id="target" class="js-hidden">Target</div>\
</div>')

toggle.start(element)
element.find('.my-toggle').trigger('click')
})

it('toggles the display of a target', function () {
expect(element.find('#target').is('.js-hidden')).toBe(false)
element.find('.my-toggle').trigger('click')
expect(element.find('#target').is('.js-hidden')).toBe(true)
})

it('updates the aria-expanded attribute on the toggle', function () {
expect(element.find('.my-toggle').attr('aria-expanded')).toBe('true')

element.find('.my-toggle').trigger('click')
expect(element.find('.my-toggle').attr('aria-expanded')).toBe('false')
})

it('updates the text shown in the toggle link when expanded if such text is supplied', function () {
expect(element.find('.my-toggle').data('toggled-text')).toBe('Toggle')
expect(element.find('.my-toggle').text()).toBe('Show fewer')
element.find('.my-toggle').trigger('click')
expect(element.find('.my-toggle').data('toggled-text')).toBe('Show fewer')
expect(element.find('.my-toggle').text()).toBe('Toggle')
})
})

describe('when clicking a toggle that controls multiple targets', function () {
it('toggles the display of each target', function () {
var element = $('\
<div>\
<a href="#" class="my-toggle" data-expanded="false" data-controls="target another-target">Toggle</a>\
<div id="target" class="js-hidden">Target</div>\
<div id="another-target" class="js-hidden">Another target</div>\
</div>')

toggle.start(element)
expect(element.find('#target').is('.js-hidden')).toBe(true)
expect(element.find('#another-target').is('.js-hidden')).toBe(true)

element.find('.my-toggle').trigger('click')
expect(element.find('#target').is('.js-hidden')).toBe(false)
expect(element.find('#another-target').is('.js-hidden')).toBe(false)

element.find('.my-toggle').trigger('click')
expect(element.find('#target').is('.js-hidden')).toBe(true)
expect(element.find('#another-target').is('.js-hidden')).toBe(true)
})
})
})

0 comments on commit d4800f2

Please sign in to comment.