Skip to content

Commit

Permalink
Set width of focus state
Browse files Browse the repository at this point in the history
The CSS adjustment removed in #132c12f had the favourable side effect of limiting the width of the focus state for the three text items (heading, summary, show/hide), stopping the focus state from expanding beyond the text to the full width of the component.

To limit the width of the focus state without the NVDA adjustment, this commit:
- adds focus containers in the markup inside the three items using JavaScript
- makes the focus containers inline items
- moves the focus styles to those classes; the inline style sets the width of the focus state to the width of the text
- renames `.govuk-accordion__section-heading-focus-wrapper` to `.govuk-accordion__section-heading-text` since the class no longer has the focus styles

Change the text containers to set bottom margin instead of top margin as this:
- resolves an issue with the summary line margin: since the summary line container is now a block level one, it renders the `.govuk-body` bottom margin; moving the margin to the bottom of the container makes the container margin collapse with the `.govuk-body` bottom margin
- is more consistent with how rest of GOV.UK Frontend sets margins

As the last text container inside the butotn now has a bottom margin, we also don’t need set the bottom margin on the button anymore.
  • Loading branch information
hannalaakso committed Oct 5, 2021
1 parent 4a818c3 commit c6cd841
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 18 deletions.
21 changes: 13 additions & 8 deletions src/govuk/components/accordion/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
padding-top: govuk-spacing(3);
}

