How can I override the user-select: none in RadioButton and CheckBox control labels? - material-ui

Currently for pre 1.0.0 releases Material-UI does not allow text selection on RadioButton and Checkbox control labels.
How can I override this behavior? Apparently passing labelStyle={{ userSelect: 'all' }} to the component doesn't help.
What I'm trying to achieve is being able to highlight the text in the option label as per this screenshot:

You need to override the CSS class that prevents selection of the labels.
The labels are made with components of type FormControlLabel. At the bottom of the doc page for that component, you can see that the CSS label class is available to override.
So, you need to override the label class on each FormControlLabel like this:
// Define the overriding style
const styles = () => ({
selectableLabel: {
userSelect: 'all',
},
});
// Override the label CSS that prevents selection
<FormControlLabel classes={{ label: classes.selectableLabel }} value="male" control={<Radio />} label="Male" />
Here's full code for a group of selectable radio buttons (derived from the Radio buttons example in the docs:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
import Radio, { RadioGroup } from 'material-ui/Radio';
import { FormLabel, FormControl, FormControlLabel } from 'material-ui/Form';
const styles = theme => ({
root: {
display: 'flex',
},
formControl: {
margin: theme.spacing.unit * 3,
},
group: {
margin: `${theme.spacing.unit}px 0`,
},
selectableLabel: {
userSelect: 'all',
},
});
class RadioButtonsGroup extends React.Component {
state = {
value: '',
};
handleChange = (event, value) => {
this.setState({ value });
};
render() {
const { classes } = this.props;
return (
<div className={classes.root}>
<FormControl component="fieldset" required className={classes.formControl}>
<FormLabel component="legend">Gender</FormLabel>
<RadioGroup
aria-label="gender"
name="gender1"
className={classes.group}
value={this.state.value}
onChange={this.handleChange}
>
<FormControlLabel classes={{ label: classes.selectableLabel }} value="male" control={<Radio />} label="Male" />
<FormControlLabel classes={{ label: classes.selectableLabel }} value="female" control={<Radio />} label="Female" />
<FormControlLabel classes={{ label: classes.selectableLabel }} value="other" control={<Radio />} label="Other" />
<FormControlLabel classes={{ label: classes.selectableLabel }} value="disabled" disabled control={<Radio />} label="Disabled" />
</RadioGroup>
</FormControl>
</div>
);
}
}
RadioButtonsGroup.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(RadioButtonsGroup);
And here's the full code for the Checkbox buttons (derived from the Checkboxes example in the doc):
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
import { FormControl, FormGroup, FormControlLabel } from 'material-ui/Form';
import Checkbox from 'material-ui/Checkbox';
const styles = {
selectableLabel: {
userSelect: 'all',
},
};
class CheckboxesGroup extends React.Component {
state = {
gilad: true,
jason: false,
antoine: true,
};
handleChange = name => (event, checked) => {
this.setState({ [name]: checked });
};
render() {
const { classes } = this.props;
return (
<FormControl component="fieldset">
<FormGroup>
<FormControlLabel
classes={{ label: classes.selectableLabel }}
control={
<Checkbox
checked={this.state.gilad}
onChange={this.handleChange('gilad')}
value="gilad"
/>
}
label="Gilad Gray"
/>
<FormControlLabel
classes={{ label: classes.selectableLabel }}
control={
<Checkbox
checked={this.state.jason}
onChange={this.handleChange('jason')}
value="jason"
/>
}
label="Jason Killian"
/>
</FormGroup>
</FormControl>
);
}
}
CheckboxesGroup.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(CheckboxesGroup);

Related

How can I add linear-gradient to my Material-UI (v5.11.5) background

