Using additional palettes beyond primary, secondary and error - material-ui

I can create a theme and replace the default palette like this:
const theme = createMuiTheme({
primary: {
main: '#aa2222',
},
extra: {
main: '#22aa22',
},
});
This automatically sets theme.primary.light and theme.primary.dark. However it does not set the equivalent light and dark values for the extra object.
Is there a way to do this for custom elements like extra without having to manually calculate the RGB values? Or am I limited to only primary, secondary, and error getting calculated automatically?

Worked this one out. This is added on to the end of the code in the question above:
theme.palette.augmentColor(theme.palette.extra, 500, 300, 700);
The three numeric parameters are the mainShade, lightShade and darkShade values. These are the ones used for the default palettes:
augmentColor(primary, 500, 300, 700);
augmentColor(secondary, 'A400', 'A200', 'A700');
augmentColor(error, 500, 300, 700);
I think they are there so you can tweak how much the colours are lightened or darkened in case the default isn't readable enough.

Related

How to color individual boxes of an echarts boxplot based on function

How do I color each boxes individually in an echarts box-plot based on a function?
The following function works on a simple bar chart and colors the bars appropriately:
series: [{
data: [120, 200, 150, 80, 70, 110, 130],
type: 'bar',
showBackground: true,
itemStyle: {
color: function(seriesIndex) {
return ProfessionColor[seriesIndex.name.split("_", 1).toString()]
},
},
}]
However, it does not work on a box-plot:
series: [{
name: 'boxplot',
type: 'boxplot',
datasetIndex: 1,
itemStyle: {
color: function(seriesIndex) {
return ProfessionColor[seriesIndex.name.split('_', 1)];
}
},
encode: {
tooltip: [1, 2, 3, 4, 5]
}
},
{
name: 'outlier',
type: 'scatter',
encode: {
x: 1,
y: 0
},
datasetIndex: 2
}
]
If I provide color: "red" rather than a function all boxes are colored red. This leads me to believe that it needs to happen in the transform.config which I can't find in the documents or tutorial.
Echarts Box-Plot currently
The link is the complete charts in its current form.
Apparently, echarts only allows scripting (i.e., using a function for) either the line color -- option itemStyle.borderColor or the fill color -- option itemStyle.color.
The difference between the two appears to be made by the value of the internal property BoxplotSeriesModel#visualDrawType. It is now set to "stroke", which means that borderColor can be set via a function.
Since you wanted to set the fill color, its value should be set to "fill". I searched a way to change that property - it was rather difficult for echarts don't document an API for extensions. Still, navigating the source code I came up with this hacky solution:
const BoxplotSeriesModel = echarts.ComponentModel.getClassesByMainType('series').find(cls=>cls.type==='series.boxplot');
const BoxplotSeriesModelFill = function(...args){
const _this = new BoxplotSeriesModel(...args);
_this.visualDrawType = 'fill';
return _this;
}
BoxplotSeriesModelFill.type = BoxplotSeriesModel.type;
echarts.ComponentModel.registerClass(BoxplotSeriesModelFill);
That's a "patch" to be applied at the beginning of your script, immediately after you have the echarts global defined.
Here's a forked version of your code that uses that patch. The only other change I made was to set a borderColor (can now only be a fixed value) to black.
This will not get you all the way, but if you add colorBy: "data" to your options and remove the itemStyle, it will look like this:

Transitive transforms appear to be happening out of order