.govuk-accordion__section-heading-focus-wrapper {
.govuk-accordion__section-heading-text {
@include govuk-font($size: 24, $weight: bold);
}

Expand Down Expand Up @@ -197,7 +197,7 @@
.govuk-accordion__section-button {
width: 100%;

padding: govuk-spacing(2) 0 govuk-spacing(3) 0;
padding: govuk-spacing(2) 0 0 0;

border: 0;

Expand Down Expand Up @@ -243,9 +243,9 @@
// styling is being applied to inner text elements that receive focus
outline: 0;

.govuk-accordion__section-heading-focus-wrapper,
.govuk-accordion__section-summary,
.govuk-accordion__section-toggle {
.govuk-accordion__section-heading-text-focus,
.govuk-accordion__section-summary-focus,
.govuk-accordion__section-toggle-focus {
@include govuk-focused-text;
}

Expand Down Expand Up @@ -277,10 +277,15 @@
}

.govuk-accordion__section-toggle,
.govuk-accordion__section-heading-focus-wrapper,
.govuk-accordion__section-heading-text,
.govuk-accordion__section-summary {
display: block;
margin-top: 13px;
margin-bottom: 13px;

.govuk-accordion__section-heading-text-focus,
.govuk-accordion__section-summary-focus,
.govuk-accordion__section-toggle-focus {
display: inline;
}
}

Expand Down Expand Up @@ -320,7 +325,7 @@

.govuk-accordion__show-all:focus,
.govuk-accordion__section-button:focus {
.govuk-accordion__section-heading-focus-wrapper,
.govuk-accordion__section-heading-text,
.govuk-accordion__section-summary,
.govuk-accordion__section-toggle,
.govuk-accordion-nav__chevron {
Expand Down
36 changes: 26 additions & 10 deletions src/govuk/components/accordion/accordion.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,17 @@ function Accordion ($module) {

this.sectionHeaderClass = 'govuk-accordion__section-header'
this.sectionHeadingClass = 'govuk-accordion__section-heading'
this.sectionHeadingClassFocusWrapper = 'govuk-accordion__section-heading-focus-wrapper'
this.sectionHeadingTextClass = 'govuk-accordion__section-heading-text'
this.sectionHeadingTextFocusClass = 'govuk-accordion__section-heading-text-focus'
this.sectionSummaryClass = 'govuk-accordion__section-summary'
this.sectionButtonClass = 'govuk-accordion__section-button'
this.sectionExpandedClass = 'govuk-accordion__section--expanded'
this.sectionShowHideToggleClass = 'govuk-accordion__section-toggle'
this.sectionShowHideToggleFocusClass = 'govuk-accordion__section-toggle-focus'
this.sectionShowHideTextClass = 'govuk-accordion__section-toggle-text'
this.upChevronIconClass = 'govuk-accordion-nav__chevron'
this.downChevronIconClass = 'govuk-accordion-nav__chevron--down'
this.sectionSummaryFocusClass = 'govuk-accordion__section-summary-focus'
}

// Initialize component
Expand Down Expand Up @@ -117,41 +120,54 @@ Accordion.prototype.initHeaderAttributes = function ($headerWrapper, index) {
// Create show / hide icons with text.
var $showIcons = document.createElement('span')
$showIcons.classList.add(this.sectionShowHideToggleClass)
// Create an inner container to limit the width of the show/hide focus state
var $showIconsFocus = document.createElement('span')
$showIconsFocus.classList.add(this.sectionShowHideToggleFocusClass)
$showIcons.appendChild($showIconsFocus)

// Wrapper of heading to receive focus state design
// ID set to allow the heading alone to be referenced without "this section"
var $wrapperFocusHeading = document.createElement('span')
$wrapperFocusHeading.classList.add(this.sectionHeadingClassFocusWrapper)
$wrapperFocusHeading.setAttribute('id', this.moduleId + '-heading-' + (index + 1))
var $wrapperHeadingText = document.createElement('span')
$wrapperHeadingText.classList.add(this.sectionHeadingTextClass)
$wrapperHeadingText.setAttribute('id', this.moduleId + '-heading-' + (index + 1))
// Create an inner heading container to limit the width of the heading text focus state
var $wrapperHeadingTextFocus = document.createElement('span')
$wrapperHeadingTextFocus.classList.add(this.sectionHeadingTextFocusClass)
$wrapperHeadingText.appendChild($wrapperHeadingTextFocus)

// Build additional wrapper for toggle text, place icon before wrapped text.
var $wrapperToggleText = document.createElement('span')
var $icon = document.createElement('span')
$icon.classList.add(this.upChevronIconClass)
$showIcons.appendChild($icon)
$showIconsFocus.appendChild($icon)
$wrapperToggleText.classList.add(this.sectionShowHideTextClass)
$showIcons.appendChild($wrapperToggleText)
$showIconsFocus.appendChild($wrapperToggleText)

// Copy all attributes (https://developer.mozilla.org/en-US/docs/Web/API/Element/attributes) from $span to $button
for (var i = 0; i < $span.attributes.length; i++) {
var attr = $span.attributes.item(i)
// Add all attributes but not ID as this is being add directly on $wrapperFocusHeading
// Add all attributes but not ID as this is being added directly on $wrapperHeadingText
if (attr.nodeName !== 'id') {
$button.setAttribute(attr.nodeName, attr.nodeValue)
}
}

$heading.removeChild($span)
$heading.appendChild($button)
$button.appendChild($wrapperFocusHeading)
$button.appendChild($wrapperHeadingText)

$button.appendChild(this.getButtonPunctuationEl())
// span could contain HTML elements (see https://www.w3.org/TR/2011/WD-html5-20110525/content-models.html#phrasing-content)
$wrapperFocusHeading.innerHTML = $span.innerHTML
$wrapperHeadingTextFocus.innerHTML = $span.innerHTML

// If summary content exists add to DOM in correct order
if (typeof ($summary) !== 'undefined' && $summary !== null) {
// Create new element, in order to swap the summary from div to span as the summary element is with a button
var $summarySpan = document.createElement('span')
// Create an inner summary container to limit the width of the summary focus state
var $summarySpanFocus = document.createElement('span')
$summarySpanFocus.classList.add(this.sectionSummaryFocusClass)
$summarySpan.appendChild($summarySpanFocus)

// Get original attributes, and pass them to the replacement
for (var j = 0, l = $summary.attributes.length; j < l; ++j) {
Expand All @@ -161,7 +177,7 @@ Accordion.prototype.initHeaderAttributes = function ($headerWrapper, index) {
}

// Persist contents
$summarySpan.innerHTML = $summary.innerHTML
$summarySpanFocus.innerHTML = $summary.innerHTML

// Switch summary from div to span
$summary.parentNode.replaceChild($summarySpan, $summary)
Expand Down

0 comments on commit c6cd841

Please sign in to comment.