I have an Appbar that has a fixed colour background that has been applied using the createTheme module for material-ui. I have been asked to apply a linear gradient for a transitioning color effect to the Appbar. I have tried using palette: {
background: {
paper: '-webkit-linear-gradient(to left, #30e8bf, #ff8235)',
}, in my createTheme then using sx={{ bgcolor: 'background.paper' }} in my Appbar.
Any suggestion to changes I need to make ?
import * as React from 'react'
import AppBar from '#mui/material/AppBar'
import Box from '#mui/material/Box'
import Toolbar from '#mui/material/Toolbar'
import Stack from '#mui/material/Stack'
import Button from '#mui/material/Button'
import Tabs from '#mui/material/Tabs'
import Tab from '#mui/material/Tab'
import Typography from '#mui/material/Typography'
import IconButton from '#mui/material/IconButton'
import MenuIcon from '#mui/icons-material/Menu'
import AccountCircle from '#mui/icons-material/AccountCircle'
import Switch from '#mui/material/Switch'
import FormControlLabel from '#mui/material/FormControlLabel'
import FormGroup from '#mui/material/FormGroup'
import MenuItem from '#mui/material/MenuItem'
import Menu from '#mui/material/Menu'
import CssBaseline from '#mui/material/CssBaseline'
import { ThemeProvider, createTheme } from '#mui/material/styles'
import Chip from '#mui/material/Chip'
import Check from '#mui/icons-material/Check'
const finalTheme = createTheme({
components: {
// Name of the component
MuiButton: {
styleOverrides: {
// Name of the slot
root: {
// Some CSS
fontSize: '3rem',
backgroundColor: '#fff',
},
},
},
},
typography: {
// In Chinese and Japanese the characters are usually larger,
// so a smaller fontsize may be appropriate.
fontSize: 15,
},
palette: {
background: {
paper: '-webkit-linear-gradient(to left, #30e8bf, #ff8235)',
},
},
})
export default function NavBar() {
const [auth, setAuth] = React.useState(true)
const [anchorEl, setAnchorEl] = React.useState(null)
const [value, setValue] = React.useState('apple')
const handleChange = (event) => {
setAuth(event.target.checked)
}
const handleMenu = (event) => {
setAnchorEl(event.currentTarget)
}
const handleClose = () => {
setAnchorEl(null)
}
return (
<React.StrictMode>
<Box sx={{ flexGrow: 1 }}>
<ThemeProvider theme={finalTheme}>
<AppBar position="static" sx={{ bgcolor: 'background.paper' }}>
<Toolbar>
<IconButton
size="large"
edge="start"
color="inherit"
aria-label="menu"
sx={{ mr: 2 }}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }} />
<Tab value="0" label="Sessions" />
<Tab value="1" label="Gallery" />
<Tab value="2" label="About Us" />
{auth && (
<div>
<IconButton
size="large"
aria-label="account of current user"
aria-controls="menu-appbar"
aria-haspopup="true"
onClick={handleMenu}
color="inherit"
>
<AccountCircle />
</IconButton>
<Menu
id="menu-appbar"
anchorEl={anchorEl}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
keepMounted
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
</Menu>
</div>
)}
</Toolbar>
</AppBar>
</ThemeProvider>
</Box>
</React.StrictMode>
)
}

Tab Color disorder and single click ripple effect disappears after I add active tabs

Here's my header copmponent where I try to apply active tabs effect, the text completely disappers.
Header.js
import {
AppBar,
Toolbar,
useScrollTrigger,
Typography,
Tabs,
Tab,
Button,
} from "#mui/material";
import DeveloperModeIcon from "#mui/icons-material/DeveloperMode";
import { Box } from "#mui/system";
import { styled } from "#mui/material/styles";
import { Link } from "react-router-dom";
const Header = () => {
const [value, setValue] = useState(window.location.pathname);
function ElevationScroll(props) {
const { children } = props;
const trigger = useScrollTrigger({
disableHysteresis: true,
threshold: 0,
});
return React.cloneElement(children, {
elevation: trigger ? 4 : 0,
});
}
const TabComponent = styled(Tab)(({ theme }) => ({
fontWeight: 600,
fontSize: "1rem",
textTransform: "none",
// color: theme.palette.common.white,
}));
const onTabChangeHandler = (event, newValue) => {
setValue(newValue);
};
return (
<React.Fragment>
<ElevationScroll>
<AppBar position="fixed">
<Toolbar>
<DeveloperModeIcon sx={{ fontSize: "3rem" }} />
<Typography variant="h4">Lopxhan Development</Typography>
<Tabs
sx={{ marginLeft: "auto" }}
value={value}
onChange={onTabChangeHandler}
aria-label="secondary tabs example"
>
<TabComponent label="Home" component={Link} to="/" value="/" />
<TabComponent
label="Services"
component={Link}
to="/services"
value="/services"
disableRipple
/>
<TabComponent
label="Projects"
component={Link}
to="/projects"
value="/projects"
/>
<TabComponent
label="About Us"
component={Link}
to="/aboutus"
value="/aboutus"
/>
<TabComponent
label="Conatct Us"
component={Link}
to="/contactus"
value="/contactus"
/>
</Tabs>
<Button
variant="contained"
color="secondary"
sx={{
borderRadius: "50px",
fontWeight: 600,
}}
>
Get a Quote
</Button>
</Toolbar>
</AppBar>
</ElevationScroll>
<Box
sx={[
(theme) => ({
marginBottom: {
...theme.mixins.toolbar,
},
}),
]}
/>
</React.Fragment>
);
};
export default Header;
Theme.js
const arcBlue = "#0B72B9";
const arcOrange = "#e67700";
const arcGrey = "#868686";
export const appTheme = createTheme({
palette: {
common: {
blue: arcBlue,
orange: arcOrange,
white: "#fff",
},
primary: {
main: arcBlue,
},
secondary: {
main: arcOrange,
},
},
});
App.js
import { Routes, Route } from "react-router-dom";
import { ThemeProvider } from "#mui/material/styles";
import Header from "./components/UI/Header";
import { appTheme } from "./components/UI/Theme";
import HomePage from "./components/pages/HomePage";
import ServicesPage from "./components/pages/ServicesPage";
import ProjectsPage from "./components/pages/ProjectsPage";
import GetAQuotePage from "./components/pages/GetAQuotePage";
import AboutUsPage from "./components/pages/AboutUsPage";
import ContactUsPage from "./components/pages/ContactUsPage";
function App() {
return (
<ThemeProvider theme={appTheme}>
<Header />
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/services" element={<ServicesPage />} />
<Route path="/projects" element={<ProjectsPage />} />
<Route path="/aboutus" element={<AboutUsPage />} />
<Route path="/contactus" element={<ContactUsPage />} />
<Route path="/getaquote" element={<GetAQuotePage />} />
</Routes>
</ThemeProvider>
);
}
export default App;
I tried applying textColor and indicatorColor to Tabs, and its kinda somehow shows the tab text but ripple effect changes to double click. Also ripple effect on tab changes to double click as soon as I add active tab effect.

