You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Discussion of a new consistent modal API to cover:
a11y wiring
level of complexity for inexperienced developers
UX restrictions on what a developer can and can't do
Below are several options for APIs.
Modal is controlled by state
Each usage must define a state to link a modal to a trigger.
const[open,setOpen]=useState(false);(// Your trigger<ButtononPress={()=>setOpen(true)}>Open modal</Button>// Your modal contents<Modalopen={open}onClose={()=>setOpen(false)}><InformationDialog/></Modal>)
Developer is expected to be responsible for adding all aria tags and updates. A more realistic and compliant implementation will look like the below example.
Increases complexity of code reviews
Increases potential for mistakes by inexperienced developers
const[open,setOpen]=useState(false);(// Your trigger<ButtononPress={()=>setOpen(true)}aria-expanded={open}aria-controls={open ? 'my-unique-id' ? undefined}>Openmodal</Button>
// Your modal contents<Modalid="my-unique-id"open={open}onClose={()=>setOpen(false)}><InformationDialogaria-labeledby="my-unique-id"/></Modal>)
Note: any implementation should still allow experienced developers to break out of common usage and have a controlled modal, as long as the requirements for compliance are very clear.
Modal is controlled by state + required ref
Alternative of the previous example where a ref is required to associate trigger to modal.
const[open,setOpen]=useState(false);constref=useRef<Button>(null);(// Your trigger<Buttonref={ref}onPress={()=>setOpen(true)}>Open modal</Button>// Your modal<ModaltriggerRef={ref}open={open}onClose={()=>setOpen(false)}><InformationDialog/></Modal>)
Positives:
Can auto-wire aria onto the trigger, developer does not need to know requirements in depth
Negatives:
Auto-wiring may work outside of the typical React render flow. I'm not sure if I can consistently ensure the button is still tagged appropriately if it re-renders while the modal is active.
Developer is now responsible for the ref and state.
Modal is a button
The modal trigger may only be a button of type ModalTriggerButton and the children of that button is the dialog content.
<ModalHost><Slotname="trigger"><Button>Open modal</Button></Slot><Slotname="dialog"><InformationDialog/></Slot></ModalHost>// OR - the subcomponents-style API.// Architecturally - they're the same:<Modal><Modal.Trigger><Button>Open modal</Button></Modal.Trigger><Modal.Dialogname="dialog"><InformationDialog/></Modal.Dialog></Modal>
Positives:
DOM flexibility - host and slot components are purely functional
Additional work on the host component to ensure colocation of children.
For example, if not carefully implemented the host trigger may end up several components deep within a host, or several sibling components could be between trigger and dialog.
Not a huge problem, we establish this as a design pattern already for components that only support with collection <Item> children, e.g. lists and checkbox sets.
Modal trigger is a render prop
Modal host acts as a functional linkage and the element to trigger the modal (button or whatever) is a render prop.
Most content work will be done within the modal and not the trigger, so you'd either have an awkward inline component or you have to make a separate dialog component to write content in.
<ModalHostmodal={<InformationDialogtitle="Terms of service">
Long content would go here
</InformationDialog>}><Button>Open modal</Button></ModalHost>// vsfunctionTermsOfServiceDialog(){return(<InformationDialogtitle="Terms of service">
Long content would go here
</InformationDialog>)}<ModalHostmodal={<TermsOfServiceDialog/>}><Button>Open modal</Button></ModalHost>// vs the inverse example where trigger is the render prop:<ModalHosttrigger={<Button>Open modal</Button>}><InformationDialogtitle="Terms of service">
Long content would go here
</InformationDialog></ModalHost>
The text was updated successfully, but these errors were encountered:
Don't use Adobe's aria tags on the trigger button, it's confusing and not really standard practice. Our dialogs/modals will always require attention/interaction anyway, since they are just for confirmations, forms, and other information for intentional user review. We very intentionally don't support popup spam.
Don't support esc on form modals - can be accidentally pressed too easily and end up resetting large forms
Do return focus to the trigger once the modal is gone, which does eliminate option 1 without the ref as a candidate.
UI 5 Modal API
Discussion of a new consistent modal API to cover:
Below are several options for APIs.
Modal is controlled by state
Each usage must define a state to link a modal to a trigger.
Positives:
Negatives:
Modal is controlled by state + required ref
Alternative of the previous example where a ref is required to associate trigger to modal.
Positives:
Negatives:
Modal is a button
The modal trigger may only be a button of type
ModalTriggerButton
and the children of that button is the dialog content.Positives:
Negatives:
Modal is a slot host
The modal is a host component for content slots.
Positives:
Negatives:
<Item>
children, e.g. lists and checkbox sets.Modal trigger is a render prop
Modal host acts as a functional linkage and the element to trigger the modal (button or whatever) is a render prop.
Positives:
Negatives:
Modal is a render prop
Inverse of the prior example, the host wraps the trigger and the modal acts as the render prop:
Positives:
Negatives:
The text was updated successfully, but these errors were encountered: