plouc / nivo

nivo provides a rich set of dataviz components, built on top of the awesome d3 and React libraries
https://nivo.rocks
MIT License
13.08k stars 1.02k forks source link

Theming for components #308

Closed alcmacys closed 4 years ago

alcmacys commented 5 years ago

I was wondering if there are any further documentation on theming? The only reference I found was the closed issue https://github.com/plouc/nivo/issues/132

I tried applying the same CSS provided in the example to the theme for my line chart but it is not working..

I would really appreciate a basic theme documentation, if I have a basic understanding I may be able to contribute and expand the documentation.

Please let me know! Thanks!

ByronBecker commented 5 years ago

One way I found out the structure of theme was by going into the specific installed nivo node_module and looking in the cjs folder at the nivo-.js file. I then added a console statement to print the theme object to the console. In my case, this was in node_modules/@nivo/bullet/cjs/nivo-bullet.js

The printed out theme object looks something like this. Hope this helps in modifying some of the default theme styles...

Theme for bullet object

axis:
  domain:
    line: {stroke: "transparent", strokeWidth: 1}
    __proto__: Object
  legend:
    text: {fill: "#333333", fontSize: 11}
    __proto__: Object
  ticks:
    line: {stroke: "#777", strokeWidth: 1}
    text: {fill: "#333333", fontSize: 11}
    __proto__: Object
    __proto__: Object
  background: "transparent"
dots:
  text: {fill: "#333333", fontSize: 11}
  __proto__: Object
grid:
  line: {stroke: "#ddd", strokeWidth: 1}
  __proto__: Object
labels:
  text: {fill: "#333333", fontSize: 11, fontFamily: "Roboto, sans-serif", color: "#999999"}
  __proto__: Object
legends:
  text: {fill: "#333333", fontSize: 11}
  __proto__: Object
markers:
  fontSize: 11
  lineColor: "#000"
  lineStrokeWidth: 1
  textColor: "#333333"
  __proto__: Object
tooltip:
  basic: {whiteSpace: "pre", display: "flex", alignItems: "center"}
  container: {background: "white", color: "inherit", fontSize: "inherit", borderRadius: "2px", boxShadow: 
  "0 1px 2px rgba(0, 0, 0, 0.25)", …}
  table: {}
  tableCell: {padding: "3px 5px"}
  __proto__: Object
cbfrance commented 5 years ago

As of at least 0.58.0 it looks like there is a default theme in node_modules/@nivo/core/dist/nivo-core.cjs.js — I pulled it out and am starting to use it as the basis for my theming. Here's a snapshot of how it looks today (it's probably under active development and likely to change.)

Not sure yet how this interacts with each of the components, but figured I'd share it since some of the googleable docs are out of date.

export default {
  background: 'transparent',
  fontFamily: 'sans-serif',
  fontSize: 11,
  textColor: '#333333',
  axis: {
    domain: {
      line: {
        stroke: 'transparent',
        strokeWidth: 1
      }
    },
    ticks: {
      line: {
        stroke: '#777777',
        strokeWidth: 1
      },
      text: {}
    },
    legend: {
      text: {
        fontSize: 12
      }
    }
  },
  grid: {
    line: {
      stroke: '#dddddd',
      strokeWidth: 1
    }
  },
  legends: {
    text: {
      fill: '#333333'
    }
  },
  labels: {
    text: {}
  },
  markers: {
    lineColor: '#000000',
    lineStrokeWidth: 1,
    text: {}
  },
  dots: {
    text: {}
  },
  tooltip: {
    container: {
      background: 'white',
      color: 'inherit',
      fontSize: 'inherit',
      borderRadius: '2px',
      boxShadow: '0 1px 2px rgba(0, 0, 0, 0.25)',
      padding: '5px 9px'
    },
    basic: {
      whiteSpace: 'pre',
      display: 'flex',
      alignItems: 'center'
    },
    table: {},
    tableCell: {
      padding: '3px 5px'
    }
  },
  crosshair: {
    line: {
      stroke: '#000000',
      strokeWidth: 1,
      strokeOpacity: 0.75,
      strokeDasharray: '6 6'
    }
  },
  annotations: {
    text: {
      fontSize: 13,
      outlineWidth: 2,
      outlineColor: '#ffffff'
    },
    link: {
      stroke: '#000000',
      strokeWidth: 1,
      outlineWidth: 2,
      outlineColor: '#ffffff'
    },
    outline: {
      fill: 'none',
      stroke: '#000000',
      strokeWidth: 2,
      outlineWidth: 2,
      outlineColor: '#ffffff'
    },
    symbol: {
      fill: '#000000',
      outlineWidth: 2,
      outlineColor: '#ffffff'
    }
  }
}
brandondurham commented 5 years ago

How is a theme added? Why isn’t it documented anywhere?

JayCarney commented 4 years ago

@brandondurham Not sure if this is the "right" way of doing it, but this is a simplified example of how I got theme changes working:

import { Line } from '@nivo/line'
import { ThemeProvider } from '@nivo/core'

const theme = {
  tooltip: {
    tableCell: {
      background: 'red',
    }
  }
}

function Chart(props) {
  return (
    <ThemeProvider theme={theme}>
      <Line {...props}/>
    </ThemeProvider>
  )
}

defaultTheme is also in @nivo/core so I was just inspecting that to see what I could target

JakeDluhy commented 4 years ago

Not sure how that worked for @JayCarney. When I did that Line was not properly picking up the theme. After some long investigation I figured out that's because Line is exported with useContainer which renders it's own theme provider (which was overriding the theme from the higher level provider I defined). I had to pass theme into my Line component in order for it to be passed into the theme for the container. Here's a small sample:

