-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
charts enhancement #113
charts enhancement #113
Changes from all commits
08853c6
74de128
53ebf23
f7939a6
aa41128
a068194
10a0fae
9c338f8
ea0f07b
38ea250
d741fb1
ba0a17e
c8f87f0
2a19b52
95de744
68ead59
ddae4d8
8af4225
cfca325
3469da7
b141a31
b637a7b
2045cef
0b4077c
8a8160e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,30 +4,51 @@ import { | |
CANDLE_PERIODS, | ||
OHLCVData, | ||
setCandlePeriod, | ||
handleCrosshairMove, | ||
// fetchCandlesForInitialPeriod, | ||
initializeLegend, | ||
} from "../redux/priceChartSlice"; | ||
import { useAppDispatch, useAppSelector } from "../hooks"; | ||
import { formatPercentageChange } from "../utils"; | ||
|
||
interface PriceChartProps { | ||
data: OHLCVData[]; | ||
} | ||
|
||
function PriceChartCanvas(props: PriceChartProps) { | ||
const chartContainerRef = useRef<HTMLDivElement>(null); | ||
const dispatch = useAppDispatch(); | ||
const { data } = props; | ||
|
||
useEffect(() => { | ||
const chartContainer = chartContainerRef.current; | ||
|
||
// dispatch(fetchCandlesForInitialPeriod()); | ||
if (data && data.length > 0) { | ||
dispatch(initializeLegend()); | ||
} | ||
|
||
if (chartContainer) { | ||
const handleResize = () => { | ||
chart.applyOptions({ width: chartContainer.clientWidth }); | ||
}; | ||
|
||
const chart = createChart(chartContainer, { | ||
width: chartContainer.clientWidth, | ||
height: 450, | ||
|
||
// TODO: timescale is not visible | ||
height: 500, | ||
//MODIFY THEME COLOR HERE | ||
layout: { | ||
background: { color: "#181c27" }, | ||
textColor: "#DDD", | ||
}, | ||
//MODIFY THEME COLOR HERE | ||
grid: { | ||
vertLines: { color: "#444" }, | ||
horzLines: { color: "#444" }, | ||
}, | ||
timeScale: { | ||
//MODIFY THEME COLOR HERE | ||
borderColor: "#d3d3d4", | ||
timeVisible: true, | ||
}, | ||
}); | ||
|
@@ -37,30 +58,45 @@ function PriceChartCanvas(props: PriceChartProps) { | |
// OHLC | ||
const ohlcSeries = chart.addCandlestickSeries({}); | ||
ohlcSeries.setData(clonedData); | ||
|
||
chart.priceScale("right").applyOptions({ | ||
//MODIFY THEME COLOR HERE | ||
borderColor: "#d3d3d4", | ||
scaleMargins: { | ||
top: 0, | ||
bottom: 0.2, | ||
top: 0.1, | ||
bottom: 0.3, | ||
}, | ||
}); | ||
|
||
// Volume | ||
// Volume Initialization | ||
const volumeSeries = chart.addHistogramSeries({ | ||
priceFormat: { | ||
type: "volume", | ||
}, | ||
priceScaleId: "volume", | ||
color: "#eaeff5", | ||
}); | ||
|
||
volumeSeries.setData(clonedData); | ||
// VOLUME BARS | ||
// MODIFY THEME COLOR HERE | ||
volumeSeries.setData( | ||
data.map((datum) => ({ | ||
...datum, | ||
color: datum.close - datum.open <= 0 ? "#ef5350" : "#26a69a", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These colors should come from css variables. As strings in code they can be represented as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, probably we can import tailwind config object then and take the color from there (I guess only if it goes inside the canvas), we'll need to handle dark/light switching ourselves (but that's after-mvp). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did find this fiddle that will help with that after the mvp. |
||
})) | ||
); | ||
|
||
// volumeSeries.setData(clonedData); | ||
chart.priceScale("volume").applyOptions({ | ||
scaleMargins: { | ||
top: 0.8, | ||
bottom: 0, | ||
bottom: 0.01, | ||
}, | ||
}); | ||
|
||
//Crosshair Data for legend | ||
dispatch(handleCrosshairMove(chart, data, volumeSeries)); | ||
|
||
//Prevent Chart from clipping | ||
const chartDiv = chartContainer.querySelector(".tv-lightweight-charts"); | ||
if (chartDiv) { | ||
(chartDiv as HTMLElement).style.overflow = "visible"; | ||
|
@@ -70,37 +106,100 @@ function PriceChartCanvas(props: PriceChartProps) { | |
|
||
return () => { | ||
window.removeEventListener("resize", handleResize); | ||
// clearInterval(intervalId); | ||
chart.remove(); | ||
}; | ||
} | ||
}, [data]); | ||
|
||
return <div ref={chartContainerRef} />; | ||
}, [data, dispatch]); | ||
//Temporary brute force approach to trim the top of the chart to remove the gap | ||
return <div ref={chartContainerRef} className="relative mt-[-1.7rem]"></div>; | ||
} | ||
|
||
export function PriceChart() { | ||
const state = useAppSelector((state) => state.priceChart); | ||
const dispatch = useAppDispatch(); | ||
const candlePeriod = useAppSelector((state) => state.priceChart.candlePeriod); | ||
const candlePrice = useAppSelector( | ||
(state) => state.priceChart.legendCandlePrice | ||
); | ||
const change = useAppSelector((state) => state.priceChart.legendChange); | ||
const percChange = useAppSelector( | ||
(state) => state.priceChart.legendPercChange | ||
); | ||
const currentVolume = useAppSelector( | ||
(state) => state.priceChart.legendCurrentVolume | ||
); | ||
const isNegativeOrZero = useAppSelector( | ||
(state) => state.priceChart.isNegativeOrZero | ||
); | ||
|
||
return ( | ||
<div> | ||
<label htmlFor="candle-period-selector">Candle Period:</label> | ||
<select | ||
className="select select-ghost" | ||
id="candle-period-selector" | ||
value={state.candlePeriod} | ||
onChange={(e) => { | ||
dispatch(setCandlePeriod(e.target.value)); | ||
}} | ||
> | ||
{CANDLE_PERIODS.map((period) => ( | ||
<option key={period} value={period}> | ||
{period} | ||
</option> | ||
))} | ||
</select> | ||
|
||
<div className=""> | ||
<div className="flex p-[1vh]"> | ||
{CANDLE_PERIODS.map((period) => ( | ||
<button | ||
key={period} | ||
className={`px-[0.5vw] py-[0.5vw] text-sm font-roboto text-#d4e7df hover:bg-white hover:bg-opacity-30 hover:rounded-md ${ | ||
candlePeriod === period ? "text-blue-500" : "" | ||
}`} | ||
onClick={() => dispatch(setCandlePeriod(period))} | ||
> | ||
{period} | ||
</button> | ||
))} | ||
</div> | ||
<div className="flex justify-between text-sm font-roboto"> | ||
<div className="ml-4"> | ||
Open:{" "} | ||
<span | ||
className={isNegativeOrZero ? "text-red-500" : "text-green-500"} | ||
> | ||
{candlePrice?.open} | ||
</span> | ||
</div> | ||
<div> | ||
High:{" "} | ||
<span | ||
className={isNegativeOrZero ? "text-red-500" : "text-green-500"} | ||
Comment on lines
+142
to
+163
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here and below (and you probably can specify Please also remove There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I removed the font-roboto and swapped colors where I could in #145 |
||
> | ||
{candlePrice?.high} | ||
</span> | ||
</div> | ||
<div> | ||
Low:{" "} | ||
<span | ||
className={isNegativeOrZero ? "text-red-500" : "text-green-500"} | ||
> | ||
{candlePrice?.low} | ||
</span> | ||
</div> | ||
<div> | ||
Close:{" "} | ||
<span | ||
className={isNegativeOrZero ? "text-red-500" : "text-green-500"} | ||
> | ||
{candlePrice?.close} | ||
</span> | ||
</div> | ||
<div> | ||
Volume:{" "} | ||
<span | ||
className={isNegativeOrZero ? "text-red-500" : "text-green-500"} | ||
> | ||
{currentVolume === 0 ? 0 : currentVolume.toFixed(2)} | ||
</span> | ||
</div> | ||
<div className="mr-4"> | ||
Change:{" "} | ||
<span | ||
className={isNegativeOrZero ? "text-red-500" : "text-green-500"} | ||
> | ||
{change} | ||
{formatPercentageChange(percChange)} | ||
</span> | ||
</div> | ||
</div> | ||
</div> | ||
<PriceChartCanvas data={state.ohlcv} /> | ||
</div> | ||
); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These colors probably can also come from the theme settings. You can find what colors we currently have at
tailwind.config.js
underdaisyui
objects (only dark theme currently).Here is the list of color names and variables that you can use - https://daisyui.com/docs/colors/#-2 . Here in the chart settings you can use them as variables (e.g.
hsl(var(--b1))
). In other places where you style an html element in .tsx you can specify them as classes, e.g. for backgroundbg-base-100
or for text colortext-base-100
.