-
Notifications
You must be signed in to change notification settings - Fork 338
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add new Modal Dialogue component #1668
Conversation
Can we please have this on a Heroku preview URL so I can share with the team? Thanks edit: Preview URL |
aab4515
to
49a0e1f
Compare
Also any design feedback would be appreciated. We're aware we added another embedded "crown" SVG, so you might want a better way of adding this to the page without duplicating the SVG markup. I added the crown as it's already in use here: But not sure what the user need is. |
@alex-ju and I worked on one here, not sure if you've seen it: |
Ahh is this the same code as used on as https://components.publishing.service.gov.uk/component-guide/modal_dialogue? If you're the original designer thank you 😁 We've also improved the focus trapping so if you manage to click out of the modal, you're pulled back in again, not just looping from last/first items. We've added It's been great to improve one that's already in production. |
I have some questions on the design, maybe these have been decided as part of research...
|
@NickColley Maybe @soniaturcotte can help? We used the design from https://components.publishing.service.gov.uk/component-guide/modal_dialogue and it tested well when we did user research. |
49a0e1f
to
b77bf86
Compare
I've removed the vertical alignment fallback for older browsers using In IE10+ we've got basic flexbox support so that's good enough. Older browsers like IE8 + IE9 will have the modal at the top of the screen. |
b77bf86
to
0913734
Compare
@NickColley Did you mean like this for the close button text? Maybe it's something @FeyAgape can explore? You're in her capable hands now 😊 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good, thanks Colin 🙌 A couple of small suggestions from me. I've only really had a chance to review app/
part which @colinrotherham was keen to get some feedback on, will look at the src/
files next.
Caused by `.govuk-main-wrapper--auto-spacing`
Requires fixed height as iFrameResizer can’t handle `position: fixed` child content
0913734
to
125474b
Compare
125474b
to
aba92ba
Compare
this.hasNativeDialog = 'showModal' in this.$dialogBox | ||
|
||
// Allowed focussable elements | ||
this.focussable = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is an 'inert' feature we could consider referring to when reviewing the focus trap functionality in this proposal:
https://github.com/WICG/inert
It ships in chromium, I'm not sure if it's a proper standard yet but worth thinking about.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah sounds like a good enhancement.
You'd have to be very careful and keep the modal outside govuk-width-container
or whatever the page wrapper element was.
<body>
<div class="govuk-width-container" inert>…</div>
<div data-module="govuk-modal-dialogue">…</div>
</body>
It could go horribly wrong if the modal was inside the [inert]
wrapper.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The early prototype version of the modal that GOV.UK based theirs on used both the inert
attribute and aria-hidden
to make the <main>
wrapper non-actionable and this tested well with screen reader users. The modal markup was outside <main>
and below <body>
.
Colin does have a valid point: we need to be clear in the guidance about where the modal markup is placed in the page content.
ModalDialogue.prototype.init = function (options) { | ||
this.options = options || {} | ||
|
||
this.open = this.handleOpen.bind(this) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if these method binds should be in the constructor instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@NickColley I try to defer anything that uses more CPU cycles until it's actually needed (like when .init()
gets run) but it's probably negligible so don't mind.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Colin 👍 We believe that the performance impact is negligible so we should make the change for consistency with other components.
this.$lastActiveElement.focus() | ||
|
||
// Optional 'onClose' callback | ||
if (typeof this.options.onClose === 'function') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we need to consider how we're documenting the JavaScript options for components, since we use data-attributes elsewhere instead of programmatic options.
See also: Proposal programmatic and data attribute api interface for components
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@NickColley Yeah good point.
Here's how we currently use this Modal API on our prototype:
var $dialogue = document.querySelector('[data-module="govuk-modal-dialogue"]')
var $dialogueButtonResume = document.querySelector('.govuk-modal-dialogue__continue')
if ($dialogue && $dialogueButtonResume) {
var modal = new window.ModalDialogue($dialogue)
.init({
focusElement: $dialogueButtonResume,
onClose: function () {
// Extend session timeout here
}
})
}
@import "../../helpers/all"; | ||
|
||
@include govuk-exports("govuk/component/modal-dialogue") { | ||
$govuk-dialogue-width: 640px; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably want to use !default
here so that the value can overridden.
box-sizing: border-box; | ||
display: block; | ||
position: relative; | ||
z-index: 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might want to increase this, just in the (non-ideal) case that the page has other competing elements. I notice that the GOV.UK Publishing equivalent sets this to 1000.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've made this 1001 so it is above the backdrop which also needs the z-index increasing.
z-index: 1; | |
z-index: 1001; |
width: 90%; | ||
margin: auto; | ||
padding: 0; | ||
overflow-y: auto; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might be okay as it is but just for reference, I notice that the GOV.UK Publishing example currently sets these to:
overflow-x: hidden;
overflow-y: scroll;
I don't think we currently have an example with page content in the main area so we need to add one (see #1668 (comment)) in order to check that the main page content is not scrollable and the modal is.
background: govuk-colour("black"); | ||
pointer-events: none; | ||
touch-action: none; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this block should live below https://github.com/alphagov/govuk-frontend/pull/1668/files#diff-40be96fa6566e06e9d9d9ab4d1d3d831R8 to in order to keep the backdrop styles together.
} | ||
} | ||
|
||
// New dialogue width, inline button + link |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure why these styles are set separately from the other ones in this file. Should this be a modifier class?
} | ||
|
||
// Fixed width | ||
@include govuk-media-query($from: desktop) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure why these styles are set separately from the other ones in this file. Should this be a modifier class?
|
||
// Close dialogue on close button click | ||
this.$buttonClose.addEventListener('click', this.close) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a big deal but I wonder if the events inside this block could live inside init()
, it'll be tidier once we move the variable definitions to the constructor.
this.$lastActiveElement = document.activeElement | ||
|
||
// Disable scrolling, show wrapper | ||
this.$container.classList.add('govuk-!-scroll-disabled') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does govuk-!-scroll-disabled
do anything? I can't see any styles created for it.
type: "button", | ||
classes: "govuk-modal-dialogue__close", | ||
attributes: { | ||
"aria-label": "Close modal dialogue" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if all users will know what is meant by "modal dialogue" here? The users of GOV.UK Publisher components (which this is based on) would mainly be repeat users with at least a moderate level of computer literacy and are therefore not representative of the wider population at whole. If we could explore an alternative wording that would be great.
} | ||
|
||
// Ensure focus stays within modal | ||
ModalDialogue.prototype.handleFocusTrap = function (event) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to understand more about the scenario in which focus might escape the modal. This function executes when the tab key is pressed, but the background should already be non-actionable so that none of the background elements can be tabbed to.
Fixing #1668 (comment) should help with this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To add to this point, what if a user navigates via landmarks? What is the impact on them when the modal is open.
: this.$dialogBox.removeAttribute('open') | ||
|
||
// Hide wrapper, enable scrolling | ||
this.$module.classList.remove('govuk-modal-dialogue--open') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we save class names as variables in the constructor and reference them from there?
} | ||
|
||
// New dialogue width, inline button + link | ||
@include govuk-media-query($from: tablet) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the mobile/tablet experience meant to be similar to the GOV.UK Publishing modal?
This might be something for @Ash-Wilson to consider.
|
||
// Lock scroll, focus modal | ||
ModalDialogue.prototype.handleFocus = function () { | ||
this.$dialogBox.scrollIntoView() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the component is going to follow the mobile experience of the GOV.UK Publisher modal (see #1668 (comment)) then this might not be needed, since the modal will either have a fixed position or fill the viewport?
viewbox="0 0 132 97" | ||
height="30" | ||
width="36" | ||
> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had a chat with @FeyAgape. We should consider removing the crown logo as there is no clear user need. Its usage here is not consistent with our other components and it adds complexity.
Its usage in public facing sites in this manner might also be problematic with regards to the branding guidelines; the Service Manual guidance mentions the use of the crown logo only in the header.
</svg> | ||
|
||
{{ govukButton({ | ||
text: "×", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had a chat with @FeyAgape. If possible, we should explore using a text equivalent here as icons might not be understood by all users.
previewLayout: modal | ||
|
||
examples: | ||
- name: default |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we make this example open the modal with a button? Similar to the GOV.UK Publishing modal example. This would allow us to test the transition of the modal being closed to it being open, and how the main page content is made actionable / non-actionable.
Doing this might require some tweaking of the review app.
description: | ||
html: <p class="govuk-body">Prompt text for the modal dialogue component goes here</p> | ||
|
||
- name: open with scrolling content |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we make this example to have some page content in the main page area? Similar to the GOV.UK Publishing modal example. This would allow us to test that the background is not scrollable / actionable when the modal is open.
- name: open | ||
type: boolean | ||
required: true | ||
description: If true, modal dialogue element will be visible. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we consider calling the component "modal dialog" instead?
We're using the HTML <dialog>
element and the industry docs talk about "modal dialog".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trends over time of different names:
https://trends.google.com/trends/explore?cat=422&q=modal,dialog,modal%20dialog,modal%20dialogue,dialogue
@hannalaakso I can help review this when you're happy later on, perhaps before it goes to the working group. I think we should do some real device testing at some point too. |
What is the status of this PR? @hannalaakso, @NickColley is this still being worked on. We're adding a timeout modal in our next sprint and I would like to use this component. |
@nogginbox Thanks for reaching out. This work depends on #1708 especially, and also #1722. It's unfortunately not possible to give a timeline on the work at the moment but we will pick it up when we're able to prioritise it. |
.govuk-modal-dialogue, | ||
.govuk-modal-dialogue__backdrop { | ||
position: fixed; | ||
z-index: 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Increase to 1000 so that this will appear above all other elements already in the site.
I had to do this when I've used this code as several elements floated on top of the backdrop.
z-index: 0; | |
z-index: 1000; |
|
||
// Inner content | ||
.govuk-modal-dialogue__content { | ||
@include govuk-font($size: 16); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was able to safely remove this font definition as I wanted the site's standard fonts to be used. We're a non gov body so can't use the standard GDS font and have overrides in place to not use them. This line being included broke our GDS font overrides.
@include govuk-font($size: 16); |
Hi @hannalaakso @NickColley, do you guys have any update on the timeline? |
@zaizous No update at the moment. You might find the acceptance criteria which this component will need to meet helpful if you're researching this topic. |
I’m closing this PR as it’s currently blocked by #1722 and #1708. Note for teams who are researching modal dialogues: the work done in this PR could be used as the basis for creating a modal dialogue. We would encourage teams to review:
|
Afternoon 👋
As discussed with @hannalaakso, @timpaul, @amyhupe our team has been working on contributing a new "Modal dialogue" component to the Design System.
Sadly I'm going to be handing over work on this to @FeyAgape and @Ash-Wilson so this is still a draft for now, but more work to come!
Acceptance criteria
See alphagov/govuk-design-system-backlog#30 (comment)
Changes to GOV.UK Frontend
To support a modal component I've had to enhance GOV.UK Frontend slightly:
position: fixed
content{% call macro() %}{% endcall %}
But here's a draft pull request where we're up to anyway.