How to properly target the Matrial UI nested prop attributes? - material-ui

Even after having read the Material UI Customization rules, I haven't quite understood how to properly target nested elements.
Here is an example, where I am targeting the label of the <TextField> component. The styling for the label works, but the styling for when the label is shrinked does not.
const useStyles = makeStyles({
label: {
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
right: '22px',
bottom: '0px',
'&.MuiInputLabel-shrink': {
right: 'unset',
color: 'green',
},
'&. MuiInputLabel-shrink': {
right: 'unset',
color: 'green',
},
'&.shrink': {
right: 'unset',
color: 'green',
},
'&.shrinked': {
right: 'unset',
color: 'green',
},
},
'&.MuiInputLabel-shrink': {
color: 'purple',
},
});

To target a the class 'shrink', this would be the correct usage:
const useStyles = makeStyles({
label: {
'& .shrink': {
right: 'unset',
color: 'green',
},
},
},
If this doesn't work for you - it may be an issue of specificity. Just as a test, I'd add the '!important' flag to the css to validate that you're styles are actually being applied.
You'll also have to apply object on the 'classes' prop of the material-ui component.
Hope this helps

Related

In Echarts, how to title/label series (pies) in nested pie chart

In Apache Echarts, when using multiple pie charts (e.g. nested pies, or even side-by-side pies), how do we add a title to each pie to signify what the pie represents? While the "title" option can accept an array of titles, there isn't a good way to position them so that they are above, within or in some other way related to the respective pies they are meant to label. It's as if there's a missing concept of a seriesLabel / seriesTitle that sits conceptually between the chart title and the individual item labels.
Series item labels are already in use for the items (pie slices) so cannot be used with position: center, and that wouldn't help with nested pies anyway since there's only room for one label at the center.
Here are my nested pies. I used an image editor to add labels where I might want them - hugging the pies they each label. That's what I'm trying to accomplish.
I do not understand what is your problem with the array of titles...
Here is a simple example showing how to give a title to each pie:
const data = [
{
name: 'Foo',
value: 10
},
{
name: 'Bar',
value: 20
},
{
name: 'Baz',
value: 15
}
];
let option = {
title: [
{
text: 'Pie 1',
subtext: 'Left',
left: '46px',
textAlign: 'center'
},
{
text: 'Pie 2',
subtext: 'Center',
left: '146px',
textAlign: 'center'
},
{
text: 'Pie 3',
subtext: 'Right',
left: '246px',
textAlign: 'center'
}
],
series: [
{
type: 'pie',
radius: '42px',
center: ['50%', '50%'],
data,
label: {
position: 'inner'
},
left: 0,
right: '66%',
top: 0,
bottom: 0
},
{
type: 'pie',
radius: '42px',
center: ['50%', '50%'],
data,
label: {
position: 'inner'
},
left: '33%',
right: '33%',
top: 0,
bottom: 0
},
{
type: 'pie',
radius: '42px',
center: ['50%', '50%'],
data,
label: {
position: 'inner'
},
left: '66%',
right: 0,
top: 0,
bottom: 0
}
]
};
let myChart = echarts.init(document.getElementById('main'));
myChart.setOption(option);
#main {
width: 300px;
height: 200px;
}
<script src="https://cdn.jsdelivr.net/npm/echarts#5.4.1/dist/echarts.min.js"></script>
<div id="main"></div>
EDIT 1
Same example with nested pies:
const data = [
{
name: 'Foo',
value: 10
},
{
name: 'Bar',
value: 20
},
{
name: 'Baz',
value: 15
}
];
let option = {
title: [
{
text: 'Pie 1',
left: '48%',
textAlign: 'center'
},
{
text: 'Pie 2',
left: '48%',
top: '26%',
textAlign: 'center'
}
],
series: [
{
type: 'pie',
radius: ['120px', '90px'],
center: ['50%', '50%'],
data,
label: {
position: 'inner'
},
top: '10px'
},
{
type: 'pie',
radius: '42px',
center: ['50%', '50%'],
data,
label: {
position: 'inner'
},
top: '10px'
}
]
};
let myChart = echarts.init(document.getElementById('main'));
myChart.setOption(option);
#main {
width: 300px;
height: 300px;
}
<script src="https://cdn.jsdelivr.net/npm/echarts#5.4.1/dist/echarts.min.js"></script>
<div id="main"></div>
EDIT 2
If you want something completely responsive with nested pies, indeed, I do not know the recipe using a simple array of titles...
But you can do this somehow creating two containers, which means each pie will be in its own <canvas> element. Then you can use CSS to give your inner pie an absolute position.
There is extra work to handle the behavior of both charts on resize. Your <canvas> elements should always be squares. In other words, their width and height should stay equal.
When you resize the window, you have to get its width and height to determine if you have a horizontal display or a vertical one. In both cases, take the smallest value and resize outer and inner containers (width and height) with it. You can even get a variable font size thanks to this value.
Of course, you should avoid px in your options. Prefer % instead.
Here is the code:
const data = [
{
name: 'Foo',
value: 10
},
{
name: 'Bar',
value: 20
},
{
name: 'Baz',
value: 15
}
];
let outerOption = {
title: {
text: 'Pie 1',
top: '2%',
left: '50%',
textAlign: 'center'
},
series: [
{
type: 'pie',
radius: ['100%', '80%'],
center: ['50%', '50%'],
data,
label: {
position: 'inner'
},
top: '10%'
}
]
};
let innerOption = {
title: {
text: 'Pie 2',
top: '25%',
left: '50%',
textAlign: 'center'
},
series: [
{
type: 'pie',
radius: '50%',
center: ['50%', '50%'],
data,
label: {
position: 'inner'
},
top: '10%'
}
]
};
let outerChart = echarts.init(document.getElementById('outer')),
innerChart = echarts.init(document.getElementById('inner'));
outerChart.setOption(outerOption);
innerChart.setOption(innerOption);
function resize(container, size) {
container.resize({
width: size,
height: size
});
container.setOption({
title: {
textStyle: {
fontSize: Math.round(size / 20)
}
}
});
}
['load', 'resize'].forEach(event => {
window.addEventListener(event, () => {
let width = window.innerWidth,
height = window.innerHeight,
size = width;
if (width > height) {
size = height;
}
resize(outerChart, size);
resize(innerChart, size);
});
});
body {
margin: 0;
}
#outer, #inner {
width: 100vh;
height: 100vh;
}
#inner {
position: absolute;
top: 0;
left: 0;
}
<script src="https://cdn.jsdelivr.net/npm/echarts#5.4.1/dist/echarts.min.js"></script>
<div id="outer"></div>
<div id="inner"></div>

