I have a modal that pops up with tab-able elements. Is there something like jQuery's :focusable or pointer-events: none that would allow me use CSS to disallow focusing on items underneath the overlay?
edit: The problem with a JS based approach (and selectors), is that each rerender with React, the query selector would have to be run through again. I don't have control over the component rendering this modal.
You want to do something along the lines of:
const inputs = [...document.getElementsByTagName('input')];
inputs.forEach((input) => input.setAttribute('tabindex', '-1'));
const modalInputs = [...document.querySelectorAll('.my-modal input')];
modalInputs.forEach((input, index) => input.setAttribute('tabindex', index));
Full Example https://codepen.io/bradevans/pen/GGYxrg
Edit: I hadn't seen the reactjs tag until OP commented... I'd utilize the Modals componentDidMount lifecycle method to change the underlying DOM inputs tab indexes and change the modals at the same time or using internal state....
You may also want to store the old tab indexes and reapply them on componentWillUnmount();
Related
I've got a dark mode switch that I want to style according to what theme the user has stored in localstorage. It works fine until refresh. Somehow I think my theme context is undefined so my dm const always favours the second value in the ternary.
import styles from "./ThemeSwitchToggle.module.scss"
const { theme, setTheme } = useContext(FormatContext)
// Context updated in another component based on localstorage
const dm = theme === "light" ? styles.Light : styles.Dark
// Always favours second parameter
<div className={`${styles.themeSwitch} ${dm}`}
<div
className={`${styles.themeSwitchDot} ${dm}`}
</div>
</div>
Toggle style in dark mode:
Toggle style in light mode:
After refresh if in light mode when refreshing (somehow uses styles.Dark even though theme = "light")
styles.Dark favoured
Refreshing in dark mode applies the correct styles since it always favours styles.Dark. If i switch places on the ternary, the opposite problem occurs.
E.g:
const dm = theme === "light" ? styles.Dark : styles.Light
Result, after refresh in dark mode:
styles.Light favoured
It also throws the warning:
Warning: Prop className did not match.
Server: "ThemeSwitchToggle_themeSwitchDot__uot4R
ThemeSwitchToggle_Light__nL8dx"
Client: "ThemeSwitchToggle_themeSwitchDot__uot4R
ThemeSwitchToggle_Dark__JtIx9"
I think I understand the issue, that next essentially prerenders the page before the theme context (FormatContext) is read/initialized, and then client-side rendering takes over and updates the component correctly (but somehow does not apply the right style), but this part of next is new to me.
How does next actually handle renders when the style is applied like
this?
Does this have any other implication aside from just styles? Is
the serverside content rendered before contexts are initialized every
time?
Side note: the actual functionality is entirely based on animations, which I've not included here; but essentially, this is only to apply the style initially. When clicked the animations take over and overwrite the styles.
ThemeSwitchToggle.module.scss
So a little disclaimer: I am completely and utterly self taught. Bear over with me if I'm being a clown.
Anyways, I am currently working on a some platform and in need for a dropdown functionality. That's simple right? Just use HTML5 select tag. However option tags can't be styled :>
So onwards to build my own. The HTML5 select tag uses keyboard input (up/down/enter) for those with disabilities, and I thought I would implement that too. That did present a problem though: The :hover selector collided with my custom attribute, which I use to style keyboard selected items (&[data-selected=true] to be precise).
So onwards to implement my own :hover. And this is where my bewilderment starts.
const handleChildMouseOver = () => {
const items = Array.from(listItem.current?.children!); // The wonders of typescript XD
for (const item of items) {
if (item === event.target) {
item.setAttribute("data-selected", "true");
} else {
item.removeAttribute("data-selected"); // I'm removing the attribute, rather than toggling it, because I got components with 3 states: On, off, and default.
}
}
}
(...)
<ul css={css.list} /*emotion prop*/ data-toggled={toggled} /*parent state*/ onMouseOver={handleChildMouseOver}>
{children} // parent prop
</ul>
So it works as intended, which is fine. But I recall from my pre-react days that you should never manipulate the DOM in loops, as it causes repaints on every iteration. However when I look at the Dev Tools performance profiler, I barely see any "Paints", 8 or so, even when I'm switching hover targets like a madman. What I do see is one million "Composite layer". Oh, and as a bonus React doesn't re-render. Which is fine right? 'Cause I'm not really changing the state of anything, just adding some CSS.
So my question boils down to: Am I being bonkers or smart?
N.B.: I would love to share the actual component, but seeing as this is my first post on stackoverflow, I've got no clue how you do those fancy script tag. Well github is involved somehow, I know that much 🤔
I have a very niche use-case. I have to add a modal animation like this:
regular css animation
But I need to have a component (our own filter component for a datatable) inside said modal.
So I need to use the ModalService. But this service is only attaching my custom config like this:
toggleFilter = () => {
const modalOptions: ModalOptions = {
initialState: {
labels: this.datatableLabels, // needed for filter to have labels
filterGroups: this.filterGroups // needed to add filterGroups
},
class: 'filter-modal' // this sould be my custom class
};
this.bsModalRef = this.modalService.show(FilterComponent, modalOptions);
}
to modal-content and the above mentioned animation and styling uses divs above that. Not only it's working when encapsulation set toViewEncapsulation.None then it screws our other modals as well, since I cannot apply correct classes to the one I need to mess with.
How can I overcome this issue I'm having?
Instead of using the ModalService and open desired embedded component within the modal. You can basically inject the desired component into the body of the modal while using directive instead -> Here you are declaring the whole modal layout -> you can modify all the related classes so it's easier to modify a modal and have your ViewEncapsulation untuched so other modals are unaffected.
Implemented following scenario
nextClassName={'text-hide'}
nextText={''}
nextIconComponent={
<RaisedButton
label='Next'
/>}
Now this provides me a Next Button with a wrapper div above button, and text-hide class is applied to that div not the button and hence border and background of next button remains as it is.
Please see screenshot http://imgur.com/a/AhBnc
make background and border outside NEXT button transparent, what should i do
The approach I have taken in this implementation is totally wrong.
What should be done is that create a custom pagination component with that component we will create a Next and Previous button and drop down select list for page number, and then include that custom component in the Griddle section
The value passed to customPagerComponent should be a React class, not simply jsx. To take your first example you would probably want to do this:
class MyCustomPagerComponent extends Component {
// boilerplate react stuff
render() {
// jsx for your component
}
}
Then in your Griddle jsx you would want to do:
import MyCustomPagerComponent from 'path/to/component';
<Griddle
...
customPagerComponent={MyCustomPagerComponent}
>
Both next and previous button will come in this new custom pagination component.
More info on this Griddle Issue
https://github.com/GriddleGriddle/Griddle/issues/530
I have an ExtJS form that uses hbox-layout containers to create sentences that contain form inputs and there is a requirement to disable the form under certain conditions. The hbox-layout containers have a series of radio, text, checkbox, and textfield components. You can see an example on jsfiddle.
This is an answered question here on SO that doesn't fully work for me because if you disable something that isn't a field (like the text component I'm using) the disable style is different - it appears to mask the component instead of just graying out the text. When nested components are disabled, the mask gradients stack. Examples of this scenario are illustrated on this jsfiddle.
Is there a way to override how text handles its styling when it becomes disabled? I think that may be the easiest solution.
You'll have to handpick each style fix, but yes that's completely possible. Just addCls to give a hook for your CSS...
For example, using the following CSS:
.my-disabled-ct text {
opacity: .3;
}
You can give a similar disabled look both to fields and text items with the following code:
var rootCt = Ext.getCmp('lotsOfItems');
rootCt.query('field').forEach(function(field) {
field.disable();
});
rootCt.query('container').forEach(function(ct) {
ct.addCls('my-disabled-ct');
});
You should probably avoid using disable on field since Ext put a mask over them then (though you could probably hide it with CSS).
You could add the class and target the CSS directly to text items however, why not? In this case, you would query for 'text' and use addCls on them, with this kind of CSS:
text.my-disabled-cls {opacity: .3;}
That goes without saying that you'll restore your components look to "not disabled" by removing the CSS class with the same query and the removeCls method.