REACT 17 wrap mui tab in form how to control form submission with react hook form

I'm stuck can a charitable soul advise me : I have a form that wraps 3 tabs
which contain text fields
interface TabPanelProps {
// eslint-disable-next-line react/require-default-props
children?: ReactNode;
index: number;
value: number;
}
function TabPanel(props: TabPanelProps) {
const { children, value, index, ...other } = props;
return (
<div
aria-labelledby={`simple-tab-${index}`}
hidden={value !== index}
id={`simple-tabpanel-${index}`}
role="tabpanel"
{...other}
>
{value === index && (
<Box sx={{ p: 3 }}>
<div>{children}</div>
</Box>
)}
</div>
);
}
function getTab(index: number) {
return {
id: `simple-tab-${index}`,
'aria-controls': `simple-tabpanel-${index}`,
};
}
export default function tt({ closeModal, testData }: any) {
const [value, setvalue] = useState(0);
const methods = useForm<MyInterface>();
const {
register,
handleSubmit,
formState: { errors, isDirty },
} = methods;
const onSubmit = (formValue: MyInterface) => {
console.log("isSubmitted");
console.log(formValue);
};
const handleChangeTab = (event: SyntheticEvent, newValue: number) => {
setvalue(newValue);
};
return (
<FormProvider {...methods} >
< form className="myForm"
onSubmit={methods.handleSubmit(onSubmit)} >
<Box sx={{ width: '100%' }}>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<Tabs aria-label="basic tabs example" onChange={handleChangeTab} value={value}>
<Tab label="1" {...getTab(0)} />
<Tab label="2" {...getTab(1)} />
<Tab label="3" {...getTab(2)} />
</Tabs>
</Box>
<TabPanel index={0} value={value}>
<Component1 />
</TabPanel>
<TabPanel index={1} value={value}>
<Component2 testData={testData} />
</TabPanel>
<TabPanel index={2} value={value}>
<Component3 />
</TabPanel>
</Box>
<DialogActions>
<Button onClick={methods.handleSubmit(onSubmit)}>Enregistrer</Button>
<Button onClick={closeModal}>Annuler</Button>
</DialogActions>
</form>
</FormProvider>
);
}
2 and 3 have for example juste textField which are required in Component 1 but not in Component 2 and 3 :
import { useFormContext } from "react-hook-form";
import { TextField } from '#mui/material';
export default function Component1() {
const { register, formState } = useFormContext();
return (
<>
<TextField
error={Boolean(formState.errors?.name)}
fullWidth
helperText={Boolean(formState.errors?.name) === false ? "give the name" : formState.errors.name?.message}
{...register('name', { required: "name is required." })}
label="name"
variant="standard"
/>
</>
);
}
code in the Component2:
import { Controller, useFormContext } from 'react-hook-form';
import { Checkbox, Chip, FormControl, InputLabel, ListItemText, MenuItem, Select, SelectChangeEvent, TextField } from '#mui/material';
export default function Component3(props: any) {
const { register, control } = useFormContext();
return (
<>
<FormControl sx={{ m: 1, minWidth: '100%' }} variant="standard">
<InputLabel id="test">En prod</InputLabel>
<Controller
control={control}
defaultValue=""
name="test"
render={({ field }) => (
<Select labelId="test" {...field}>
<MenuItem value="yes">yes</MenuItem>
<MenuItem value="no">no</MenuItem>
</Select>
)}
/>
</FormControl>
my problem is:
when I change tab without clicking in a field of the form, that is sent even if the required fields are not filled.
On the contrary when I click in any field and the required fields are not filled in isDirty remains true.
Which is normal.
But if I fill in the required fields and I change tab isDirty always stays true and I can't send the form.
Thank you for your help!!

how to integrate tailwind into formik forms

I am trying to implement tailwindcss styles into Formik to style forms. But the styles declared through className are not being applied?
I think Formik is using classname to define input type and tailwind uses the same method to declare styles?
my form page:
import React from "react";
import * as yup from "yup"
import { Formik, Form } from 'formik'
import { MyTextInput } from "../components/FormParts";
let mainFormSchema = yup.object().shape({
name: yup.string().trim().required()
})
const tryMainForm = () => {
const initValues = {
name: ''
}
return (
<div>
<h1>Any place in your app!</h1>
<Formik
initialValues={initValues}
validationSchema={mainFormSchema}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 400);
}}
>
{({ isSubmitting }) => (
<Form>
<MyTextInput
label="name"
name="name"
type="text"
placeholder="name"
/>
<button type="submit" disabled={isSubmitting}>
Submit
</button>
</Form>
)}
</Formik>
</div>
)
}
export default tryMainForm
formpart component:
import { useField } from "formik";
export const MyTextInput = ({ label, ...props }) => {
const [field, meta] = useField(props)
return (
<>
<label htmlFor={props.id || props.name} className="block text-sm font-medium text-gray-700">{label}</label>
<input className="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md" {...field} {...props} />
{meta.touched && meta.error ? (
<div className="error">{meta.error}</div>
) : null}
</>
)
}
can you suggest a way to deal with this?
tailwind applies styles properly to label but doesn't with input?