How to make a colored circle pointer with white center in Apache eCharts?

I'm trying to re-create this example picture using Apache eCharts:
This is what my Apache eCharts version looks like so far:
As you can see, I have almost finished re-creating it.
The only part I can't figure out is how to make the small circle pointer to be a colored circle with white center. The color of the pointer should match the color of axis line it is on.
Currently mine is grey, which doesn't look good.
Here is my code:
const gaugeOption = {
series: [
{
data: gaugeData,
type: 'gauge',
startAngle: 180,
endAngle: 0,
min: 0,
max: 100,
splitNumber: 3,
pointer: {
icon: 'circle',
length: '12%',
width: 50,
offsetCenter: [0, '-90%'],
itemStyle: {
color: '#FFFFFF',
borderColor: 'auto', // This doesn't work :(
borderWidth: 5,
shadowColor: 'rgba(10, 31, 68, 0.5)',
shadowBlur: 2,
shadowOffsetY: 1,
},
},
axisLine: {
show: true,
roundCap: true,
lineStyle: {
width: 9,
color: [
[0.5, '#e76262'],
[0.54],
[0.66, '#f9cf4a'],
[0.7],
[0.83, '#eca336'],
[0.87],
[1, '#3ece80'],
],
},
},
axisTick: {
length: 2,
lineStyle: {
color: '#8a94a6',
width: 2,
},
},
splitLine: {
show: false,
},
axisLabel: {
show: false,
},
title: {
show: false,
},
detail: {
rich: {
header: {
fontSize: 36,
fontWeight: 700,
fontFamily: 'Open Sans',
color: '#0a1f44',
},
subHeader: {
fontSize: 16,
fontWeight: 400,
fontFamily: 'Open Sans',
color: '#8a94a6',
},
},
formatter: ['{header|{value}}', '{subHeader|15-30-2022}'].join('\n'),
offsetCenter: [0, '-20%'],
valueAnimation: true,
},
},
],
}
EDIT:
I have also tried specifying the colors directly as per below. It makes no difference. The border or the circle pointer remains a grey color:
pointer: {
icon: 'circle',
length: '12%',
width: 50,
offsetCenter: [0, '-90%'],
itemStyle: {
color: '#FFFFFF',
borderColor: [
[0.5, '#e76262'],
[0.66, '#f9cf4a'],
[0.83, '#eca336'],
[1, '#3ece80'],
],
borderWidth: 5,
shadowColor: 'rgba(10, 31, 68, 0.5)',
shadowBlur: 2,
shadowOffsetY: 1,
},
},
The only way I can change it's color is to set it to a single static color, but that is not what I want, it should adapt to the color of the axis beneath it.
Set borderColor to a variable. Then change this variable when the gauge value is changed, depending on its new position.
You'll also have to use setOption() to make the change effective on the chart.
//update your variable however you want
myBorderColor = '#f00';
//then make the change to the chart
myChart.setOption({
series: [
{
pointer: {
itemStyle : {
borderColor: myBorderColor
},
},
},
],
});