I'm working on a refactor of our style-dictionary implementation. I'm working on applying alpha values through a transform rather than predefining values with alpha values.
It looks something like this:
In color.json
{
color: {
text: {
primary: {
value: '{options.color.warm-grey-1150.value}',
alpha: .75,
category: 'color',
docs: {
category: 'colors',
type: 'text',
example: 'color',
description: 'The default, primary text color',
},
}
}
}
The value for warm-grey-1150 is #0C0B08 and is in another file.
I have already successfully created a simple alpha transform for scss, less, and js and it works just fine:
const tinycolor = require('tinycolor2');
module.exports = (StyleDictionary) => {
StyleDictionary.registerTransform({
name: 'color/alpha',
type: 'value',
transitive: true,
matcher(prop) {
return (prop.attributes.category === 'color') && prop.alpha;
},
transformer(prop) {
const { value, alpha } = prop;
let color = tinycolor(value);
color.setAlpha(alpha)
return color.toRgbString();
},
});
};
However, I'm stuck on the IOS UIColor transform. My initial approach was to convert the colors to a hex8 value, as those were the original values that we were converting. (We had a value already created which mapped to #0C0B08BF and just plugged that into UIColor).
So I created a separate transform for IOS to set the alpha value and then extended the UI-color transform to make it transitive.
const tinycolor = require('tinycolor2');
module.exports = (StyleDictionary) => {
StyleDictionary.registerTransform({
name: 'color/alpha-hex',
type: 'value',
transitive: true,
matcher(prop) {
return (prop.attributes.category === 'color') && prop.alpha;
},
transformer(prop) {
let { value, alpha } = prop;
let color = tinycolor(value);
color.setAlpha(alpha);
return color.toHex8String();
},
});
};
In the transform group I made sure that the alpha-hex transform happened before UIColor:
module.exports = (StyleDictionary) => {
StyleDictionary.registerTransformGroup({
name: 'custom/ios',
transforms: [
//Other non-color related transforms
'color/alpha-hex',
'color/UIColor-transitive',
//Other non-color related transforms
],
});
};
The results were strange, as all the UIColor values that happened to undergo the alpha transform had a red, green and blue value of zero, but the alpha value was set:
[UIColor colorWithRed:0.000f green:0.000f blue:0.000f alpha:0.749f]
I decided to experiment and tried using chroma-js instead of tinycolor2 and chroma threw up an error:
Error: unknown format: [UIColor colorWithRed:0.047f green:0.043f blue:0.031f alpha:1.000f]
(Apparently, tinycolor doesn't throw up an error when passed an invalid format and instead creates an instance of tinycolor with #000000 as its value.)
For some reason, the UIColor formatted values are already being piped to the alpha-hex transform, even though I specified that I wanted the alpha-hex transform to run before. I've tried several things like not running the transform if value.indexOf('UIColor') !== -1) and that didn't seem to work. I also copied/pasted the UIColor transform and tried to run my hex transform in the same transform function but that didn't seem to work either.
Any ideas on what I'm missing here?
We had this exact same issue. This was happening because non-transitive transforms were occurring in our mix function, even if the matcher excluded that particular token.
What ended up working for us was to first console.log what was being used in the mix method and using Regex to parse it into a color format that would work.
We ended up splitting color transforms up into two separate transforms:
One that is non-transitive, and would output in the final format we needed but had a matcher that excluded all color-blended tokens (ex. UIColor(red: 1.000, green: 1.000, blue: 1.000, alpha: 1)
The other that is transitive transform targeting color-blended tokens, that would then take in each prop and transform those already transformed values into a color format supported by tinyColor.
By using tinyColor's isValid() method, we could validate what was being passed in or throw an error. This helped us debug but would also help future contributions that required color blending.
I figured out the issue for me. We had a whole bunch of options structure like this:
These are one of our color options tokens that get filtered out of the final result. These options get used for tokens like color-text-primary
'warm-grey-200': {
value: '#f4f2ed',
category: 'color',
},
When we use a transitive transform we are going through every single transform in a transform group for each of the options. With ios UIColor the problem is the final result of the transform can't get transformed again because it's a different format.
So this is what solved it for us. We changed the options to bare values like so:
'warm-grey-200': '#f4f2ed',
'warm-grey-300': '#edeae3',
we removed the "value" keyword as well as the category. However, this meant that now we had to make all of our transforms transitive (at least those dealing with color) and this meant extending some of the existing predefined transforms so they were transitive like so:
module.exports = (StyleDictionary) => {
StyleDictionary.registerTransform(
Object.assign({}, StyleDictionary.transform[`predefined/transform`], {
name: 'predefined/transform-transitive',
transitive: true
}),
)
}
This worked great for us. To sum up the two steps we needed to make were:
Restructure our color options to bare values so that transforms
don't happen to them until AFTER they are referenced
Make sure that all transforms that deal with these color options are transitive--otherwise you'll just end up with the original,non-transformed values.

Can't style slider (or maybe anything) in Material UI

There was an issue requesting documentation for theming which the author subsequently closed. The author found their answer. A non-programmer will probably not. At least, the non-programmer designer I'm helping doesn't even know where to start (and I still don't have a working different colored slider). This kind of documentation would be great. Even if it's just a link to the code #jdelafon found with some explanation that would suffice to answer the following specific example.
Ultimately, we want a set of sliders with each one a different color. It seems like the appropriate way to do this is with per-element inline styles.
I made a simple example here. Can you change the color of the slider? (We started down the path of breaking out to CSS, but the widget is so dynamic that this approach ends up being quite ugly.)
Slider has two different slots for theming, neither of which seems to respond to an embedded object with a selectionColor key.
Should be simple. Probably it is, but it appears to be undocumented. Otherwise it's a rad UI toolkit, thanks devs!
Take a look at this line of getMuiTheme.js. You can find there that slider can have those styles overridden:
{
trackSize: 2,
trackColor: palette.primary3Color,
trackColorSelected: palette.accent3Color,
handleSize: 12,
handleSizeDisabled: 8,
handleSizeActive: 18,
handleColorZero: palette.primary3Color,
handleFillColor: palette.alternateTextColor,
selectionColor: palette.primary1Color,
rippleColor: palette.primary1Color,
}
In material-ui you need to use MuiThemeProvider in order to use your custom theme. Taking your example:
...
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import { Slider } from 'material-ui';
const theme1 = getMuiTheme({
slider: {
selectionColor: "red",
trackSize: 20
}
})
const theme2 = getMuiTheme({
slider: {
selectionColor: "green",
trackSize: 30
}
})
const HelloWorld = () => (
<div>
...
<MuiThemeProvider muiTheme={theme1}>
<Slider defaultValue={0.5}/>
</MuiThemeProvider>
<MuiThemeProvider muiTheme={theme2}>
<Slider defaultValue={0.5}/>
</MuiThemeProvider>
</div>
);
export default HelloWorld;
Your modified webpackbin: http://www.webpackbin.com/EyEPnZ_8M
The sliderStyle you tried to use is for different styles :-) Like marginTop / marginBottom, a full list can be found here.

nvd3 space between bars

I've made a MultiBarChart with NVD3.
It works, however, a colleague said I needed more space between each Australian state.
So, Tasmania further from Victoria etc.
Here is the data visualisation
I can not find a forum that explains this in non-developer language. I'm not a developer, but having a go.
Here is my code...
var chart;
nv.addGraph(function() {
chart = nv.models.multiBarHorizontalChart()
.x(function(d) { return d.label })
.y(function(d) { return d.value })
.margin({top: 30, right: 105, bottom: 30, left: 103})
.tooltips(true)
.showControls(false);
chart.yAxis
.tickFormat(d3.format(',.1f'));
d3.select('#chart1 svg')
.datum(long_short_data)
.transition().duration(1400)
.call(chart);
nv.utils.windowResize(chart.update);
chart.dispatch.on('stateChange', function(e) { nv.log('New State:', JSON.stringify(e)); });
return chart;
});
Thanks you super kind and smart people!
No Need to use too much code for spacing just use below code :
var chart = nv.models.multiBarChart();
//added by santoshk for fix the width issue of the chart
chart.groupSpacing(0.8);//you can any value instead of 0.8
This is unfortunately something you can't configure in NVD3. However, you can change the height of the bars after the chart has been created to make it appear as if there's more space between them. The code to do this is simple:
d3.selectAll(".nv-bar > rect").attr("height", chart.xAxis.rangeBand()/3);
The default height is chart.xAxis.rangeBand()/2 -- you can adjust this as you see fit. The only thing to keep in mind when running this code is that NVD3 animates its elements, so not everything will be there in the beginning or values may be overwritten. You can solve this by waiting a small amount of time before calling that code using setTimeout:
setTimeout(function() {
d3.selectAll(".nv-bar > rect").attr("height", chart.xAxis.rangeBand()/3);
}, 100);
Just found this question while searching for a way to add more space between bars. Like Lars said, you can change the bar size after the chart has been drawn. However, when you increase the bar height without changing the space between each bar, it overflows. To add space between the bars you should use xRange:
var chart = nv.models.multiBarHorizontalChart().xRange([0, 125])

Embed bubble charts on a web site

I'm looking for a way to create what come to know to be called a "bubble chart" for a website I'm building. It needs to be compatible with IE7 and above, and of course all the good browsers like Firefox, Chrome and Safari. And no flash since this thing will need to run on iOS.
The chart needs to look like this, http://www.flickr.com/photos/jgrahamthomas/5591441300/
I've browse online and tried a few things, including:
Google Scatter Charts. This doesn't work as it seems Google Charts limits the size of a point to something smaller than I need. And Venn Diagrams are limited to three circles.
Protovis Dots. Great library, but isn't compatible with IE8.
Raphael Javascript. This one might be my best bet, but there's no explicit support for bubble charts.
Thanks for your help.
It looks like Raphael javascript is the way to go. It's compatible with IE6. I found a great tutorial at http://net.tutsplus.com/tutorials/javascript-ajax/an-introduction-to-the-raphael-js-library/ and am able to get the example working on my rails site with this code:
# window.onload = function() {
# var paper = new Raphael(document.getElementById('canvas_container'), 500, 500);
# var circle = paper.circle(100, 100, 80);
# for(var i = 0; i < 5; i+=1) {
# var multiplier = i*5;
# paper.circle(250 + (2*multiplier), 100 + multiplier, 50 - multiplier)
# }
# var rectangle = paper.rect(200, 200, 250, 100);
# var ellipse = paper.ellipse(200, 400, 100, 50);
# }
You can give Protovis a chance, the library looks good for your needs: http://vis.stanford.edu/protovis/ex/
Another charting library is Highcharts, but I haven't tried it yet: http://www.highcharts.com/
Have you had a look at flot?
It's a plotting library for jQuery. While it technically doesn't have any "native" support for bubble charts it is possible to create bubble charts with it by using a few tricks, the simplest one probably being to simply put each point in its own data series (thus allowing you to control the radius of each individual point.
By defining your points similar to this you'll be able to create a bubble chart:
var dataSet = [{
color:"rgba(0,0,0,0)", // Set the color so it's transparent
shadowSize:0, // No drop shadow effect
data: [[0,1],], // Coordinates of the point, normally you'd have several
// points listed here...
points: {
show:true,
fill:true,
radius: 2, // Here we set the radius of the point (or rather, all points
// in the data series which in this case is just one)
fillColor: "rgba(255,140,0,1)", // Bright orange :D
}
},
/* Insert more points here */
];
There is a bubble chart available for flot here
Note that you need to scale your bubbles size yourself if you don't want them to coverup the graph. Documentation is here.
To use it, add the following at the beggining of your html page:
and call it from a json result or any data object like in this sample:
$.getJSON('myQuery.py?'+params, function(oJson) {
// ... Some validation here to see if the query worked well ...
$.plot('#myContainer',
// ---------- Series ----------
[{
label: 'Line Sample',
data: oJson.lineData,
color: 'rgba(192, 16, 16, .2)',
lines: { show: true },
points: { show: false }
},{
label: 'Bubble Sample',
data: oJson.bubbleData, // arrays of [x,y,size]
color: 'rgba(80, 224, 80, .5)',
lines: { show: false },
points: { show: false },
},{
label: 'Points sample',
data: oJson.pointsData,
color: 'rgba(255, 255, 0, 1)',
lines: { show: false },
points: { show: true, fillColor: 'rgba(255, 255, 0, .8)' }
},{
...other series
}],
// ---------- Options ----------
{ legend: {
show: true,
labelBoxBorderColor: 'rgba(32, 32, 32, .2)',
noColumns: 6,
position: "se",
backgroundColor: 'rgba(224, 224, 224, .2)',
backgroundOpacity: .2,
sorted: false
},
series: {
bubbles: { active: true, show: true, fill: true, linewidth: 2 }
},
grid: { hoverable: true, clickable: true } },
xaxis: { tickLength: 0 }
}); // End of plot call
// ...
}); // End of getJSON call
I tried to do the same thing with jqPlot which has some advantages but doesn't work with bubbles and other kind of series on the same graph. Also Flot does a better job to synchronise common axis scale with many series. Highchart does a really good job here (mixing bubble chart with other kind of series) but isn't free for us (government context).