ReactJS + MaterialUI: SelectField height change - reactjs

I'm using React material-ui SelectField on my page. I'm not able to adjust the height of the select field. Here is my code snippet:
<SelectField
underlineStyle={{
display: 'none'
}}
style={{
width: '49%',
padding: '0 0 5em 5em',
border: '1px solid #ccc',
borderRadius: '5px',
backgroundColor: '#fff',
margin: '16px 0px 0px 28px',
}}
floatingLabelText="Select Stack*"
value={this.state.stack}
onChange={this.handleStackChange.bind(this)}
>
{this.state.dropDownStack}
</SelectField>
My UI is looking as below
I need to reduce the height of dropdown box, how can I do it?

You have to set it using following:
<SelectField
className="custom-selectfield"
underlineStyle={{
visibility: 'hidden',
}}
floatingLabelStyle={{
top: '14px',
}}
style={{
border: '1px solid #ccc',
height: '45px',
}}
floatingLabelText="Select Stack*"
value={this.state.stack}
onChange={this.handleStackChange.bind(this)}>
{this.state.dropDownStack}
</SelectField>
There is some internal CSS applied in material UI so in order to overwrite it added a custom class to SelectPicker component named custom-selectfield
Add following lines in your CSS file
.custom-selectfield > div:nth-child(2) {
margin-top: -6px !important;
}

Related

Button on Hover shows boxShadow in ReactJs