pseudo selector after not working when nested in wild card class selector

I'm trying to make a custom TextField using MUI v4. After discovering that we cannot use [class selectors when using nested themes][1], we are trying to switch to class wildcard selectors they recommend in the answer. It seems like the pseudo selector after is no longer working when nested under a class wildcard selector.
.root {
'& [class*="MuiInputBase-root"]': {
height: '56px',
'&::after': {
content: '""',
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
borderStyle: 'solid',
borderColor: '#000000',
borderWidth: '1px',
borderRadius: '8px',
},
},
},
Even though it is working when not nested
.root {
'& [class*="MuiInputBase-root"]::after': {
content: '""',
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
borderStyle: 'solid',
borderColor: '#000000',
borderWidth: '1px',
borderRadius: '8px',
},
},
I'm passing in the classes by spreading
const styles = useStyles();
<MuiTextField classes={...classes} />
Am I doing anything wrong?
[1]: How reliable are MUI Global Class names in JSS?

creating a custom scrollbar in echarts using dataZoom

I am trying to create a scrollbar like the one below using echarts
So far I have managed to get the scroll using dataZoom feature but I haven't been able to style it like a normal scroll bar.
const dataY = [
'a',
'b',
'v',
'd',
'e',
'f',
'x',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n'
]; // 名称
const dataX = [
20, 50, 15, 35, 50, 30, 40, 50, 60, 20, 50, 15, 35, 50, 30, 40, 50, 60
]; // 数据
option = {
backgroundColor: '#1C1C1C',
grid: {
top: '10%',
right: '10%',
left: '10%',
bottom: '10%'
},
yAxis: [
{
type: 'category',
data: dataY,
axisLine: {
lineStyle: {
color: '#333333'
}
},
axisLabel: {
interval: 0,
margin: 10,
color: '#999999',
textStyle: {
fontSize: 11
},
rotate: '0'
},
axisTick: {
show: false
}
}
],
xAxis: [
{
axisLabel: {
padding: [3, 0, 0, 0],
formatter: '{value}',
color: '#999999',
textStyle: {
fontSize: 11
}
},
axisTick: {
show: true
},
axisLine: {
lineStyle: {
color: '#333333'
}
},
splitLine: {
lineStyle: {
color: '#333333'
}
}
}
],
dataZoom: [
{
type: 'slider',
yAxisIndex: 0,
zoomLock: true,
width: 5,
right: 10,
top: '10%',
bottom: '10%',
start: 70,
end: 20,
brushSelect: false,
handleSize: '60%',
showDetail: false,
backgroundColor: '#000',
borderColor: '#000',
opacity: 1,
brushStyle: false,
handleStyle: {
color: '#FF6700',
borderColor: '#FF6700'
}
},
{
type: 'inside',
id: 'insideY',
yAxisIndex: 0,
start: 15,
end: 20,
zoomOnMouseWheel: false,
moveOnMouseMove: true,
moveOnMouseWheel: true,
backgroundColor: 'transparent'
}
],
series: [
{
type: 'bar',
data: dataX,
barWidth: '5',
itemStyle: {
normal: {
color: '#FF6700',
shadowBlur: 4,
borderRadius: 100
}
},
label: {
normal: {
show: false,
lineHeight: 4,
formatter: '{c}',
position: 'top',
textStyle: {
color: '#fff',
fontSize: 10
}
}
}
}
]
};
I am left with a weird scrollbar that works as it should be unfortunately looks really weird.
I had the exact same issue as you, and i found a turnaround.
Instead of using the datazoom from ECharts as a scrollbar, you can just use the overflow of the div of the chart, and you can costumize it as you want with css. First you need to comment or delete the part of the datazoom in you code and change the html and css as this:
<div class="grid" [style.width.%]="100" [style.height.%]="100" #wrapper>
<div class="ChartDiv" echarts [options]="options" [style.width.px]="ganttWidth" [style.height.px]="ganttHeight"></div>
</div>
Then you just have to define the css like this:
.grid {
overflow-y: scroll !important;
//hidden if you dont want the x-Axis to have a scroll
overflow-x: hidden !important;
}
//Change the css as you want
::-webkit-scrollbar {
width: 16px;
}
::-webkit-scrollbar-track {
background-color: #e4e4e4;
border-radius: 100px;
}
With this code, your graph will have this aspect:
Now you just need to change your css as you want the style of this xD.

