chart: Add candlestick chart (#1749)
## Description Add `CandlestickChart` component for visualizing financial OHLC data with candlestick patterns. - Introduced a new CandlestickChart for displaying OHLC (Open, High, Low, Close) values. - Updated ChartStory to include stock price data and render multiple candlestick chart variations. - Enhanced theme with bullish and bearish colors for candlestick representation. - Updated documentation to include CandlestickChart examples and usage. This addition enhances the charting library by providing a crucial tool for visualizing stock market trends. ## Screenshot <img width="1335" height="423" alt="image" src="https://github.com/user-attachments/assets/5df7078e-a469-4262-b645-6434d08b7ccf" /> ## How to Test ```bash cargo run -p gpui-component-story ``` ## Checklist - [x] I have read the [CONTRIBUTING](../CONTRIBUTING.md) document and followed the guidelines. - [x] Reviewed the changes in this PR and confirmed AI generated code (If any) is accurate. - [x] Passed `cargo run` for story tests related to the changes. - [ ] Tested macOS, Windows and Linux platforms performance (if the change is platform-specific)
This commit is contained in:
parent
bc1092a6e1
commit
9b3b2802cc
9 changed files with 445 additions and 9 deletions
|
|
@ -5,7 +5,7 @@ use gpui::{
|
|||
};
|
||||
use gpui_component::{
|
||||
ActiveTheme, StyledExt,
|
||||
chart::{AreaChart, BarChart, LineChart, PieChart},
|
||||
chart::{AreaChart, BarChart, CandlestickChart, LineChart, PieChart},
|
||||
divider::Divider,
|
||||
dock::PanelControl,
|
||||
h_flex, v_flex,
|
||||
|
|
@ -36,10 +36,20 @@ pub struct DailyDevice {
|
|||
pub watch: f64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize)]
|
||||
pub struct StockPrice {
|
||||
pub date: SharedString,
|
||||
pub open: f64,
|
||||
pub high: f64,
|
||||
pub low: f64,
|
||||
pub close: f64,
|
||||
}
|
||||
|
||||
pub struct ChartStory {
|
||||
focus_handle: FocusHandle,
|
||||
daily_devices: Vec<DailyDevice>,
|
||||
monthly_devices: Vec<MonthlyDevice>,
|
||||
stock_prices: Vec<StockPrice>,
|
||||
}
|
||||
|
||||
impl ChartStory {
|
||||
|
|
@ -52,10 +62,14 @@ impl ChartStory {
|
|||
"../fixtures/monthly-devices.json"
|
||||
))
|
||||
.unwrap();
|
||||
let stock_prices =
|
||||
serde_json::from_str::<Vec<StockPrice>>(include_str!("../fixtures/stock-prices.json"))
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
daily_devices,
|
||||
monthly_devices,
|
||||
stock_prices,
|
||||
focus_handle: cx.focus_handle(),
|
||||
}
|
||||
}
|
||||
|
|
@ -326,5 +340,58 @@ impl Render for ChartStory {
|
|||
cx,
|
||||
)),
|
||||
)
|
||||
.child(Divider::horizontal())
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_x_4()
|
||||
.h(px(400.))
|
||||
.child(chart_container(
|
||||
"Candlestick Chart",
|
||||
CandlestickChart::new(self.stock_prices.clone())
|
||||
.x(|d| d.date.clone())
|
||||
.open(|d| d.open)
|
||||
.high(|d| d.high)
|
||||
.low(|d| d.low)
|
||||
.close(|d| d.close),
|
||||
false,
|
||||
cx,
|
||||
))
|
||||
.child(chart_container(
|
||||
"Candlestick Chart - Narrow",
|
||||
CandlestickChart::new(self.stock_prices.clone())
|
||||
.x(|d| d.date.clone())
|
||||
.open(|d| d.open)
|
||||
.high(|d| d.high)
|
||||
.low(|d| d.low)
|
||||
.close(|d| d.close)
|
||||
.body_width_ratio(0.5),
|
||||
false,
|
||||
cx,
|
||||
))
|
||||
.child(chart_container(
|
||||
"Candlestick Chart - Wide",
|
||||
CandlestickChart::new(self.stock_prices.clone())
|
||||
.x(|d| d.date.clone())
|
||||
.open(|d| d.open)
|
||||
.high(|d| d.high)
|
||||
.low(|d| d.low)
|
||||
.close(|d| d.close)
|
||||
.body_width_ratio(1.0),
|
||||
false,
|
||||
cx,
|
||||
))
|
||||
.child(chart_container(
|
||||
"Candlestick Chart - Tick Margin",
|
||||
CandlestickChart::new(self.stock_prices.clone())
|
||||
.x(|d| d.date.clone())
|
||||
.open(|d| d.open)
|
||||
.high(|d| d.high)
|
||||
.low(|d| d.low)
|
||||
.close(|d| d.close)
|
||||
.tick_margin(2),
|
||||
false,
|
||||
cx,
|
||||
)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
44
crates/story/src/fixtures/stock-prices.json
Normal file
44
crates/story/src/fixtures/stock-prices.json
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
[
|
||||
{
|
||||
"date": "Jan",
|
||||
"open": 100.0,
|
||||
"high": 112.0,
|
||||
"low": 95.0,
|
||||
"close": 110.0
|
||||
},
|
||||
{
|
||||
"date": "Feb",
|
||||
"open": 110.0,
|
||||
"high": 112.0,
|
||||
"low": 108.0,
|
||||
"close": 111.0
|
||||
},
|
||||
{
|
||||
"date": "Mar",
|
||||
"open": 111.0,
|
||||
"high": 118.0,
|
||||
"low": 110.0,
|
||||
"close": 116.0
|
||||
},
|
||||
{
|
||||
"date": "Apr",
|
||||
"open": 116.0,
|
||||
"high": 120.0,
|
||||
"low": 108.0,
|
||||
"close": 110.0
|
||||
},
|
||||
{
|
||||
"date": "May",
|
||||
"open": 110.0,
|
||||
"high": 118.0,
|
||||
"low": 105.0,
|
||||
"close": 115.0
|
||||
},
|
||||
{
|
||||
"date": "Jun",
|
||||
"open": 115.0,
|
||||
"high": 125.0,
|
||||
"low": 113.0,
|
||||
"close": 123.0
|
||||
}
|
||||
]
|
||||
223
crates/ui/src/chart/candlestick_chart.rs
Normal file
223
crates/ui/src/chart/candlestick_chart.rs
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use gpui::{App, Bounds, Hsla, PathBuilder, Pixels, SharedString, TextAlign, Window, fill, px};
|
||||
use gpui_component_macros::IntoPlot;
|
||||
use num_traits::{Num, ToPrimitive};
|
||||
|
||||
use crate::{
|
||||
ActiveTheme, PixelsExt,
|
||||
plot::{
|
||||
AXIS_GAP, AxisText, Grid, Plot, PlotAxis, origin_point,
|
||||
scale::{Scale, ScaleBand, ScaleLinear, Sealed},
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(IntoPlot)]
|
||||
pub struct CandlestickChart<T, X, Y>
|
||||
where
|
||||
T: 'static,
|
||||
X: PartialEq + Into<SharedString> + 'static,
|
||||
Y: Copy + PartialOrd + Num + ToPrimitive + Sealed + 'static,
|
||||
{
|
||||
data: Vec<T>,
|
||||
x: Option<Rc<dyn Fn(&T) -> X>>,
|
||||
open: Option<Rc<dyn Fn(&T) -> Y>>,
|
||||
high: Option<Rc<dyn Fn(&T) -> Y>>,
|
||||
low: Option<Rc<dyn Fn(&T) -> Y>>,
|
||||
close: Option<Rc<dyn Fn(&T) -> Y>>,
|
||||
tick_margin: usize,
|
||||
body_width_ratio: f32,
|
||||
}
|
||||
|
||||
impl<T, X, Y> CandlestickChart<T, X, Y>
|
||||
where
|
||||
X: PartialEq + Into<SharedString> + 'static,
|
||||
Y: Copy + PartialOrd + Num + ToPrimitive + Sealed + 'static,
|
||||
{
|
||||
pub fn new<I>(data: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
{
|
||||
Self {
|
||||
data: data.into_iter().collect(),
|
||||
x: None,
|
||||
open: None,
|
||||
high: None,
|
||||
low: None,
|
||||
close: None,
|
||||
tick_margin: 1,
|
||||
body_width_ratio: 0.8,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn x(mut self, x: impl Fn(&T) -> X + 'static) -> Self {
|
||||
self.x = Some(Rc::new(x));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn open(mut self, open: impl Fn(&T) -> Y + 'static) -> Self {
|
||||
self.open = Some(Rc::new(open));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn high(mut self, high: impl Fn(&T) -> Y + 'static) -> Self {
|
||||
self.high = Some(Rc::new(high));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn low(mut self, low: impl Fn(&T) -> Y + 'static) -> Self {
|
||||
self.low = Some(Rc::new(low));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn close(mut self, close: impl Fn(&T) -> Y + 'static) -> Self {
|
||||
self.close = Some(Rc::new(close));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn tick_margin(mut self, tick_margin: usize) -> Self {
|
||||
self.tick_margin = tick_margin;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn body_width_ratio(mut self, ratio: f32) -> Self {
|
||||
self.body_width_ratio = ratio;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, X, Y> Plot for CandlestickChart<T, X, Y>
|
||||
where
|
||||
X: PartialEq + Into<SharedString> + 'static,
|
||||
Y: Copy + PartialOrd + Num + ToPrimitive + Sealed + 'static,
|
||||
{
|
||||
fn paint(&mut self, bounds: Bounds<Pixels>, window: &mut Window, cx: &mut App) {
|
||||
let (Some(x_fn), Some(open_fn), Some(high_fn), Some(low_fn), Some(close_fn)) = (
|
||||
self.x.as_ref(),
|
||||
self.open.as_ref(),
|
||||
self.high.as_ref(),
|
||||
self.low.as_ref(),
|
||||
self.close.as_ref(),
|
||||
) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let width = bounds.size.width.as_f32();
|
||||
let height = bounds.size.height.as_f32() - AXIS_GAP;
|
||||
|
||||
// X scale
|
||||
let x = ScaleBand::new(self.data.iter().map(|v| x_fn(v)).collect(), vec![0., width])
|
||||
.padding_inner(0.4)
|
||||
.padding_outer(0.2);
|
||||
let band_width = x.band_width();
|
||||
|
||||
// Y scale
|
||||
let all_values: Vec<Y> = self
|
||||
.data
|
||||
.iter()
|
||||
.flat_map(|d| vec![high_fn(d), low_fn(d), open_fn(d), close_fn(d)])
|
||||
.collect();
|
||||
let y = ScaleLinear::new(all_values, vec![height, 10.]);
|
||||
|
||||
// Draw X axis
|
||||
let x_label = self.data.iter().enumerate().filter_map(|(i, d)| {
|
||||
if (i + 1) % self.tick_margin == 0 {
|
||||
x.tick(&x_fn(d)).map(|x_tick| {
|
||||
AxisText::new(
|
||||
x_fn(d).into(),
|
||||
x_tick + band_width / 2.,
|
||||
cx.theme().muted_foreground,
|
||||
)
|
||||
.align(TextAlign::Center)
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
PlotAxis::new()
|
||||
.x(height)
|
||||
.x_label(x_label)
|
||||
.stroke(cx.theme().border)
|
||||
.paint(&bounds, window, cx);
|
||||
|
||||
// Draw grid
|
||||
Grid::new()
|
||||
.y((0..=3).map(|i| height * i as f32 / 4.0).collect())
|
||||
.stroke(cx.theme().border)
|
||||
.dash_array(&[px(4.), px(2.)])
|
||||
.paint(&bounds, window);
|
||||
|
||||
// Draw candlesticks
|
||||
let origin = bounds.origin;
|
||||
let x_fn = x_fn.clone();
|
||||
let open_fn = open_fn.clone();
|
||||
let high_fn = high_fn.clone();
|
||||
let low_fn = low_fn.clone();
|
||||
let close_fn = close_fn.clone();
|
||||
|
||||
for d in &self.data {
|
||||
let x_tick = x.tick(&x_fn(d));
|
||||
let Some(x_tick) = x_tick else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// Get OHLC values for the current data point
|
||||
let open = open_fn(d);
|
||||
let high = high_fn(d);
|
||||
let low = low_fn(d);
|
||||
let close = close_fn(d);
|
||||
|
||||
// Convert values to pixel coordinates
|
||||
let open_y = y.tick(&open);
|
||||
let high_y = y.tick(&high);
|
||||
let low_y = y.tick(&low);
|
||||
let close_y = y.tick(&close);
|
||||
|
||||
let (Some(open_y), Some(high_y), Some(low_y), Some(close_y)) =
|
||||
(open_y, high_y, low_y, close_y)
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// Determine if bullish (close > open) or bearish (close < open)
|
||||
let is_bullish = close > open;
|
||||
let color: Hsla = if is_bullish {
|
||||
cx.theme().bullish
|
||||
} else {
|
||||
cx.theme().bearish
|
||||
};
|
||||
|
||||
// Calculate candlestick body dimensions
|
||||
let center_x = x_tick + band_width / 2.;
|
||||
let body_width = band_width * self.body_width_ratio;
|
||||
let body_left = center_x - body_width / 2.;
|
||||
let body_right = center_x + body_width / 2.;
|
||||
|
||||
// Draw wick (high to low line)
|
||||
let mut wick_builder = PathBuilder::stroke(px(1.));
|
||||
wick_builder.move_to(origin_point(px(center_x), px(high_y), origin));
|
||||
wick_builder.line_to(origin_point(px(center_x), px(low_y), origin));
|
||||
|
||||
if let Ok(path) = wick_builder.build() {
|
||||
window.paint_path(path, color);
|
||||
}
|
||||
|
||||
// Draw body (open to close rectangle)
|
||||
// For bullish: top is close, bottom is open
|
||||
// For bearish: top is open, bottom is close
|
||||
let (top, bottom) = if is_bullish {
|
||||
(close_y, open_y)
|
||||
} else {
|
||||
(open_y, close_y)
|
||||
};
|
||||
|
||||
let body_bounds = Bounds::from_corners(
|
||||
origin_point(px(body_left), px(top), origin),
|
||||
origin_point(px(body_right), px(bottom), origin),
|
||||
);
|
||||
|
||||
window.paint_quad(fill(body_bounds, color));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,11 @@
|
|||
mod area_chart;
|
||||
mod bar_chart;
|
||||
mod candlestick_chart;
|
||||
mod line_chart;
|
||||
mod pie_chart;
|
||||
|
||||
pub use area_chart::AreaChart;
|
||||
pub use bar_chart::BarChart;
|
||||
pub use candlestick_chart::CandlestickChart;
|
||||
pub use line_chart::LineChart;
|
||||
pub use pie_chart::PieChart;
|
||||
|
|
|
|||
|
|
@ -77,6 +77,8 @@
|
|||
"success.active.background": "#16a34a",
|
||||
"success.foreground": "#f9fafb",
|
||||
"success.hover.background": "#22c55ee6",
|
||||
"bullish.background": "#22c55e",
|
||||
"bearish.background": "#ef4444",
|
||||
"switch.background": "#d4d4d4",
|
||||
"tab.background": "#00000000",
|
||||
"tab.active.background": "#ffffff",
|
||||
|
|
@ -278,6 +280,8 @@
|
|||
"success.active.background": "#104224",
|
||||
"success.foreground": "#f0fdf4",
|
||||
"success.hover.background": "#165b32",
|
||||
"bullish.background": "#22c55e",
|
||||
"bearish.background": "#ef4444",
|
||||
"switch.background": "#404040",
|
||||
"tab.background": "#00000000",
|
||||
"tab.active.background": "#0a0a0a",
|
||||
|
|
|
|||
|
|
@ -281,6 +281,12 @@ pub struct ThemeConfigColors {
|
|||
/// Success active background color.
|
||||
#[serde(rename = "success.active.background")]
|
||||
pub success_active: Option<SharedString>,
|
||||
/// Bullish color for candlestick charts (upward price movement).
|
||||
#[serde(rename = "bullish.background")]
|
||||
pub bullish: Option<SharedString>,
|
||||
/// Bearish color for candlestick charts (downward price movement).
|
||||
#[serde(rename = "bearish.background")]
|
||||
pub bearish: Option<SharedString>,
|
||||
/// Switch background color.
|
||||
#[serde(rename = "switch.background")]
|
||||
pub switch: Option<SharedString>,
|
||||
|
|
@ -508,6 +514,8 @@ impl ThemeColor {
|
|||
success_active,
|
||||
fallback = self.success.darken(active_darken)
|
||||
);
|
||||
apply_color!(bullish, fallback = self.green);
|
||||
apply_color!(bearish, fallback = self.red);
|
||||
apply_color!(info, fallback = self.cyan);
|
||||
apply_color!(info_foreground, fallback = self.primary_foreground);
|
||||
apply_color!(
|
||||
|
|
|
|||
|
|
@ -147,6 +147,10 @@ pub struct ThemeColor {
|
|||
pub success_hover: Hsla,
|
||||
/// Success active background color.
|
||||
pub success_active: Hsla,
|
||||
/// Bullish color for candlestick charts (upward price movement).
|
||||
pub bullish: Hsla,
|
||||
/// Bearish color for candlestick charts (downward price movement).
|
||||
pub bearish: Hsla,
|
||||
/// Switch background color.
|
||||
pub switch: Hsla,
|
||||
/// Switch thumb background color.
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
---
|
||||
title: Chart
|
||||
description: Beautiful charts and graphs for data visualization including line, bar, area, and pie charts.
|
||||
description: Beautiful charts and graphs for data visualization including line, bar, area, pie, and candlestick charts.
|
||||
---
|
||||
|
||||
# Chart
|
||||
|
||||
A comprehensive charting library providing Line, Bar, Area, and Pie charts for data visualization. The charts feature smooth animations, customizable styling, tooltips, legends, and automatic theming that adapts to your application's theme.
|
||||
A comprehensive charting library providing Line, Bar, Area, Pie, and Candlestick charts for data visualization. The charts feature smooth animations, customizable styling, tooltips, legends, and automatic theming that adapts to your application's theme.
|
||||
|
||||
## Import
|
||||
|
||||
```rust
|
||||
use gpui_component::chart::{LineChart, BarChart, AreaChart, PieChart};
|
||||
use gpui_component::chart::{LineChart, BarChart, AreaChart, PieChart, CandlestickChart};
|
||||
```
|
||||
|
||||
## Chart Types
|
||||
|
|
@ -208,6 +208,65 @@ PieChart::new(data)
|
|||
.pad_angle(4. / 100.) // 4% padding
|
||||
```
|
||||
|
||||
### CandlestickChart
|
||||
|
||||
A candlestick chart displays financial data using OHLC (Open, High, Low, Close) values, perfect for visualizing stock prices and market trends.
|
||||
|
||||
#### Basic Candlestick Chart
|
||||
|
||||
```rust
|
||||
#[derive(Clone)]
|
||||
struct StockPrice {
|
||||
pub date: String,
|
||||
pub open: f64,
|
||||
pub high: f64,
|
||||
pub low: f64,
|
||||
pub close: f64,
|
||||
}
|
||||
|
||||
let data = vec![
|
||||
StockPrice { date: "Jan".to_string(), open: 100.0, high: 110.0, low: 95.0, close: 105.0 },
|
||||
StockPrice { date: "Feb".to_string(), open: 105.0, high: 115.0, low: 100.0, close: 112.0 },
|
||||
StockPrice { date: "Mar".to_string(), open: 112.0, high: 120.0, low: 108.0, close: 115.0 },
|
||||
];
|
||||
|
||||
CandlestickChart::new(data)
|
||||
.x(|d| d.date.clone())
|
||||
.open(|d| d.open)
|
||||
.high(|d| d.high)
|
||||
.low(|d| d.low)
|
||||
.close(|d| d.close)
|
||||
```
|
||||
|
||||
#### Candlestick Chart Customization
|
||||
|
||||
```rust
|
||||
// Adjust body width ratio (default: 0.6)
|
||||
CandlestickChart::new(data)
|
||||
.x(|d| d.date.clone())
|
||||
.open(|d| d.open)
|
||||
.high(|d| d.high)
|
||||
.low(|d| d.low)
|
||||
.close(|d| d.close)
|
||||
.body_width_ratio(0.4) // Narrower bodies
|
||||
|
||||
// Custom tick spacing
|
||||
CandlestickChart::new(data)
|
||||
.x(|d| d.date.clone())
|
||||
.open(|d| d.open)
|
||||
.high(|d| d.high)
|
||||
.low(|d| d.low)
|
||||
.close(|d| d.close)
|
||||
.tick_margin(2) // Show every 2nd tick
|
||||
```
|
||||
|
||||
#### Candlestick Chart Colors
|
||||
|
||||
The candlestick chart automatically uses theme colors:
|
||||
|
||||
- **Bullish** (close > open): `bullish` color (green)
|
||||
- **Bearish** (close < open): `bearish` color (red)
|
||||
|
||||
## Data Structures
|
||||
|
||||
### Example Data Types
|
||||
|
|
@ -318,6 +377,7 @@ let chart = LineChart::new(data)
|
|||
- [BarChart]
|
||||
- [AreaChart]
|
||||
- [PieChart]
|
||||
- [CandlestickChart]
|
||||
|
||||
## Examples
|
||||
|
||||
|
|
@ -443,13 +503,36 @@ struct StockData {
|
|||
volume: u64,
|
||||
}
|
||||
|
||||
fn stock_chart(data: Vec<StockData>, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
#[derive(Clone)]
|
||||
struct StockOHLC {
|
||||
date: String,
|
||||
open: f64,
|
||||
high: f64,
|
||||
low: f64,
|
||||
close: f64,
|
||||
}
|
||||
|
||||
fn stock_chart(ohlc_data: Vec<StockOHLC>, price_data: Vec<StockData>, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
v_flex()
|
||||
.gap_4()
|
||||
.child(
|
||||
chart_container(
|
||||
"Stock Price",
|
||||
LineChart::new(data.clone())
|
||||
"Stock Price - Candlestick",
|
||||
CandlestickChart::new(ohlc_data.clone())
|
||||
.x(|d| d.date.clone())
|
||||
.open(|d| d.open)
|
||||
.high(|d| d.high)
|
||||
.low(|d| d.low)
|
||||
.close(|d| d.close)
|
||||
.tick_margin(3),
|
||||
false,
|
||||
cx,
|
||||
)
|
||||
)
|
||||
.child(
|
||||
chart_container(
|
||||
"Stock Price - Line",
|
||||
LineChart::new(price_data.clone())
|
||||
.x(|d| d.date.clone())
|
||||
.y(|d| d.price)
|
||||
.stroke(cx.theme().chart_1)
|
||||
|
|
@ -462,7 +545,7 @@ fn stock_chart(data: Vec<StockData>, cx: &mut Context<Self>) -> impl IntoElement
|
|||
.child(
|
||||
chart_container(
|
||||
"Trading Volume",
|
||||
BarChart::new(data)
|
||||
BarChart::new(price_data)
|
||||
.x(|d| d.date.clone())
|
||||
.y(|d| d.volume as f64)
|
||||
.fill(|d| {
|
||||
|
|
@ -627,3 +710,4 @@ impl LiveChart {
|
|||
[BarChart]: https://docs.rs/gpui-component/latest/gpui_component/chart/struct.BarChart.html
|
||||
[AreaChart]: https://docs.rs/gpui-component/latest/gpui_component/chart/struct.AreaChart.html
|
||||
[PieChart]: https://docs.rs/gpui-component/latest/gpui_component/chart/struct.PieChart.html
|
||||
[CandlestickChart]: https://docs.rs/gpui-component/latest/gpui_component/chart/struct.CandlestickChart.html
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ collapsed: false
|
|||
### Advanced Components
|
||||
|
||||
- [Calendar](calendar) - Calendar display and navigation
|
||||
- [Chart](chart) - Data visualization charts (Line, Bar, Area, Pie)
|
||||
- [Chart](chart) - Data visualization charts (Line, Bar, Area, Pie, Candlestick)
|
||||
- [List](list) - List display with items
|
||||
- [Menu](menu) - Menu and context menu and dropdown menu.
|
||||
- [Settings](settings) - Settings UI
|
||||
|
|
|
|||
Loading…
Reference in a new issue