[charts-premium] Allow color customization in Candlestick chart#21838
[charts-premium] Allow color customization in Candlestick chart#21838JCQuintas merged 20 commits intomui:masterfrom
Conversation
…color customization
…tomization - Add candlestickPalette with MUI success/error colors as defaults - Set default colorGetter in getSeriesWithDefaultValues using palette colors - Simplify getColor processor and useCandlestickPlotData to use colorGetter - Add ColorCandlestick and ColorGetterCandlestick demos
|
Deploy preview: https://deploy-preview-21838--material-ui-x.netlify.app/ Updated pages: Bundle size report
|
|
|
||
| ### Color | ||
|
|
||
| The `colors` prop accepts an array where the first value is used for bullish candles (close ≥ open) and the second for bearish candles (close < open). |
There was a problem hiding this comment.
Any specific reason to use an array instead of named properties for the colors?
The API from tradingview looks more friendly. Maybe with only upColor and downColor to start
https://tradingview.github.io/lightweight-charts/docs/api/interfaces/CandlestickStyleOptions
There was a problem hiding this comment.
It used bullishColor/bearishColor previously, but it felt like parting away from the colors property.
Both work though, it was just preference.
/**
* The color of the candle body when the close price is greater than or equal to the open price (bullish).
* Falls back to the first color from the `colors` palette.
*/
bullishColor?: string;
/**
* The color of the candle body when the close price is less than the open price (bearish).
* Falls back to the second color from the `colors` palette.
*/
bearishColor?: string;There was a problem hiding this comment.
It used bullishColor/bearishColor
Yes but in an internal only
Both work though, it was just preference.
Not exactly. The named colors can be refined. The array will be harder.
For now it works because we only have up and down. But with more customization, it will lead to poor DX.
Probably something like: The 2 first colors are for up and down, and the 2 seconds are up and down but only for the wick.
A new joiner on the project seeing this array of colors will have a WTF moment
There was a problem hiding this comment.
By the way about naming, I prefer up/down to bullish/bearish. Every body get it without having to have some financial background
| const paletteColors = React.useMemo(() => { | ||
| if (!colors) { | ||
| return null; | ||
| } | ||
| return typeof colors === 'function' ? colors(theme.palette.mode) : colors; | ||
| }, [colors, theme.palette.mode]); |
There was a problem hiding this comment.
This will not work with composition.
Since we only have one candle stick series, what about having in series
colors: Colors | (mode: 'light'|'dark') => Colors with type Colors = { up: string; down: string; upWick?: string; downWick?: string }
With that, no need to document the colorGetter that looks over complicated compared to the potential use-cases
| import { type ChartsColorPaletteCallback } from '@mui/x-charts/colorPalettes'; | ||
|
|
||
| export const candlestickPaletteLight = ['#2e7d32', '#d32f2f']; | ||
| export const candlestickPaletteDark = ['#66bb6a', '#f44336']; | ||
|
|
||
| export const candlestickPalette: ChartsColorPaletteCallback = (mode) => | ||
| mode === 'dark' ? candlestickPaletteDark : candlestickPaletteLight; |
There was a problem hiding this comment.
knip would fail this file telling that palette light is the only one used
| import { type ChartsColorPaletteCallback } from '@mui/x-charts/colorPalettes'; | |
| export const candlestickPaletteLight = ['#2e7d32', '#d32f2f']; | |
| export const candlestickPaletteDark = ['#66bb6a', '#f44336']; | |
| export const candlestickPalette: ChartsColorPaletteCallback = (mode) => | |
| mode === 'dark' ? candlestickPaletteDark : candlestickPaletteLight; | |
| export const candlestickPaletteLight = ['#2e7d32', '#d32f2f']; |
| label?: string | ((location: 'tooltip' | 'legend') => string); | ||
| /** | ||
| * The color of the candle body when the close price is greater than or equal to the open price. | ||
| * @default Candlestick palette up color |
There was a problem hiding this comment.
Either we hardcode the color or pass allow upColor to be a callback
| * @default Candlestick palette up color | |
| * @default "#2e7d32" |
| upColor: seriesData.upColor ?? colors[0], | ||
| downColor: seriesData.downColor ?? colors[1], |
There was a problem hiding this comment.
My proposal is to have upColor and downColor accept a callback, but after processing those color are only string
The issue with having a centralised place for theming is the composition:
- You can't reuse
colorsbecause it will conflict with the color palette for other series - Creating a dedicated props in the DataProvider for a single type of series feels weird
…21838) Co-authored-by: alex <alex.fauquette@gmail.com>

Summary
upColoranddownColorproperties to the candlestick series type for customizing candle body colorscandlestickPalettewith green/red colors for bullish/bearish candles (with light/dark mode support)getColor.tsso tooltip, legend, and WebGL rendering share the same color logicuseCandlestickPlotDataby reusing the color processor instead of duplicating color logicColorCandlestickdemo with documentationCloses #21835