Why doesn't Material UI use my custom theme palette colors?

I want to use a custom palette so that my site uses brand colors across all components. I want to be able to access these custom colors globally, including in makeStyles.
This is my theme file:
import { createMuiTheme } from '#material-ui/core/styles';
const theme = createMuiTheme({
palette: {
primary: {
main: '#467f0f'
},
},
});
export default theme;
This is my component:
import theme from './theme';
const useStyles = makeStyles(theme => ({
title: {
backgroundColor: theme.palette.common.white,
borderColor: theme.palette.primary.main,
borderRadius: theme.spacing(2),
borderStyle: 'solid',
borderWidth: theme.spacing(1),
color: theme.palette.primary.main,
fontSize: theme.spacing(4),
margin: theme.spacing(2, 'auto'),
padding: theme.spacing(1),
textAlign: 'center',
[theme.breakpoints.up('sm')]: {
fontSize: theme.spacing(8),
},
},
}));
function App(): JSX.Element {
const classes = useStyles();
return (
<ThemeProvider theme={theme}>
<Typography
className={classes.title}
variant='h1'
>
My App
</Typography>
</ThemeProvider>
);
}
export default App;
There are no errors being thrown or linter warnings or anything. But the color from my custom palette is not being used. What might I have missed along the way?
The reason it isn't working is because when your ThemeProvider is in the same component as your useStyles. So what is happening is you are trying to use your theme before it has actually been added to the rest of your app.
So what you might need to do is either import your ThemeProvider one level higher (I assume your index.js file), or have a child component inside ThemeProvider which renders your children, which is the example I have given below
import theme from './theme';
function App(): JSX.Element {
return (
<ThemeProvider theme={theme}>
<AppContent/>
</ThemeProvider>
);
}
export default App;
const useStyles = makeStyles(theme => ({
title: {
backgroundColor: theme.palette.common.white,
borderColor: theme.palette.primary.main,
borderRadius: theme.spacing(2),
borderStyle: 'solid',
borderWidth: theme.spacing(1),
color: theme.palette.primary.main,
fontSize: theme.spacing(4),
margin: theme.spacing(2, 'auto'),
padding: theme.spacing(1),
textAlign: 'center',
[theme.breakpoints.up('sm')]: {
fontSize: theme.spacing(8),
},
},
}));
function AppContent(): JSX.Element {
const classes = useStyles();
return (
<Typography
className={classes.title}
variant='h1'
>
My App
</Typography>
);
}
Also Rather then createMuiTheme try just createTheme It seems that it was renamed in one of the newer releases to make clearer
import { createTheme } from '#material-ui/core/styles';
const theme = createTheme({
palette: {
primary: {
main: '#467f0f'
},
},
});
export default theme;
And on another note. I would recommend not styling the typography that much other than things like color, fontSize, etc. Rather think about wrapping it in a Box and having that have the styles for the backgroundColor, borderRadius, etc