EDIT: after further testing it seems that each time the component is re-rendered material-ui's makeStyles is executed again, while JSS's createUseStyles is NOT!
I have a component that has to dynamically change the styling based on the state. When I use makeStyles provided with material-ui the code works perfectly:
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles(theme => ({
root: {
position: "relative",
borderRadius: filteredItems.length > 0 ? "4px 4px 0 0" : "4px 4px 4px 4px", // this is the relevant line
backgroundColor: "white",
color: "black",
},
}));
But I don't want to use material-ui, I just want to use JSS. Unfortunately it doesn't work. It looks like filteredItems.length > 0 always returns false, so I guess that createUseStyles for some reason is executed differently than makeStyles:
import { createUseStyles } from "react-jss";
const useStyles = createUseStyles(theme => ({
root: {
position: "relative",
borderRadius: filteredItems.length > 0 ? "4px 4px 0 0" : "4px 4px 4px 4px", // this is the relevant line
backgroundColor: "white",
color: "black",
},
}));
I know that material-ui runs under the hood JSS so I'm puzzled by this behaviour. I thought about adding two CSS classes and toggle them within my JSX, but I think sorting out the issue in the styling is the cleanest solution here. Anyone knows why this is happening or how to fix the issue?
EDIT2: To fix the issue I simply created two classes and toggled them within JSX:
const useStyles = createUseStyles(() => {
return ({
root: {
position: "relative",
borderRadius: "4px 4px 4px 4px",
backgroundColor: "white",
color: "black",
},
withItems: {
borderRadius: "4px 4px 0 0",
},
})
});
And then:
<div className={filteredItems.length > 0 ? `${classes.root} ${classes.withItems}` : classes.root}>
Have you tried this approach?
const useStyles = makeStyles({
root: {
position: "relative",
backgroundColor: "white",
color: "black",
borderRadius: props.withItems ? "4px 4px 0 0" : "4px 4px 4px 4px",
// or
// borderRadius: "4px 4px 4px 4px",
// borderRadius: props.withItems && "4px 4px 0 0",
color: props => props.color,
},
});
render() {
const classes = useStyles({ withItems: filteredItems.length > 0 });
return <div className={classes.root} />;
}
Related
A component has been created that I can not edit:
import * as React from 'react'
import styled from '#emotion/styled'
import FlexRow from '../../layouts/FlexRow'
const RowContainer = styled('div')<TableRowProps>(
({theme, padding, active, hoverActive=true}): any => ({
position: 'relative',
borderBottom: `1px solid ${theme.concrete}`,
borderLeft: active ? `4px solid ${theme.primaryDark}` : 'none',
boxShadow: active ? `inset 16px 0px 0px 0px ${theme.alabaster}, inset 0px 2px 4px -2px rgba(44, 51, 55, 0.16)` : 'none',
backgroundColor: active ? `${theme.alabaster}` : 'none',
padding: padding ?? `20px 16px 20px ${active ? '12px' : '16px'}`,
'&:hover': hoverActive ? {
borderLeft: `4px solid ${theme.schist}`,
paddingLeft: '12px',
backgroundColor: `${theme.alabaster}`,
boxShadow: `inset 16px 0px 0px 0px ${theme.alabaster}, inset 0px 2px 4px -2px rgba(44, 51, 55, 0.16)`
} : {}
})
)
type TableRowProps = {
theme?: any
padding?: string
active?: boolean,
hoverActive?: boolean
}
export const Row = (props) => <RowContainer padding={props.padding} active={props.active} hoverActive={props.hoverActive} ><FlexRow {...props} /></RowContainer>
I'm using this component with a custom Table component like this:
<Table.Row {...flexProps} className="TableRow">
I'm wanting to remove the padding from Row and have tried:
<Table.Row style={{ padding: 0 }}>...</Table.Row>
How can I access it's props and make changes to the component?
Given that the Row component forwards any padding prop to the RowContainer where it uses it for the padding style (falling back to 20px 16px 20px ${active ? '12px' : '16px'}), you can simply set padding="0" when you use it
<Table.Row padding="0">...</Table.Row>
I'm trying to build custom scrollable chips array with material ui version 4 no version 5.
In older tickets i could see similar demos:
Demo code
I want to change this component scrolling bar to left and right arrow buttons (same line with the Chip array).
please suggest how it can be done by modifying the same code or advice on another approach.
You can use Material UI Tabs
And style scroll Buttons using .MuiTabs-scrollButtons class name.
Or change scroll buttons using Tabs's prop: ScrollButtonComponent.
Material UI Tabs Documentation
#Amr Thanks for the advice, I have now exactly what I need.
I can't share the full code because it's mixed a lot with other code that is not related to this question, but here is something similar that I can share:
import React, { useState } from "react";
import { makeStyles } from "#material-ui/core/styles";
import Chip from "#material-ui/core/Chip";
import Box from "#material-ui/core/Box";
import Tabs from "#material-ui/core/Tabs";
import IconButton from "#material-ui/core/IconButton";
import styled from "#emotion/styled";
import ChevronLeftIcon from "#material-ui/icons/ChevronLeftRounded";
import ChevronRightIcon from "#material-ui/icons/ChevronRightRounded";
const StyledChip = styled(Chip)`
border-radius: 16px;
text-transform: capitalize;
color: ${(props) => (props.selected ? "#FFFFFF" : "#6877AE")};
background-color: ${(props) => (props.selected ? "#03194F" : "#FFFFFF")};
border: 4px solid ${"#03194F"};
border-color: ${(props) =>
props.selected ? "#03194F" : "rgba(0, 83, 229, 0.12)"};
.MuiChip-root&:hover {
background-color: ${(props) => (props.selected ? "#03194F" : "")};
}
`;
const StyledIconButton = styled(IconButton)`
left: ${(props) => (props.isLeft ? "0" : "none")};
right: ${(props) => (props.isLeft ? "none" : "0")};
height: 32px;
width: 32px;
position: absolute;
border-radius: 16px;
border: 1px solid gray;
//top: 33%;
background-color: white;
color: rgba(0, 83, 229, 1);
border-color: rgba(0, 83, 229, 0.12);
z-index: 1;
opacity: 1;
margin: 20px;
:hover {
box-shadow: 0px 2px 4px -1px rgba(0, 0, 0, 0.2),
0px 4px 5px rgba(0, 0, 0, 0.14), 0px 1px 10px rgba(0, 0, 0, 0.12);
border-color: white;
background-color: inherit;
}
`;
const useStyles = makeStyles((theme) => ({
root: {
display: "flex",
justifyContent: "center",
flexWrap: "nowrap",
listStyle: "none",
padding: theme.spacing(0.5),
margin: 0,
overflow: "auto",
maxWidth: "100%"
},
chip: {
margin: theme.spacing(2)
}
}));
export default function ChipsArray() {
const classes = useStyles();
const [chipData, setChipData] = React.useState([
{ key: 0, label: "Angular" },
{ key: 1, label: "jQuery" },
{ key: 2, label: "Polymer" },
{ key: 3, label: "React" },
{ key: 4, label: "Vue" },
{ key: 5, label: "Knockout" },
{ key: 6, label: "Ember" },
{ key: 7, label: "D3" },
{ key: 8, label: "Google Charts" },
{ key: 9, label: "C+" },
{ key: 10, label: "C++" },
{ key: 11, label: "NodeJS" }
]);
const [selectedIndustryFilter, setSelectedIndustryFilter] = React.useState(
"Angular"
);
return (
<Box className={classes.root}>
<Tabs
variant="scrollable"
scrollButtons="on"
aria-label="scrollable auto tabs example"
ScrollButtonComponent={(props) => {
if (props.direction === "left") {
return (
<StyledIconButton isLeft {...props}>
<ChevronLeftIcon />
</StyledIconButton>
);
} else if (props.direction === "right") {
return (
<StyledIconButton {...props}>
<ChevronRightIcon />
</StyledIconButton>
);
} else {
return null;
}
}}
>
{chipData.map((data) => {
return (
<StyledChip
label={data.label}
onClick={() => {
setSelectedIndustryFilter(data.label);
console.log(data.label);
}}
selected={data.label === selectedIndustryFilter}
key={data.key}
className={classes.chip}
/>
);
})}
</Tabs>
</Box>
);
}
also you can check it here:
https://codesandbox.io/s/demo-material-ui-chips-single-line-with-scroll-forked-2f0z30?file=/src/index.js
i'm currently i'm working in a project that is required to have a "Inset Fab" button between containers. I saw in the Material Design documentation that the name of the component is called "Inset FAB", i'd got some tutorials on google (but didn't find many) on how to implement, but normally they are "workaround" (setting a background border with radius behind the button). I'm still puzzled in how to do it.
Currently i'm using the MUI/Material UI 5.
Example of inset Fab
from what I understand inset is done through box shadows.
specifically
boxShadow: "0px 0px 0px 5px white inset"
here is a code sandbox I threw together
import React from "react";
import ReactDOM from "react-dom";
import { Box, Fab } from "#material-ui/core";
const appBarStyle = {
height: "100px",
backgroundColor: "blue",
position: "relative"
};
const fabWithInset = {
position: "absolute",
backgroundColor: "red",
boxShadow: "0px 0px 0px 0px white inset",
left: "50%",
bottom: "0px",
transform: "translate(0%,50%)",
"&:onclick": {
boxShadow: "0px 0px 0px 5px white inset"
}
};
function App() {
return (
<Box style={appBarStyle}>
<Fab style={fabWithInset} />
</Box>
);
}
ReactDOM.render(<App />, document.querySelector("#app"));
I'm trying to create an object to use it in inline style but I don't know how to how to write clamp and after the right way.
const PhoneInputStyle = {
fontSize: clamp("13px", "1.111vw", "16px"), /*this is giving me trouble
lineHeight: clamp("15px", "1.319vw", "19px"), */
position: "relative",
width: "100%",
height: "51px",
cursor: "pointer",
display: "flex",
flexDirection: "row",
alignItems: "center",
padding: "8px 16px",
border: "1px solid ${COLOR_NOT_BLACK}",
boxSizing: "border-box",
borderRadius: "10px",
outline: "none",
&:focus { /*this is giving me trouble
border: "1px solid ${COLOR_SALMON} !important",
} */
gridRowStart: "1",
gridColumnStart: "1"
}
The error I get on clamp is : Cannot find name 'clamp'
What I get on focus is : Expression expected (on the &)
You need to make the whole thing a string e.g. {fontSize: "clamp(13px, 1.111vw, 16px)"}
For the focus, I think you'll need something like: https://styled-components.com/
-edit-
Perhaps you could create a wrapper component that you can set an onHover event handler on.
Something along the lines of...
<div
style={isShown ? {border: "1px solid ${COLOR_SALMON}"}: ""}
onMouseEnter={() => setIsShown(true)}
onMouseLeave={() => setIsShown(false)}
>
{children}
</div>
This would probably even work without needing to set a wrapper component.
The idea is to resize a css definition that has been done in css. The css js object looks as :
style: {
textAlign: "left",
fontWeight: "bold",
fontSize: "1.0em",
lineHeight: "12px",
fontFamily: "#{fontFamily}",
color: "#{textColor}",
margin: "0 10px 0 10px",
padding: "7px 0 7px 0",
borderBottom: "1px solid rgba(0, 0, 0, 0.06)",
width: "auto",
height: "30px",
},
Now I would like to zoom all this by a 20% (30px -> 36px, 10px -> 12px, 1.0em -> 1.2em...) . What is the smartest and robust way of doing this ?
Following solution works for values like 1.0em, 30px (number followed by non-numerical value)
Object.keys(styles).forEach( s => {
if( !isNaN(parseInt(styles[s])) )
{
var nonNumericVal = [...(styles[s].match(/[^\d\.]/g, "")|| []) ].join("");
var numValue = styles[s].replace( nonNumericVal, "");
if ( !isNaN( numValue ) )
{
styles[s] = numValue * 120/100 + nonNumericVal;
}
}
})
Demo
var styles = {
textAlign: "left",
fontWeight: "bold",
fontSize: "1.0em",
lineHeight: "12px",
fontFamily: "#{fontFamily}",
color: "#{textColor}",
margin: "0 10px 0 10px",
padding: "7px 0 7px 0",
borderBottom: "1px solid rgba(0, 0, 0, 0.06)",
width: "auto",
height: "30px",
};
Object.keys(styles).forEach(s => {
if (!isNaN(parseInt(styles[s]))) {
var nonNumericVal = [...(styles[s].match(/[^\d\.]/g, "") || [])].join("");
var numValue = styles[s].replace(nonNumericVal, "");
if (!isNaN(numValue)) {
styles[s] = numValue * 120 / 100 + nonNumericVal;
}
}
});
console.log(styles);
Attributes like (padding, margin, background-color, etc) will require more specific logic.
Use CSS zoom.
.zoom {
zoom: 120%;
}