React component prop style - reactjs

I am using from UI Materials the
(https://material-ui.com/demos/text-fields/)
component and I want to style the helper text.
I've tried
pstyle = {
"& div p": {
textAlign: "right"
}
}
and then pass it as style={this.pstyle} and it does not work.
Does anyone has a solution?
Thanks!
Update: This is the component and it's props: https://material-ui.com/api/text-field/
What am I trying to style is the helperText prop

first of all welcome!
As OliverRadini said, you cannot use & in the way you proposed, and this makes sense, since you are directly targeting a specific element, it is not required to start making complex selectors.
Talking about your task at hand, remember that TextField component in Material UI library is just a wrapper component for a complete form control including a label, input and help text.
Bare in mind that using Material UI components is aligned with Google's Material Design patterns, so the idea is to stick with their guidelines, but if you want to customize, this is what you can do, either use FormHelperTextProps as prop in the TextField or instead of using the TextField wrapper, just break it into its pieces (FormControl, InputLabel, Label, FormHelperText)
The first option is the easiest way to do it for simple customization as the one you want to achieve. Try something like:
Your CSS class
projDescHelperText: {
textAlign: "right"
}
Your Component
<TextField
id="project-description"
label="Project Description"
helperText="(0/300)"
FormHelperTextProps={className={classes.projDescHelperText}}
value={this.state.description}
/>
If you have some of your code you can share, I would be able to better tailor a response to you

I think you should set { "p": { textAlign: "right" } } instead of { "& div p": { textAlign: "right" } }

You should use:
<div styles={{textAlign: 'right'}}>
<p> 0/300</>
</div

So I've done it like this:
import { withStyles } from "#material-ui/core";
const style = {
smth: {
"& p": {
textAlign: "right !important"
}
}
}
<TextField
className={classes.smth}
/>
export default withStyles(style)(CustomTextField);
seems to be working fine for now. Thanks all for the help and the promptitude and #rdarioduarte your solution helped me a lot. Thanks a lot guys!

Related

React/Typescript/mui- Help understanding abstraction over a third party component

We started a project and implemented several pages using material ui's React library. We use React hooks exclusively. I was told to create a wrapper around the mui DataGrid. The purpose behind the decision was that a particular page would need functionality that the DataGrid probably doesn't have. A special case, and one which we don't know the specific needs of at this point. I'm a relative newbie with React and Typescript and I don't even know how you go about creating wrappers, especially with a component as large and feature rich as mui's DataGrid. Where to start? I started like this:
import {
DataGrid as DataGridWrapper,
GridColumns,
GridLocaleText,
GridRowsProp,
GridFilterModel,
GridSortModel,
GridCallbackDetails,
} from "#mui/x-data-grid";
import Tooltip from "#mui/material/Tooltip";
import IconButton from "#mui/material/IconButton";
import AddBoxIcon from "#mui/icons-material/AddBox";
import { esES } from "#mui/x-data-grid";
import { enUS } from "#mui/x-data-grid";
export interface GridProps {
style?: React.CSSProperties;
gridColumns: GridColumns;
gridRows: GridRowsProp;
gridPageSize?: number;
showAddButton?: boolean;
onAddButtonClick?: () => void;
onFilterModelChange?: (model: GridFilterModel, details: GridCallbackDetails) => void;
onSortModelChange?: (model: GridSortModel, details: GridCallbackDetails) => void;
}
function DataGrid({
style,
gridColumns,
gridRows,
gridPageSize = 10,
showAddButton = true,
onAddButtonClick,
onFilterModelChange,
onSortModelChange,
}: GridProps) {
const strings = useLocalizedStrings();
// use text translations from the grid and apply them to all pages
let localeTextTranslations : Partial<GridLocaleText>
if (strings.getLanguage() === "es") {
localeTextTranslations = esES.components.MuiDataGrid.defaultProps.localeText;
} else {
localeTextTranslations = enUS.components.MuiDataGrid.defaultProps.localeText;
}
return (
<>
{showAddButton && (
<div style={{ textAlign: "right" }}>
<Tooltip title="Add">
<IconButton
aria-label="add"
color="primary"
onClick={() => {
onAddButtonClick?.()
}}
>
<AddBoxIcon />
</IconButton>
</Tooltip>
</div>
)}
<div style={{ height: 700, width: "100%" }}>
<div style={{ display: "flex", height: "100%" }}>
<div style={{ flexGrow: 1 }}>
<DataGridWrapper
columns={gridColumns}
rows={gridRows}
style={style}
hideFooterSelectedRowCount={true}
pageSize={gridPageSize}
onFilterModelChange={onFilterModelChange}
onSortModelChange={onSortModelChange}
/>
</div>
</div>
</div>
</>
);
}
export default DataGrid;
At this point I started wondering what the benefit of doing this is, if I'm simply duplicating the mui interface. Plus, I don't know how to handle the typings. Do I create new types that wrap mui's types? That seems like it could get complicated pretty fast as everything in mui has underlying types and so do those types, many levels deep. Or should consumers import the types from mui directly like I have here where I'm typing my props as mui types (but that seems wrong and against the idea of abstraction).
So if I'm not really encapsulating logic and am instead simply renaming props, does this even make sense to do? How does one approach such a task? In the end, this just feels weird so far. To make all pages use something in basically the same way you would use the actual mui grid. I feel like I'm missing something.
Can someone give me an example of some patterns I would use to make this actually be the start of a proper wrapper? And how to handle the typings required by mui and translating those to what's exposed to consumers? Or any thoughts at all? I searched for creating 3rd party wrapper components in React and only saw stuff with classes and higher order components. Nothing with hooks. In the end, I guess my specific questions are:
how to create a basic wrapper?
how to handle typings of the thing you wrap?
any considerations I should keep in mind?
I almost don't know what I don't know so it's difficult to be specific. I wish I could find some examples.

DRY with Props in React

We have a component. Let's call it <MyComponent>. It is being used in a dozen different files. We wanted to change the styling on this component. Fortunately, the component exposes a property stylingProps. So, we wrote the following in each of the dozen files:
public render() {
const styles = {color: "purple", background: "gold"}
return(
<MyComponent
otherPropsUniqueToEachfile={"somethingOrOther"}
styles={styles}
>
"Some text"
</MyComponent>
)}
How should I refactor this so that I am not adding the constant styles with the exact same values in a dozen different files? What is "the React Way" to do so?
I like to create common components for the app, which use the library components under the hood. The rest of my app uses these common components without any knowledge of the external library component. Then, I can use my common component to create an interface that my app can use to control its appearance or behavior in different states.
For example, let's pretend your <MyComponent> is a button coming from a component library. In this example, let's pretend your app has three button variants, that I'll call "primary", "secondary", and "default".
The goal is that in your app, you could import your custom Button component, and use it like this:
<Button variant="primary" arbitraryProp={data}>Button Text</Button>
And the variant="primary" will color/style it a particular way.
One way to build the Button component to handle this would be:
import ComponentLibraryButton from "component-library";
import React from "react";
function Button({ variant, ...rest }) {
const styles =
variant === "primary"
? { color: "purple", background: "gold" }
: variant === "secondary"
? { color: "green", background: "blue" }
: { color: "black", background: "gray" };
return <ComponentLibraryButton {...rest} styles={styles} />;
}
I like creating a layer like this that sits between component libraries and the rest of my app. It makes it easy to create custom control like this, but also to swap out a new component library down the road without having to change all of the files that use components.

How to hide MUI React ListItem?

I have the following:
<ListItem key={name} hidden={true} aria-hidden={true}>
name
</ListItem>
but the ListItem is still showing up. How can it be hidden?
As far as I know, there is no hidden props on the ListItem component in Material-UI, so you will have to implement you own behavior to hide the ListItem :
You can not render the concerned ListItem at all.
You can render it but hide it using some CSS. See How to display and hide a div with CSS?.
I was looking to programmatically hide a Material-UI FormControl component, and found the same issue (i.e. the lack of a hidden prop).
What worked for me was to add a method that returned the appropriate class string, based on whether I wanted to show the component in question or not.
For example, with styles like:
const styles = createStyles({
...
formcontrol: {
minWidth: 120,
margin: 10
},
invisible: {
visibility: "hidden"
},
});
I added this to my component class:
getStyle() {
let cls: string;
if (this.props.whatever) {
cls = this.props.classes.formcontrol;
} else {
cls = this.props.classes.invisible + " " + this.props.classes.formcontrol;
}
return cls;
}
And then reference that from render() when creating the component I want to sometimes hide:
<FormControl className={this.getStyle()}>
...
</FormControl>
This should work for any styled MUI component.
(Side-note: the display prop appears from the docs to do this, but didn't work for me. Perhaps it works only for Box components, which happen to be what's used in all of the examples in the docs. This is worth further investigation which I have not yet spent the time to do.)

How to pass padding/margin as props in React-Bootstrap components

I am trying to apply margins and paddings with React-Bootstrap as props.
I passed the docs through but haven't found any mention adding padding or margin in there as it is in official bootstrap docs (3th and 4th). I know it doesn't support well Bootstrap 4, so tried with both.
I tried to pass params as p={1}, paddingxs={5} or mt='1' but it doesn't recognize any of them. More over tried to find any Spacing element in React-Bootstrap folder, but failed.
Paddings and margins work as classnames. But I feel there must be a way to it without Bootstrap classes. There must be a kind of property.
First include bootstrap CSS in your src/index.js or App.js
import 'bootstrap/dist/css/bootstrap.min.css';
Then you can style your component by passing desired bootstrap CSS class name as className prop in React, for example:
import React from "react"
import Container from "react-bootstrap/Container";
function MyComponent() {
return (
<Container fluid className="p-0">
<SomeOtherComponent />
</Container>
);
}
export default MyComponent
Above code will add p-0 CSS class to Container.
Reference
React - How do I add CSS classes to components?
React-Bootstrap - Stylesheets
You can add margin and padding by using default React's style:
const divStyle = {
marginLeft: '10px',
};
function HelloWorldComponent() {
return <div style={divStyle}>Hello World!</div>;
}
Refrenced from here
The answer is: there is no props from React Bootstrap to use margins/paddings.
You can use props for col class, but no for margins.
Example:
<Col className="col-6 col-md-3 mb-3 pt-2">
// there you have a Col component from React-Bootstrap 4
// it has some grid system classes, that you can use as props like this:
https://react-bootstrap.github.io/layout/grid/
<Col xs={6} md={3} className="mb-3 pt-2">
// but as you can see, the native classes of Bootstrap 4 like
// mt, mb, pt, pb etc, they have not a props use with
// React-Bootstrap, you have to use them like regular classes
// inside "className"
You'll want to add className="p-5" to the element. This isn't documented in react-bootstrap but it's in the original Bootstrap 4 documentation here: https://getbootstrap.com/docs/4.4/utilities/spacing/#examples
Usually, I'm able to add custom styles to React Bootstrap components by just adding them to the style param. I've put together a short example below, hope this helps.
import React from 'react';
import { Button } from 'react-bootstrap';
const styles = {
myCoolButton: {
paddingTop: "10vh",
paddingBottom: "10vh",
paddingRight: "10vw",
paddingLeft: "10vw"
}
}
const ReactButton = (props) => {
return (
<Button style={styles.myCoolButton} onClick={()=> {
console.log("Do something here!")
}}>Click Me!</Button>
);
}
export default ReactButton
You can also pass custom components (including those from react-bootstrap) into the styled-components constructor if you prefer to do it that way.
None of the jQuery-free implementations of Bootstrap (React Bootstrap, BootstrapVue or ngBootstrap) have implemented utility directives for spacing (margin/padding), simply because Bootstrap have made it unnecessary in the vast majority of cases, by providing a very intuitive set of Spacing utility classes.
All you need to do is apply the desired class.
To apply utility classes selectively, based on responsiveness interval (media queries), you could use a useMedia hook, as demoed here.
In a nutshell:
const interval = useMedia([
"(min-width: 1200px)",
"(min-width: 992px)",
"(min-width: 768px)",
"(min-width: 576px)"
],
["xl", "lg", "md", "sm"],
"xs"
);
(Based on useMedia from useHooks/useMedia).
You can now reuse this hook throughout your app to add media interval based logic.
Example usages:
// interval === 'sm' ? a : b
// ['xs', 'sm'].includes(interval) ? a : b
// negations of the above, etc...
Important: this particular implementation returns the first matching media query in the list.
If you need to map various media queries, to an object/map with true/false values, you'll need to modify getValue fn to return the entire list, along these lines:
const getValue = () => {
const matches = mediaQueryLists.map(mql => mql.matches);
return values.reduce((o, k, i) => ({...o, [k]: matches[i]}), {})
};
Working example here.
Obviously, you could expand on it and add/remove queries. However, be warned each query adds a separate listener so it could impact performance.
In most cases, the return of the first matching query (first example) is enough.
Note: if the above useMedia hook is not enough for your use case, a more robust and heavily tested solution for media-query listeners in JS is enquire.js. It's easy to use, incredibly light and thoroughly tested cross-browser/cross-device. I have no affiliation with it, but I have used it in various projects over the course of more than a decade. In short, I couldn't recommend it more.
Back to Bootstrap 4: in order to customize the $spacer sizes, follow the guide provided under Bootstrap's theming as it's actually about more than what we typically call theming (changing colors), it's about overriding default values of Bootstrap's SASS defaults, including responsivenss breakpoints, spacers, number of columns and many, many others. The one you're interested in is $spacer.
Simply write the overrides into an .scss file and import it in your root component. Example.
Note: a (simpler and more intuitive) option to customize Bootstrap is to do it visually, using bootstrap.build but it's typically a few minor versions behind (i.e. Bootstrap is now at v4.4.1 and the build tool is at v4.3.0).
The build customizer provides intuitive controls and real time visualization.
It allows export as .css or .scss.
Just try this out once according to your input and still if face any issue you can reach out.In below we have increased the .col padding with .px-md-5 and then countered then with .mx-md-n5 on the parent .row.
JSX:
import React from 'react'
import { MDBContainer, MDBRow, MDBCol } from 'mdbreact';
const SpacingPage = () => {
return (
<MDBContainer>
<MDBRow className="mx-md-n5">
<MDBCol size="6" className="py-3 px-md-5">Custom column padding</MDBCol>
<MDBCol size="6" className="py-3 px-md-5">Custom column padding</MDBCol>
</MDBRow>
</MDBContainer>
)
}
export default SpacingPage;
If you still have any kind of doubt on this then feel free to ask .

How can I access to change styles of inner items of a component in react and material ui?

How can I access to inner css classes of children of a component and add or change styles to/of them? like I want to change and customize material ui stepper steps circle font size and color and so on.
How can I write css classes like bellow:
.stepper circle {
font-size:18px;
}
or
.stepper .text {
font-size:18px;
}
thanks.
Thanks to #spakmad's answer, but that's not exactly what I meant, maybe my question was not clear enough. I meant how to write above mentioned CSSs in material ui object style classes format(classes injected with withStyle HOC).
I found my solution:
stepper:{
'& circle':{
fontSize: '18px'
}
}
and
stepper: {
'& .text': {
fontSize: '18px'
}
}
The very straightforward way to do it without having to worry about classes is by using the material-ui style prop. Like so,
<Stepper style={{ fontSize: '18px' }} />
This applies a style to the root element, which I assume to be a div or container of sorts, although it probably varies by the component.
More specifically, and what you probably want to do is use material-ui classes prop. That is, since you know exactly what classes you want to override, you can do so as follows,
<Stepper classes={{ text: { fontSize: '18px' }}} />
I use text here as a classname because in the question, .text appears to reference and already existing class. Since you're trying to increase the size of the font in this svg that comes with the Stepper. You'll need to get the class name applied to the svg and override it. In this case, one of its classnames is MuiSvgIcon-root-184 so you would expect to be able to do,
<Stepper classes={{ MuiSvgIcon-root-184: { fontSize: '18px' }}} />
This classname however is generated by material-ui dynamically based on the layout resulting from props and could be different across all renders.
TLDR
So, trusty className component and writing some css and component JSX as follows.
<Stepper className={'customStepper'} />
.customStepper svg: {
font-size: '18px !important',
}
You need to include !important to make sure this style is respected. Material UI by default puts its styles last in the document so they're normally overwriting anything else, but the !important spec should override the override.

Resources