-
Notifications
You must be signed in to change notification settings - Fork 683
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
The Dialog Component #2365
The Dialog Component #2365
Conversation
…s Update Modal to use Dialog
|
I have a comment: with I have looked at With this you don't need to embed a form element to the dialog itself. Regards, |
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.
@supernova-at Nice work so far. As discussed, i think the it's fine to render a form as a child here, but I do prefer the alternate masking approach, in which the mask is a child of the dialog.
top: 0; | ||
left: 0; | ||
height: 100vh; | ||
width: 100vw; |
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.
Consider 100%
instead of using viewport units. Apparently mobile browsers have issues with viewport units, especially vh
.
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.
Fixed in d5841ab.
grid-template-areas: | ||
'. ......... .' | ||
'. container .' | ||
'. ......... .'; |
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 certainly one approach, but I think this is far too tricky for a one-element grid.
Try removing grid-template-areas
, grid-template-columns
, and grid-template-rows
, then using align-content
and justify-content
to center the dialog element.
Remember to remove grid-area
from the grid item (.container
) when you do so.
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.
Fixed in 405e489.
max-height: 90vh; | ||
/* Minimum keeps a 16:9 aspect ratio. */ | ||
min-height: 416px; | ||
width: 740px; |
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.
These values feel pretty arbitrary to me, given that we often aim to stick to increments of 1rem
. What about 768px
by 432px
, which is 48rem
by 27rem
?
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.
Fixed in d5841ab.
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 for the fix. When we reviewed this with UX, didn't we propose shrinking the dialog to something like 640x360?
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.
Yes - that change is in here: 805a399.
grid-template-rows: auto 1fr; | ||
grid-template-areas: | ||
'header' | ||
'body'; |
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.
Likewise, I don't know that grid-template-areas
provides value here, since repositioning the header and body of a dialog doesn't really qualify as a use case. Consider dropping this and just allowing grid-template-rows
to set up the tracks for grid items to flow in naturally.
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.
Fixed in d5841ab.
|
||
/* The Header is itself a grid container for its children. */ | ||
display: grid; | ||
grid-auto-flow: column; |
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 good. It's probably also a good idea to define the columns here.
/* could even leave off the last `auto` */
grid-template-columns: 1fr 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.
Fixed in d5841ab.
.body { | ||
grid-area: body; | ||
|
||
padding: 1em; |
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.
Likewise, increments of rem
, so probably at least 1rem
here.
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.
Fixed in d5841ab.
*/ | ||
const Dialog = props => { | ||
const { | ||
areButtonsDisabled, |
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 see what your intent is here, but this doesn't feel right. If i were writing this component, I might have called this one shouldDisableButtons
, since props are essentially recommendations that the component uses to determine final state.
// disable the mask if a parent says we should
const maskIsDisabled = isModal || shouldDisableButtons
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.
Fixed in d5841ab.
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.
Fun side note: I changed this and a snapshot that I wasn't expecting to change changed and I was able to fix the bug before anyone else ever saw it - yay snapshots!
areButtonsDisabled, | ||
cancelText, | ||
children, | ||
confirmText, |
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's good to be able to customize these buttons. Perhaps we should also have another prop for whether to render them at all?
const { includeButtons } = props
const buttons = includeButtons
? // create button elements
: null
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.
Maybe it makes sense to have own buttons as a list with your own actions make it very changeable
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 issue with accepting any list of buttons is that this component is responsible for defining and attaching listeners to at least the standard buttons. If button customization is important, we may need a slightly more sophisticated API.
const { buttons } = props
const buttonElements = Array.from(buttons, button => {
const { key, props } = button
// `DialogButton` could render a `Button`,
// attach a listener, and call an optional callback
return <DialogButton key={key} {...props} />
})
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 we decided against an option supporting this.
.confirmButton { | ||
composes: root_highPriority from '../Button/button.css'; | ||
overflow: hidden; | ||
} |
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.
Do we really need to do this? I have a feeling these overrides aren't necessary and may be working around either a bug or a mistake.
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 I don't know why I couldn't get <Button priority="high">
to work. I'll try again.
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.
Resolved in 79dc8d1.
Co-authored-by: Jimmy Sanford <[email protected]>
PR Updated:
Unfortunately I still can't get the buttons in the button container to behave how I want them to when long button texts are set. The easiest place to see this is in the "Customizing the Button Texts" story in Storybook: I'm pretty confident now that the problem is in the interplay of our If someone cough @jimbo cough wants to mess around with it further that would be awesome but since I've been looking at it for two days straight now I'm inclined to go with the simple approach of stacking the buttons on mobile and putting them side-by-side on desktop, no matter how long their content is. |
Performance Test Results The following fails have been reported by WebpageTest. These numbers indicates a possible performance issue with the PR which requires further manual testing to validate. https://pr-2365.pwa-venia.com/venia-tops.html : LH Performance Expected 0.75 Actual 0.65 |
I think that's a reasonable solution, and I'd defend it. I'll riff on the layout for a bit and see if I can identify what's causing the buttons to not participate correctly, but we should probably just take your solution and switch from columns to rows on mobile. |
…le loading shipping methods
I believe the build is failing due to the lighthouse performance check. @dpatil-magento I thought this was more of a warning than an error? |
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.
@supernova-at Good changes, I think we're ready to work with this. Should be easy to apply new styles when they're ready. 👍
@supernova-at In mobile Shipping methods button are vertically displayed instead of horizontal. |
Description
This PR introduces a new component into VeniaUI: The
Dialog
component.This component is meant to standardize the way Venia shows Dialogs all over the application and make them easier to use for developers. Now when you need a Dialog you can simply
Instead of having to write or copy / paste a bunch of JSX and matching CSS.
The Storybook entries included in this PR illustrate the capabilities of
Dialog
:isModal
prop whether clicking the mask closes the Dialogprops.children
passed to it, and appends "Cancel" and "Confirm" buttons at the end, sometimes requiring the user to scroll to see them1onCancel
callback functiononConfirm
callback functioninformed
Form
componentForm
componentonConfirm
callback is passed to the internalForm
element via itsonSubmit
prop. In other words, clicking the "Confirm" button will submit the form1: This is per UX. The "Cancel" and "Confirm" buttons should not be sticky / always appear.
This PR also implements this new
Dialog
component on the Checkout page Shipping Methods section. Edit shipping methods on the checkout page to see it.Note that there are other instances that should be converted that have been broken out into their own issues: Shipping Information and Payment Information on Checkout Page, and the Product Filters.
Feedback Requested
Here are some specific areas to focus on for feedback:
The Internal Form
Dialog renders a
Form
element internally.For Buttons' Sake
This is primarily so that the Dialog buttons can be part of and control the
form
. For example, the close "X" and "Cancel" buttons reset the form, and the "Confirm" button submits the form.The obvious alternative is to have the caller pass in a form of their own as
children
to the Dialog.But then the Dialog buttons would be outside of the form and wouldn't have any way to access / control it.
There are some options to explore here, like having the
Dialog
export its buttons separately for consumers to inject into their forms:This pattern feels pretty non-idiomatic to me though, so I chose not to introduce it.
But the Mask
Unfortunately the button that is the mask is outside of the form, and therefore cannot / does not reset the form when clicked.
You can reproduce this by changing a form field value and clicking the Mask to close the Dialog.
When you re-open the Dialog, your change persists. This is in direct contrast to how the close "X" and "Cancel" buttons work (they reset the form back to its initial values on click).
Here's the tradeoff I ran into:
Update: We've decided to go with the Mask inside the Form. It isn't bad semantically.
Props to the Form
Currently,
Dialog
supports setting theinitialValues
andonSubmit
props of theForm
via itsinitialFormValues
andonConfirm
props respectively.But
Form
does support other props. ShouldDialog
take aform
prop (or similar) that it just spreads out onto theForm
?This would allow for more flexibility in working with
Dialog
's internalForm
at the cost of having a slightly more convoluted call site:Update: Support added for the pass through of
formProps
toDialog
's internalForm
in 5d8032b.Dialog Buttons
Should
Dialog
be configurable to show only one button? To not show any buttons (just the close "X")? These could be useful for more informational-type system messages. There is overlap withToasts
here.Update: For now the Dialog will always show two buttons. In Modal mode, where the user is intentionally forced to interact with the content, the close "X" button is not rendered and the mask behind the dialog is not clickable. This makes the "Cancel" button an explicit, intentional rejection by the user and the "Confirm" button an explicit, intentional acceptance.
Related Issue
Closes PWA-486.
Acceptance
Verification Stakeholders
@soumya-ashok @jimbo
Specification
Verification Steps
Storybook
To see the Storybook for the
Dialog
component, runand click on
Dialog
in the left navigation.The Checkout Page
The
Dialog
component is also implemented on the Checkout page, for editing shipping methods./checkout
pageScreenshots / Screen Captures (if appropriate)
This new
Dialog
component as seen on the Checkout page:Checklist