how to use material-ui Dialog PaperProps

I'm using v1.1.0 of material-ui in React 16.3.2. I'm trying to create a landing page similar to Showcase - Local Insights
where the dialog has opacity (Find foreclosures). I'm trying to use PaperProps for Dialog component described here Dialog doc
Here's a component I've created to try to do this.
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
import Dialog from '#material-ui/core/Dialog';
import DialogActions from '#material-ui/core/DialogActions';
import DialogContent from '#material-ui/core/DialogContent';
import DialogTitle from '#material-ui/core/DialogTitle';
import ForwardIcon from '#material-ui/icons/Forward';
import Input from '#material-ui/core/Input';
import FormControl from '#material-ui/core/FormControl';
import Slide from '#material-ui/core/Slide';
const styles = theme => ({
dialogPaper: {
opacity: 0.5,
border: '#FF0000 1px solid',
},
button: {
margin: '30px'
}
});
function Transition(props) {
return <Slide direction="up" {...props} />;
}
class SignInDialog extends React.Component {
state = {
open: false,
username: ''
};
handleClickOpen = () => {
this.setState({ open: true });
};
handleClose = () => {
this.setState({ open: false });
};
handleChange = name => event => {
this.setState({
[name]: event.target.value,
});
};
render() {
const { classes } = this.props;
return (
<div>
<Button variant="fab" color="primary" aria-label="add" className={classes.button} onClick={this.handleClickOpen}>
<ForwardIcon />
</Button>
<Dialog
PaperProps={styles.dialogPaper}
open={this.state.open}
TransitionComponent={Transition}
onClose={this.handleClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">WELCOME</DialogTitle>
<DialogContent>
<p>SIGN IN</p>
<FormControl className={classes.formControl}>
<Input
value={this.state.searchString}
onChange={this.handleChange('search')}
id="siginin-input"
placeholder="Enter your username"
/>
</FormControl>
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose} color="primary">
Cancel
</Button>
<Button onClick={this.handleClose} color="primary">
Continue
</Button>
</DialogActions>
</Dialog>
</div>
);
}
}
SignInDialog.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(SignInDialog);
I haven't been able to figure out how to get the Dialog to take the styles. What is needed to get PaperProps to work?
If you want to use PaperProps you have to specify the props of the Paperfor which you are applying style.
<Dialog
PaperProps={{ classes: {root: classes.dialogPaper } }}
/>
You can also use classes property and override the style
<Dialog
classes={{paper:classes.dialogPaper}}
/>
The correct way to overide paper props is by using classNames
<Dialog
PaperProps={{ className: classNames(classes.dialogPaper) }}/>
<Dialog
PaperProps={{ classes: {root: classes.dialogPaper } }}
/>