Popup-like components in Material-UI render on an invisible top overlay that is programmatically appended directly to body. For example, when a SelectField or DropDownMenu is opened:
<body>
<div id="app-container>
<div ...>
<!-- This is where the SelectField is rendered. -->
</div>
</div>
<div ...>
<!-- This div is: -->
<!-- (1) where the visible dropdown is rendered when open -->
<!-- (2) a full-screen overlay -->
<!-- (3) removed when the dropdown is closed -->
</div>
</body>
This mechanism is in place so that (1) the user can "click away" to close the open dropdown, (2) the user does not accidentally click on another control when attempting to close the open dropdown.
However, I need to allow clickaways to actually hit the underlying element, without being blocked by the overlay. This can be accomplished in the Popover component by using the useLayerForClickAway prop:
<Popover useLayerForClickAway={false} ... >
...
</Popover>
Unfortunately, no such option exists for SelectField or DropDownMenu (or seems to exist, it's not documented), and I need one of these instead of a Popover.
Moreover, I don't seem to find any option that allows to reliably identify the overlay element created by the dropdown, beside getting the last element in body immediately after the dropdown opened (which is hackish at best). Material-UI also doesn't seem to offer a way to manually override the inline styles of this overlay element.
So, what's the "appropriate" way to disable the invisible overlay, and allow clicks when the dropdown is open?
Related
I have a list of offers, each of them with a delete button, that once clicked opens a modal with another 2 buttons: delete and cancel.
When the modal has opened, I want to be able to tab to these 2 buttons first, but at the moment tab continues with the other tabbable elements that are after the delete button in the row, eventually hitting the buttons after completing the tab round.
Is there a way of achieving that?
<section tabIndex="-1" role="dialog" onClick={onCancel}>
<section role="document" onClick={(e) => e.stopPropagation()}>
<Button tabIndex="0" secondary className={Styles.cancel} onClick={onCancel}>
{t("abort")}
</Button>
<Button tabIndex="0" secondary className={Styles.delete} onClick={onDelete}>
{t("deleteModal.CTA")}
</Button>
</section>
</section>
Tab continues wherever the focus is set. Your code already includes tabindex="-1" which allows to focus the dialog element after opening it, with .focus() in JavaScript.
If the dialog content includes semantic structures […] then it is advisable to add tabindex="-1" to a static element at the start of the content and initially focus that element.
In your case, the dialog is really simple, and it would be more advisable to focus the primary button instead of the dialog itself.
See Dialog (Modal) from the ARIA Authoring Practices Guide (APG)
Your dialog needs an accessible name. Usually a aria-labelledby attribute is used to refer to the dialog’s title element, if you don’t have a visual title you can use aria-label.
It is also important that you establish a focus trap in the dialog, meaning that one cannot leave the dialog by means of tab, but only by means of close. Usually the focus wraps around back to the dialog-element.
Browser support for the native <dialog> element recently got better and you might consider using that one.
I have a web page side navigation menu in the left and content pane in the right.In the content pane there is a text and a iframe.When going through nav menu with tab and enter any menu option relevant content will be loaded to the content pane.Even content loaded to the pane tab focus is on the navigation menu.
I need to give the tab focus to the text or to the iframe in the content pane whenever content is newly loaded.I tried with tabindex ..
test text for tab focus
<div id="content-frame" class="fill center-content">
<div id="content-frame-loading" class="load-img"><img ng-src="{{loadingIconUrl}}" alt="{{$scope.loadingSpinnerAltText}}"></div>
<iframe id="centerIframe" name="centerIframe" class="fill content-frame" src="" orientable height="100%" width="100%" ng-style="{'height' : settings.iFrameHeight}" webkitallowfullscreen="true" mozallowfullscreen="true" allowfullscreen="true" allowtransparency="true">
</iframe>
</div>
Above is the code block of the content pane.
only setting tabindex will not solve the purpose. tabindex will add the dom node into the tabbing sequence and will be focused on clicking tab when its turn comes according to the sequence.
Here you are setting the tabindex but additionally you also want the content to get focused automatically, so you will have to write some script to achieve that.
So if your content is part of a component, you can manually focus the desired element on load of that component in any of the life cycle hooks.
that way, when you click the navigation menu option, your content's component gets loaded, its lifecycle hook gets executed where your script to focus the desired element gets executed and focus gets onto that element.
I have used react-modal for modal dialog,
and in my reactjs render(), i have the following modal
return(
<ReactModal
isOpen={this.state.showModal}
contentLabel="Minimal Modal Example">
<button style={styleClose} onClick={this.handleCloseModal}>
CloseModal</button>
{items}
</ReactModal>
)
But when this dialog open, the items behind are overlapping, how can I have only dialog being visible and not the background elements?
The elements that are overlapping are the components that have radiobuttons. Normal text are not overlapping. How can i make these buttons not to overlap?
I tried setting the zIndex and apply styling but that doesnt work.
Also how can i have close when i also click esc on keyboard ?
The first part of your question needs more info for clarification, I can answer the second part:
Add this to your modal element:
shouldCloseOnEsc={true}
If you haven't, remember to also add onRequestClose={<your component method that hides the modal}
Check this link for more usage: http://reactcommunity.org/react-modal/#usage
Really simple question here...note the code snippet first:
$('#gasmask').on('click', function(){
$('#gasmask').modal('show');
});
Clicking the element with an ID of gasmask causes the Semantic-UI modal to show, quite nicely. The issue is that after I click away, causing the modal to disappear, so the does the original element...
Before click:
<div class="content">
<img alt="Gasmask" class="fademein3 ui image" id="gasmask" src="https://s3.amazonaws.com/verumdesigns/gasmask.jpg" style="visibility: inherit; opacity: 1;">
</div>
After modal closes:
<div class="content">
</div>
It just straight up vanishes from the DOM. What's the dealio?
Semantic UI moves the modal contents around in the DOM, as you have figured out. I believe this is so that the modal gets the appropriate inherited styling to display as intended, rather than inherit whichever "component" embeds the modal.
There is an option called "detachable", which you could use like such:
$('.modal')
.modal({
detachable: false
})
.modal('show')
This would ensure that your model contents stay where they are. This has hardly ever been a good option for me, because the modal inherits the styling I use for the component that embeds the modal, which just mucks up the modal. Maybe there is a way to prevent that with CSS?
If CSS can't come to the rescue, then it's up to redesign your frontend.
For me, that meant turning the modal into a singleton component that I can instantiate from another component, passing whichever values are needed to display the modal. Obviously details on that will differ on whether you are using Riot, React, Angular, ...
Another option, if you only have one modal and you don't care where it lives in your DOM, is to id your element with the HTML id attribute. That way you don't care where it is relative to your component.
My store's collection pages have the quick-view feature where hovering over products images allow you to click 'Quick View' to open a modal dialog window with summary info about the products. This is done with the leanModal plugin.
See: http://froy.com/collections/beds-mattresses for example. Store is powered by Shopify.
The problem is, when the page initially loads, all the elements within the modal are loaded despite being hidden. This unnecessarily slows down the site. I'd like to load the contents within the modal only after the user clicks on 'Quick View.'
<div class="quick_shop"> <!--This is the modal trigger-->
<div class="quickview-text">Quick View</div>
</div>
<div class="modal">
<!--All contents of the modal dialog window go in this div-->
</div>
Script:
$('.quick_shop').leanModal(); //Calls the function on the modal trigger
(function($){$.fn.extend({leanModal:function(_1)...});})(jQuery);
//The above line of code is for leanModal. I didn't paste entire thing cause it's long
Any help would be much appreciated! I'm new and learning so this is all very exciting.
The purpose of the modal div is to have a precise view on one specific element.
In your case (on the webpage you provided), the modal is loaded for each element, which breaks the sense of what you're trying to achieve.
I've never used the leanModal plugin but I guess you could try doing the following:
When the "Quick view" is pressed, find the closest element with jQuery .closest() method by searching the element with class .quick_shop, THEN leanModal that single element and display it:
$(".quickview-text").on("click", function(e){ $(this).closest(".quick_shop").leanModal(); //Then display it with .show() if it's hidden by default });
Once the modal is closed you can delete the element instead of hiding it with the jQuery's remove() method.