Adding a background image to nav Link in React using useState - css

I was able to get the background image to show up when the link was clicked, however it is showing up on all the links once clicked. All the links have a different background image, but depending on which one is clicked all the links get the background image of the link clicked. I only want the appropriate background image to show while on page of link clicked
const navLinks = [
{ title: `HOME`, path: `/`, bgI: `${homePaintBackground}` },
{ title: `EVENTS`, path: `/events`, bgI: `${eventsPaintBackground}` },
{ title: `ARTISTS`, path: `/artists`, bgI: `${artistPaintBackground}` },
{
title: `CONTACT US`,
path: `/contactUs`,
bgI: `${contactUsPaintBackground}`,
},
]
const Nav = () => {
const classes = useStyles()
const [bgI] = navLinks
const [backgroundImage, setBackgroundImage] = useState(bgI)
const css = {
backgroundImage: `url(${backgroundImage})`,
marginBottom: '-20px',
width: '20%',
height: '80%',
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat',
}
return ( ...
{navLinks.map(({ title, path, bgI }) => (
<Link
// active={bgI}
to={path}
key={title}
// value={bgI}
className={classes.linkText}
style={css}
onClick={() => setBackgroundImage(`${bgI}`)}
>
Thank you for any help you may be able to provide.

Related

adding border bottom color on react styled element

I'm working on a basic calculator app with dynamic themes to be applied. How do I add a dynamic style react border-bottom with a set color on the keyStyle constant to be applied on my buttons?
I can't pass the value of currentTheme.numKeyShadow in the borderBottom css style as it's already a string.
How do i go about this?
This is a snippet my code:
import { useStateContext } from '../context/contextProvider'
const NumKeys = () => {
const { currentTheme, SetCurrentTheme } = useStateContext()
const keysStyle = {
borderRadius: "8px",
borderBottom:"4px solid",
borderBottomColor: currentTheme.numkeyShadow,
backgroundColor: currentTheme.keysBackground
}
return (
<section>
<div className='numKeys'>
<button style={keysStyle}>1</button>
</div>
</section>
)
}
export default NumKeys
This is my part of my data source:
export default [
{
"id": 0,
"background": "#3a4764",
"keysBackground": "#232c43",
"screenBackground": "#182034",
"KeysBackground": "#637097",
"KeysShadow": "#404e72",
"equaKeyBackground": "#d03f2f",
"equalKeyShadow": "#93261a",
"numKeyBackground": "#eae3dc",
"numKeyShadow": "#b4a597",
"num": "444b5a",
"equal": "#ffff"
}
]
You don't need a context or custom hook here. The CSS for the theme is a constant, and hence, you can declare, import and export like a simple JavaScript file.
NumKeys.js (React component)
import theme from "./Theme";
const NumKeys = () => {
const keysStyle = {
borderRadius: "8px",
borderBottom: "4px solid",
borderBottomColor: theme.numKeyShadow,
backgroundColor: theme.keysBackground,
};
return (
<section>
<div className="numKeys">
<button style={keysStyle}>1</button>
</div>
</section>
);
};
export default NumKeys;
Theme.js
const theme = {
id: 0,
background: "#3a4764",
keysBackground: "#232c43",
screenBackground: "#182034",
KeysBackground: "#637097",
KeysShadow: "#404e72",
equaKeyBackground: "#d03f2f",
equalKeyShadow: "#93261a",
numKeyBackground: "#eae3dc",
numKeyShadow: "#b4a597",
num: "444b5a",
equal: "#ffff",
};
export default theme;
This would add the style in your React component.
Live version - https://codesandbox.io/s/theme-0t9773

React align right/hide items on ANTD 4.21 Menu

Is there a way I can add different classes or an attribute to align right 2 items of this ant design top navigation menu? Also how can I hide an item conditionally? IE if there's an user logged in, I want to hide an item.
import { HomeOutlined, SettingOutlined, LoginOutlined, UserAddOutlined} from '#ant-design/icons';
import { Menu } from 'antd';
import { useState } from 'react';
const items = [
{
label: 'Home',
key: 'home',
icon: <HomeOutlined />,
},
{
label: 'Username',
key: 'SubMenu',
icon: <SettingOutlined />,
children: [
{
type: 'group',
children: [
{
label: 'Option 1',
key: 'setting:1',
},
{
label: 'Option 2',
key: 'setting:2',
},
],
},
],
},
{
label: 'Login',
key: 'login',
icon: <LoginOutlined />
},
{
label: 'Register',
key: 'register',
icon: <UserAddOutlined />,
},
];
const Header = () => {
const [current, setCurrent] = useState('home');
const onClick = (e) => {
setCurrent(e.key);
};
return (
<Menu onClick={onClick} selectedKeys={[current]} mode="horizontal" items={items} />
);
};
export default Header;
I'm using ant design's top navigation menu: https://ant.design/components/menu/#API
I checked their documentation and other places but I can't seem to figure it out. I would appreciate any help.
Thanks
I don't know if it is too late to respond :)
As far as I know, there is no "one-line" solution for this. You should make the conditions with JS using conditional JSX.
For example (in JSX, in the return expression in your React Component):
{checkedCondition &&
<Menu type one .../>
}
{uncheckedCondition &&
<Menu type two .../>
}

MUI KeyboardDatePicker change styles of date input box

Currently, I am trying to modify KeyboardDatePicker board color, size, font, padding, but unfortunately, all approaches don’t work. I tried so far:
1 . useStyles :
const useStyles = (params: any) =>
makeStyles(() =>
createStyles({
componentStyle: {
width: params.width ? params.width : 'auto',
color: params.color ? params.color : 'inherit',
verticalAlign: 'middle',
fontSize: '12px',
border: 'solid 2px #0070D8',
},
})
);
Doesn’t override and a border appears on current KeyboardDatePicker border, size doesn’t change as well.
2 . Theme provide, it overrides calendar theme, but not KeyboardDatePicker date box.
<ThemeProvider theme={theme}>
3 . Add styles into KeyboardDatePicker, it is the only working approach
style={{width:"246px",height:"44px"}}
How would you suggest modifying styles of KeyboardDatePicker, and yes style={} approach it's not the correct way to changes styles. p.s I am using Material-UI 4
My KeyboardDatesPicker:
<KeyboardDatePicker
format="MM/dd/yyyy"
margin="normal"
id="date-picker-inline"
defaultValue={props.value}
value={selectedDate}
required={props.required}
showTodayButton={true}
disableToolbar
inputVariant="outlined"
variant="inline"
onChange={(selectedDate) => setSelectedDate(selectedDate)}
KeyboardButtonProps={{
"aria-label": "change date",
}}
keyboardIcon={<Icon icon={ICONS.Cool_icon} />}
className={classes.componentStyle} // do not overide , but puts on top
/>
makeStyles is a hook factory that returns a style hook (usually called useStyles), this is how it's used:
const useStyles = makeStyles(...);
In your code, you define useStyles as a function that return makeStyles instead of telling makeStyles to create a new hook which doesn't make sense here, so change your code to the above. I also fixed the styles for you. The text color styles should be placed in InputBase component:
const useStyles = makeStyles(() =>
createStyles({
componentStyle: {
verticalAlign: "middle",
fontSize: "12px",
width: (params) => (params.width ? params.width : "auto"),
"& fieldset": {
border: "solid 2px #0070D8"
},
"& .MuiInputBase-root": {
height: (params) => (params.height ? params.height : "auto"),
color: (params) => (params.color ? params.color : "inherit")
}
}
})
);
const classes = useStyles({
color: "red",
width: 400,
height: 80,
});
<KeyboardDatePicker
onChange={() => {}}
inputVariant="outlined"
InputProps={{
className: classes.componentStyle
}}
/>
If you want to style via createMuiTheme, here is the equivalent code. Note that you can't pass the component props to create dynamic styles unlike the useStyles approach above:
const theme = createMuiTheme({
overrides: {
MuiTextField: {
root: {
verticalAlign: "middle",
fontSize: "12px",
width: 150,
"& fieldset": {
border: "solid 2px #0070D8"
}
}
}
}
});
And it should work again. For reference, see this section to know how you can use makeStyles with component props.
It seems you don't need to write a custom hook like this useStyles = (params: any) => ..., the hook returned by makeStyles already accepts a props param.
When styling MUI components you need to check the API for each component to define the object you pass to makeStyles, in this case, the date picker component is a group of other MUI components, if you go to the API you'll see different props to pass to each individual component. To style the input you pass the classes returned by the useStyle hook in InputProps, with root rule as it is in the Input API, apply other rules if you need more specific styles.
const useInputStyles = makeStyles({
root: {
width: (props) => (props.width ? props.width : "auto"),
color: (props) => (props.color ? props.color : "inherit"),
verticalAlign: "middle",
fontSize: "12px",
border: "solid 2px #0070D8"
}
});
...
const inputClasses = useInputStyles()
...
<KeyboardDatePicker
...
InputProps={{ classes: inputClasses }}
/>
and to style the "board", not sure if you mean the popover, since you use the inline variant, you pass the styles in the PopoverProps, defining the styles in the paper rule as described in the Popover API
const usePopoverStyles = makeStyles({
paper: {
backgroundColor: "green"
}
});
...
const popoverClasses = usePopoverStyles();
...
<KeyboardDatePicker
...
PopoverProps={{ classes: popoverClasses }}
/>
you can see it working here https://codesandbox.io/s/mui-keyboarddatepicker-styles-sueqd?file=/src/App.tsx
I have implemented it like this in TS, not a finished component, but I hope that this assists people. I am about to add MuiFormLabel-root etc to add more specific styling to the label.
const useDatePickerStyles = makeStyles<ITheme, ITextFieldStyleProps>((theme) =>
createStyles({
datePickerContainer: ({ isValid, isError }) => ({
border: 'solid',
borderRadius: 4,
borderWidth: theme.mvf.border.width.thin,
borderColor: theme.mvf.palette.border,
...(!isError && {
'&:hover': {
boxShadow: theme.mvf.boxShadow.primary,
borderColor: theme.mvf.palette.primary.main,
},
...(isValid && {
color: theme.mvf.palette.primary.main,
boxShadow: theme.mvf.boxShadow.primary,
borderColor: theme.mvf.palette.primary.main,
}),
}),
...(isError && {
color: theme.mvf.palette.error,
boxShadow: theme.mvf.boxShadow.error,
borderColor: theme.mvf.palette.error,
}),
}),
datePicker: () => ({
margin: theme.mvf.spacing.small,
}),
}),
);
export default useDatePickerStyles;
And get access to classes like so
const DatePicker: DatePickerType = ({
id,
onChange,
format,
value,
label,
errorMessage,
placeholder,
isVerticallyCentered,
...props
}: IDatePickerProps) => {
const isValid = !errorMessage && !!value;
const classes = useDatePickerStyles({
isError: !!errorMessage,
isVerticallyCentered,
isValid,
});
return (
<div className={classes.datePickerContainer}>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<KeyboardDatePicker
id={id}
fullWidth
maxDateMessage={''}
minDateMessage={''}
invalidDateMessage={''}
className={classes.datePicker}
label={isVerticallyCentered ? undefined : label} // don't show as label will be outside
placeholder={placeholder}
format={format} // of the displayed date
emptyLabel={placeholder} // displayed value if empty
name="datePicker"
InputLabelProps={{
className: classes.inputLabel,
}}
margin="normal"
value={value}
onChange={onChange}
InputProps={{
className: classes.inputPropsClasses,
inputProps: { className: classes.textInput },
disableUnderline: true,
}}
inputVariant="standard"
KeyboardButtonProps={{
className: classes.calendarButton,
}}
{...props}
/>
</MuiPickersUtilsProvider>
</div>
);
};

How to change the text color of the selected row in material ui table

I am trying to change the color of the row text and the background color of row on selection.
I am able to change the background color successfully but I am not able to change the text color.
<TableRow
className={classes.tableBody}
>
tableBody: {
"&:focus": {
color: "yellow !important",
backgroundColor: "#3D85D2 !important",
},
},
The background color is controlled in TableRow. In order to get the correct specificity (you shouldn't ever need to leverage "!important" when overriding Material-UI styles), you need to leverage the "hover" class similar to what is done within TableRow.
The color is controlled in TableCell, so that is the level where you need to control it.
For a working solution, in the styles you would have something like:
const styles = theme => ({
tableRow: {
"&$hover:hover": {
backgroundColor: "blue"
}
},
tableCell: {
"$hover:hover &": {
color: "pink"
}
},
hover: {}
});
then in the rendering:
<TableRow
hover
key={row.id}
classes={{ hover: classes.hover }}
className={classes.tableRow}
>
<TableCell
className={classes.tableCell}
component="th"
scope="row"
>
{row.name}
</TableCell>
Here's a working version based on your sandbox:
Here's a similar example, but using "selected" instead of "hover":
https://codesandbox.io/s/llyqqwmr79
This uses the following styles:
const styles = theme => ({
tableRow: {
"&$selected, &$selected:hover": {
backgroundColor: "purple"
}
},
tableCell: {
"$selected &": {
color: "yellow"
}
},
selected: {}
});
and some state:
const [selectedID, setSelectedID] = useState(null);
and changing the TableRow rendering to be:
<TableRow
hover
key={row.id}
onClick={() => {
setSelectedID(row.id);
}}
selected={selectedID === row.id}
classes={{ selected: classes.selected }}
className={classes.tableRow}
>
v4 of Material-UI will include some changes that should make overriding styles considerably easier (and easier to figure out how to do successfully without looking at the source code).
In v4 of Material-UI, we can use the global class names for the selected state ("Mui-selected") and for TableCell ("MuiTableCell-root") and then we only need to apply a single class to TableRow:
const styles = (theme) => ({
tableRow: {
"&.Mui-selected, &.Mui-selected:hover": {
backgroundColor: "purple",
"& > .MuiTableCell-root": {
color: "yellow"
}
}
}
});
This is the only solution that worked for me
const styles = theme => ({
tableRow: {
'&&:hover': {
backgroundColor: '#0CB5F3',
},
},
});
<TableRow
hover
className={classes.tableRow}
>
const useStyles = makeStyles((theme) => ({
selected: {
backgroundColor: "green !important",
"&:hover": {
backgroundColor: "green !important",
},
},
}));
const classes = useStyles();
<TableRow selected classes={{selected: classes.selected,}}/>

How to style a functional stateless component in Reactjs using classes object

I want to write and style a functional stateless component in ReactJs as described here.
const MyBlueButton = props => {
const styles = { background: 'blue', color: 'white' };
return <button {...props} style={styles} />;
};
The problem is that I want to add in some styles from stateful components as described here.
const styles = theme => ({
root: {
width: '100%',
maxWidth: 360,
backgroundColor: theme.palette.background.paper,
},
});
The problem is that when I try to do something like this:
<div className={classes.root}>
I get the error:
'classes' is not defined no-undef
How do I access the withStyles classes object to style root the way I want?
If I understood right here is how you can do this with a functional component.
const styles = theme => ( {
root: {
width: "100%",
maxWidth: 360,
backgroundColor: theme.palette.background.paper,
},
} );
const App = ( props ) => {
const { classes } = props;
return <div className={classes.root}>Foo</div>;
};
export default withStyles( styles )( App );

Resources