// App.js - renders everything in my tree
<ThemeProvider theme={theme}>
  <Root />
</ThemeProvider>
// LineGraph.js
const LineGraph = (props) => {
  const theme = useTheme();

  return <ResponsiveLine theme={theme} {...props} />;
};
senelithperera commented 4 years ago

Hi @JakeDluhy, I tried to give a fixed position to the tooltip container like below

theme={{ tooltip: { container: { position: "fixed" } } }}

but It seems like this is getting overridden by the default theme props. I couldn't get a solid idea about how to get these themes working by referring to your above explanation. Can you be a little more specific ?

MightyMoud commented 4 years ago

One way I found out the structure of theme was by going into the specific installed nivo node_module and looking in the cjs folder at the nivo-.js file. I then added a console statement to print the theme object to the console. In my case, this was in node_modules/@nivo/bullet/cjs/nivo-bullet.js

The printed out theme object looks something like this. Hope this helps in modifying some of the default theme styles...

Theme for bullet object

axis:
  domain:
    line: {stroke: "transparent", strokeWidth: 1}
    __proto__: Object
  legend:
    text: {fill: "#333333", fontSize: 11}
    __proto__: Object
  ticks:
    line: {stroke: "#777", strokeWidth: 1}
    text: {fill: "#333333", fontSize: 11}
    __proto__: Object
    __proto__: Object
  background: "transparent"
dots:
  text: {fill: "#333333", fontSize: 11}
  __proto__: Object
grid:
  line: {stroke: "#ddd", strokeWidth: 1}
  __proto__: Object
labels:
  text: {fill: "#333333", fontSize: 11, fontFamily: "Roboto, sans-serif", color: "#999999"}
  __proto__: Object
legends:
  text: {fill: "#333333", fontSize: 11}
  __proto__: Object
markers:
  fontSize: 11
  lineColor: "#000"
  lineStrokeWidth: 1
  textColor: "#333333"
  __proto__: Object
tooltip:
  basic: {whiteSpace: "pre", display: "flex", alignItems: "center"}
  container: {background: "white", color: "inherit", fontSize: "inherit", borderRadius: "2px", boxShadow: 
  "0 1px 2px rgba(0, 0, 0, 0.25)", …}
  table: {}
  tableCell: {padding: "3px 5px"}
  __proto__: Object

So Apparently this is the only place to refer how to make a them. Maybe this should be added to the documentation? 🤘🏻

dancitron commented 4 years ago

I'm trying to figure out how to change the font in a PieChart, this is a little frustrating the lack of documentation. Especially with how well documented everything else is.

tomaswitek commented 4 years ago

@dancitron it is very straightforward:

import {ResponsivePie} from "@nivo/pie";

function PieChart({data}) {
  return (
    <ResponsivePie
      theme={{
        fontFamily: "Helvetica"
      }}

The default theme settings are located here: https://github.com/plouc/nivo/blob/master/packages/core/src/theming/defaultTheme.js

You're right, it could be better documented. Btw. anybody can always open a PR for documentation 😏 https://github.com/plouc/nivo/tree/master/website

mickdee commented 4 years ago

Axis > domain styles both axes. Is there a way to style axes independently? Edit: found a related ask from 2018: https://github.com/plouc/nivo/issues/286

cbfrance commented 4 years ago

Observation (agreeing with @JakeDluhy above) — 

Theming globally with the ThemeProvider does not seem to work as I expected — at least for some components, like ResponsiveLine.

In this case it seems you must pass it directly with the theme prop.

(Although I do see in the docs that props might have access to the theme like: pointColor={{ theme: 'background' }} ... I haven't tried that approach.)

camilobern commented 4 years ago

To avoid opening a new issue I'll post a question here. I'm trying to make the background of a ResponsiveLine graph transparent, or at least try to make it match the rest of my application: image Also, I'm using a natural curve but the graph does not look curved. I presume that I may have too many data points.

This is basically my current usage:

  const commonProperties = {
    animate: true,
    labelTextColor: 'Red',
    background: 'transparent'
  };
  return (
    <ResponsiveLine {...commonProperties} data={chartData} curve="natural" enablePoints={false} enableGridY={true} enableGridX={true} />
  );
plouc commented 4 years ago

@camilobern you can pass the styles to the theme property, and the shape of the theme is available here https://github.com/plouc/nivo/blob/master/packages/core/index.d.ts#L38.

For the curve issue, if you have many points, this won't be smoothed, the only way around this is to remove points from your dataset.

camilobern commented 4 years ago

Thanks @plouc. I tried the following earlier without any effect (i.e. background is still white):

    <ResponsiveLine
      theme={{ background: '#FF0000' }}
      data={chartData}
      curve="natural"
      enablePoints={false}
      enableGridY={true}
      enableGridX={true}
      animate={true}
    />

I must be misunderstanding the shape of the theme for ResponsiveLine charts; the same example above works when using a Line graph.

In this example they resort to custom layers, which I would prefer to avoid: https://codesandbox.io/s/yogxd?file=/src/index.js:1107-1114

plouc commented 4 years ago

@camilobern, that's weird :/ I just tried to add it using your example and it works:

Capture d’écran 2020-06-09 à 08 09 09

However you won't be able to get different bands as for this example if that's what you're trying to achieve, you'll have to use a custom layer.

camilobern commented 4 years ago

@plouc I ended up switching the data set for a simpler one and the red background colour configuration took effect. Switching back to the original data set and the red background colour configuration took effect as well ... not sure what happened there. Caching perhaps?

emalo6 commented 1 year ago

Hi, Is it possible to change the color of the following element? image