I want this button to show boxShadow only at Hover. How to do that ?
Button code:
<CButton
style={{
float: 'right',
marginBottom: '15px',
marginRight: '30px',
backgroundColor: '#06ac06',
border: 'none',
boxShadow: '0 12px 16px 0 rgba(0,0,0,0.24),0 17px 50px 0 rgba(0,0,0,0.19)',
}}
</CButton>
Pseudo-classes like :hover are not available as inline style. You can implement the hover behavior in JS through a React state + onMouseEnter and onMouseLeave listeners (and then set the box-shadow value based on the state). But as you can see, this approach requires too much boilerplate. I would suggest using CSS-in-JS library like styled-components, utility class like Tailwind, or SCSS.
Try this code: https://codesandbox.io/s/kind-morning-s5sh64?file=/src/App.js
const [isHover, setIsHover] = useState(false)
//...
<CButton
onMouseEnter={() => setIsHover(true)}
onMouseLeave={() => setIsHover(false)}
style={{
float: 'right',
marginBottom: '15px',
marginRight: '30px',
backgroundColor: '#06ac06',
border: 'none',
transition: 'box-shadow .3s', //added for Smouth transition
boxShadow: `5px 5px 18px -3px rgba(0,0,0,${isHover ? 0.27 : 0})`,
}}
>
</CButton>
```

How to add a label to a border in mui?

I would like to have a list wrapped in a border which looks and behaves the same as a textfield border:
Example textfield and list which should have both same border.
In the image, the border around the list looks similar than the one around the textfield but most notably, the label is missing. How can I add the label and how would I set up the focus listeners to get the same hover and selection behaviour?
The typescript code for the list:
<List dense sx={{ borderRadius: 1, border: 1, borderColor: 'grey.600'}}>
<ListItem secondaryAction={<IconButton edge="end" aria-label="delete"><DeleteIcon /></IconButton>}>
<ListItemText primary="primary" secondary="group id"/>
</ListItem>
</List>
I am also open for alternative approaches. Thanks for the help.
Here is my answer using React and Mui (only for icon).
It relies on flex.
We have a main container that only draws its left, bottom and right borders.
Then we have a header container in charge of drawing the top border in two parts (before and after) and a section with an icon and title.
You can either pass an icon and a title, just a title, just an icon, or nothing at all.
borderedSection.js:
import React from "react";
import SvgIcon from "#mui/material/SvgIcon";
import styles from "./borderedSection.module.scss";
function BorderedSection({ icon, title, children }) {
return (
<div className={styles.mainContainer}>
<div className={styles.header}>
<div className={styles.headerBorderBefore}></div>
{(icon || title) && (
<div className={styles.headerTitle}>
{icon && <SvgIcon component={icon} />}
{title && <span className={styles.title}>{title}</span>}
</div>
)}
<div className={styles.headerBorderAfter}></div>
</div>
<div className={styles.childrenContainer}>{children}</div>
</div>
);
}
export default BorderedSection;
borderedSection.module.scss:
$border-color: #b2b2b2;
.mainContainer {
display: flex;
flex-direction: column;
max-width: 100%;
border-left: 1px solid $border-color;
border-bottom: 1px solid $border-color;
border-right: 1px solid $border-color;
border-radius: 5px;
margin: 1em;
.childrenContainer {
padding: 1em;
}
.header {
display: flex;
flex-direction: row;
width: 100% !important;
.headerBorderBefore {
border-top: 1px solid $border-color;
width: 1em;
border-top-left-radius: 5px;
}
.headerTitle {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
gap: 0.25em;
width: fit-content;
height: 2em;
margin: -1em 0.5em 0em 0.5em;
overflow: hidden;
text-overflow: ellipsis;
font-size: 1em;
font-weight: 600;
}
.headerBorderAfter {
border-top: 1px solid $border-color;
width: 1em;
flex-grow: 2;
border-top-right-radius: 5px;
}
}
}
usage:
import React from "react";
import BorderedSection from "./borderedSection";
import InfoIcon from "#mui/icons-material/Info";
function Example() {
return (
<div style={{ padding: "2em" }}>
<BorderedSection icon={InfoIcon} title="Icon and title">
<div>a first child with quite a long text</div>
<div>a second child</div>
</BorderedSection>
<BorderedSection title="Title only">
<div>a first child with quite a long text</div>
<div>a second child</div>
</BorderedSection>
<BorderedSection icon={InfoIcon} >
<div>Icon only</div>
<div>a second child with quite a long text</div>
</BorderedSection>
<BorderedSection >
<div>No icon and no title</div>
<div>a second child with quite a long text</div>
</BorderedSection>
</div>
);
}
Here is how it looks:
I hope it helps
I now managed to hack a solution which looks the same. I do still hope though that there is a clean way to do this: result.
<FormLabel style={{marginLeft: "0.71em", marginTop: "-0.71em", paddingLeft: "0.44em", zIndex: 2, width: "4.2em", backgroundColor: "#383838", position: "absolute", fontSize: "0.75em"}}>Damage</FormLabel>
<List dense sx={{ borderRadius: 1, border: 1, borderColor: 'grey.600', "&:hover": { borderColor: 'grey.200' }}}>
<ListItem secondaryAction={<IconButton edge="end" aria-label="delete"><DeleteIcon /></IconButton>}>
<ListItemText primary="primary" secondary="group id"/>
</ListItem>
</List>
I needed the same thing. As I was poking around I noticed that MUI accomplished this by using the fieldset tag. I created a quick and dirty component (OutlinedBox) to get this effect:
import React from "react";
import {Box, FormLabel} from "#mui/material";
const OutlinedBox = (props) => {
const {
label,
children
} = props;
return (
<Box>
<FormLabel
sx={{
marginLeft: "0.71em",
marginTop: "-0.71em",
paddingLeft: "0.44em",
paddingRight: '0.44em',
zIndex: 2,
backgroundColor: (theme) => theme.palette.background.default,
position: "absolute",
fontSize: "0.75em",
width: 'auto',
}}>{label}</FormLabel>
<Box
sx={{
position: 'relative',
borderRadius: theme => theme.shape.borderRadius + 'px',
fontSize: '0.875rem',
}}
>
<Box
sx={{
padding: (theme) => theme.spacing(1),
display: 'flex',
gap: (theme) => theme.spacing(1),
flexWrap: 'wrap',
overflow: 'auto'
}}
>
{children}
</Box>
<fieldset aria-hidden={"true"} style={{
textAlign: 'left',
position: 'absolute',
bottom: 0,
right: 0,
top: '-5px',
left: 0,
margin: 0,
padding: '0 8px',
pointerEvents: 'none',
borderRadius: 'inherit',
borderStyle: 'solid',
borderWidth: '1px',
overflow: 'hidden',
minWidth: '0%',
borderColor: 'rgba(255, 255, 255, 0.23)',
}}
>
<legend style={{
float: 'unset',
overflow: 'hidden',
display: 'block',
width: 'auto',
padding: 0,
height: '11px',
fontSize: '0.75em',
visibility: 'hidden',
maxWidth: '100%',
'-webkit-transition': 'max-width 100ms cubic-bezier(0.0, 0, 0.2, 1) 50ms',
transition: 'max-width 100ms cubic-bezier(0.0, 0, 0.2, 1) 50ms',
whiteSpace: 'nowrap',
}}><span>{label}</span></legend>
</fieldset>
</Box>
</Box>
);
}
export { OutlinedBox };
// Example usage: <OutlinedBox label="Test">Some content here</OutlinedBox>
I figured I'd post it here in case anyone needs the same thing and comes across this question. All the styling stuff was copied from the styles MUI was using. There may be a better way to read some of this off of the theme, so if anyone decides to use this you may want to tweak it some.

React Stripe Elements - set width to auto for iFrame? Elements invisible inside grid and modal

I am trying to build a Stripe form using React Elements, inside of a React Modal, with layout managed by React Grid
<StripeProvider apiKey="stripeApiKey">
<Grid
container
direction="column"
alignItems="center"
justify="center"
style={{ minWidth: '30rem', maxWidth: '100rem' }}
>
<Grid item>
<Grid
container
direction="column"
justify="center"
style={{
backgroundColor: theme.palette.primary.dark,
padding: '73px',
width: '100%'
}}
>
<Elements>
<CardElement />
</Elements>
</Grid>
</Grid>
</Grid>
</StripeProvider>
The above renders the CardElement, but it's set to 1px width. If I manually set the IFrame's width property to auto it completely resolves my problem. How can I set the IFrame's width property for Stripe? (or is this even possible with cross-origin IFrame)
Or if not, how else can I resolve this issue to get the fields to display?
The style for individual elements for React-Stripe has to be passed manually as props. Below is an example from their official react-stripe-elements sample:
Elements
<CardNumberElement
onBlur={handleBlur}
onChange={this.handleChange}
onFocus={handleFocus}
onReady={handleReady}
{...createOptions(this.props.fontSize)}
/>
Function createOptions
const createOptions = (fontSize, padding) => {
return {
style: {
base: {
fontSize,
color: '#424770',
letterSpacing: '0.025em',
fontFamily: 'Source Code Pro, monospace',
'::placeholder': {
color: '#aab7c4',
},
...(padding ? { padding } : {}),
},
invalid: {
color: '#9e2146',
},
},
};
};
css
input,
.StripeElement {
display: block;
margin: 10px 0 20px 0;
max-width: 500px;
padding: 10px 14px;
font-size: 1em;
font-family: 'Source Code Pro', monospace;
box-shadow: rgba(50, 50, 93, 0.14902) 0px 1px 3px, rgba(0, 0, 0, 0.0196078) 0px 1px 0px;
border: 0;
outline: 0;
border-radius: 4px;
background: white;
}

How to style react autocomplete input box?

I am trying to use react-autocomplete in my component. Everything is working fine results are shown. But I am not able to style the default input box.
this is autocomplete
<Autocomplete
getItemValue={this.getItemValue}
items={this.state.autocompleteData}
renderItem={this.renderItem}
value={this.state.value}
onChange={this.onChange}
onSelect={this.onSelect}
menuStyle={menuStyle}
/>
style for dropdown menu is working fine.
const menuStyle = {
borderRadius: '3px',
boxShadow: '0 2px 12px rgba(0, 0, 0, 0.1)',
background: 'rgba(255, 255, 255, 0.9)',
padding: '2px 0',
fontSize: '90%',
position: 'fixed',
overflow: 'auto',
maxHeight: '50%', // TODO: don't cheat, let it flow to the bottom
"zIndex": 100,
};
i tried to add style as per answer in this question but it's not working.
how to increase input text box size in react-autocomplete?
How to add style to input box?
The object given to prop inputProps is used as props for the input, so you can give an object with a style property containing your menuStyles to that.
<Autocomplete
getItemValue={this.getItemValue}
items={this.state.autocompleteData}
renderItem={this.renderItem}
value={this.state.value}
onChange={this.onChange}
onSelect={this.onSelect}
inputProps={{ style: menuStyle }}
/>
inputProps={{ style: menuStyle }}
or you can do
styling={
borderRadius: '3px',
boxShadow: '0 2px 12px rgba(0, 0, 0, 0.1)',
background: 'rgba(255, 255, 255, 0.9)',
padding: '2px 0',
fontSize: '90%',
position: 'fixed',
overflow: 'auto',
maxHeight: '50%', // TODO: don't cheat, let it flow to the bottom
"zIndex": 100,
}

use conditional inside style inside render

I have this render and I have notification.isError in props, but I don't know how to use conditional to print a value inside background value, to get different colors accord to the property is Error.
I get "Unexpected token"
render() {
return (
<div style={{ padding: '4px 10px 1px 10px',
fontSize: '16px',
backgroundColor: {return (this.props.notification.isError?'red':'black')},
}}
>
I've tried this too:
const bgcolor = (this.props.notification.isError?'red':'black');
return (
<div style={{ padding: '4px 10px 1px 10px',
backgroundColor: {bgcolor},
}}
but backgroundColor is not showed on the browser; it's like react don't like the way to send the value
Can you try this:
render() {
return (
<div style={{ padding: '4px 10px 1px 10px',
fontSize: '16px',
backgroundColor: (this.props.notification.isError?'red':'black')
}}
>

Resources