-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replace GOVUK Radios JS with NHSUK Radios JS
This implements a Stimulus controller shim to enhance `nhsuk-radios` using the custom JS from `nhsuk-frontend`. Because we're using GOVUK Radios HTML but with NHSUK Radios styling, we need to manually add a `nhsuk-radios--conditional` class to the root element. In addition, NHSUK Radios use `aria-controls` on the server-rendered HTML, but GOVUK Radios use `data-aria-controls` and enhance it when JS initialises. Using `data-aria-controls` is the better solution, because it means that the attribute doesn't kick in in a no-JS situation.
- Loading branch information
Showing
4 changed files
with
84 additions
and
12 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
app/javascript/controllers/nhsuk_radios_controller.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { application } from "./application"; | ||
import NhsukRadiosController from "./nhsuk_radios_controller"; | ||
import NhsukRadios from "nhsuk-frontend/packages/components/radios/radios"; | ||
|
||
jest.mock("nhsuk-frontend/packages/components/radios/radios"); | ||
|
||
// Creating HTML body structure | ||
document.body.innerHTML = ` | ||
<div data-module="nhsuk-radios"> | ||
<input type="radio" data-aria-controls="target-id" /> | ||
<div id="target-id" class="nhsuk-radios__conditional"></div> | ||
</div> | ||
<div data-module="nhsuk-radios"> | ||
<input type="radio" /> | ||
</div> | ||
`; | ||
|
||
describe("NhsukRadiosController", () => { | ||
beforeEach(() => { | ||
application.register("nhsuk-radios", NhsukRadiosController); | ||
}); | ||
|
||
test("should call NhsukRadios", () => { | ||
expect(NhsukRadios).toHaveBeenCalledTimes(2); | ||
}); | ||
|
||
test("should add 'nhsuk-radios--conditional' class", () => { | ||
const elements = document.querySelectorAll('[data-module="nhsuk-radios"]'); | ||
expect(elements[0].classList).toContain("nhsuk-radios--conditional"); | ||
expect(elements[1].classList).not.toContain("nhsuk-radios--conditional"); | ||
}); | ||
|
||
test("should promote 'data-aria-controls' to 'aria-controls'", () => { | ||
const radioInput = document.querySelector('input[type="radio"]'); | ||
expect(radioInput.getAttribute("aria-controls")).toEqual("target-id"); | ||
expect(radioInput.getAttribute("data-aria-controls")).toBeNull(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { Controller } from "@hotwired/stimulus"; | ||
import NhsukRadios from "nhsuk-frontend/packages/components/radios/radios"; | ||
|
||
// Connects to data-module="nhsuk-radios" | ||
export default class extends Controller { | ||
connect() { | ||
this.addConditionalClassIfNeeded(); | ||
this.promoteAriaControlsAttribute(); | ||
|
||
NhsukRadios(); | ||
} | ||
|
||
// We use govuk-frontend radio button HTML, which doesn't use a --conditional | ||
// modifier on the root element. NHSUK Radios require this in order to set up | ||
// and initialise. | ||
addConditionalClassIfNeeded() { | ||
if (!this.element.querySelectorAll(".nhsuk-radios__conditional").length) | ||
return; | ||
|
||
this.element.classList.add("nhsuk-radios--conditional"); | ||
} | ||
|
||
// Promote data-aria-controls attribute to a aria-controls attribute as per | ||
// https://github.com/alphagov/govuk-frontend/blob/88fea750b5eb9c9d9f661405e68bfb59e59754b2/packages/govuk-frontend/src/govuk/components/radios/radios.mjs#L33-L34 | ||
promoteAriaControlsAttribute() { | ||
const $inputs = this.element.querySelectorAll('input[type="radio"]'); | ||
|
||
$inputs.forEach(($input) => { | ||
const targetId = $input.getAttribute("data-aria-controls"); | ||
|
||
// Skip radios without data-aria-controls attributes, or where the | ||
// target element does not exist. | ||
if (!targetId || !document.getElementById(targetId)) { | ||
return; | ||
} | ||
|
||
// Promote the data-aria-controls attribute to a aria-controls attribute | ||
// so that the relationship is exposed in the AOM | ||
$input.setAttribute("aria-controls", targetId); | ||
$input.removeAttribute("data-aria-controls"); | ||
}); | ||
} | ||
} |