table: Improve sort icon color and fix stripe row display. (#578)

- Improve sort icon color:

<img width="139" alt="image"
src="https://github.com/user-attachments/assets/6374c26a-4555-4735-953b-dbd961fe5b31"
/>

- Avoid duplicate border when enabled fixed column.

<img width="587" alt="image"
src="https://github.com/user-attachments/assets/6e186d29-5d8a-404e-b160-20c2af6a16fa"
/>


TODO

- [x] The extra rows not show when `stripe` is true.
This commit is contained in:
Jason Lee 2025-01-26 16:25:34 +08:00 committed by GitHub
parent 649e765729
commit e658aeee96
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 160 additions and 101 deletions

View file

@ -1,4 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevrons-up-down">
<path opacity="0.5" d="m7 15 5 5 5-5"/>
<path d="m7 9 5-5 5 5"/>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-chevrons-up-down"
>
<path opacity="0.2" d="m7 15 5 5 5-5" />
<path d="m7 9 5-5 5 5" />
</svg>

Before

Width:  |  Height:  |  Size: 297 B

After

Width:  |  Height:  |  Size: 340 B

View file

@ -1,4 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevrons-up-down">
<path d="m7 15 5 5 5-5"/>
<path opacity="0.5" d="m7 9 5-5 5 5"/>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-chevrons-up-down"
>
<path d="m7 15 5 5 5-5" />
<path opacity="0.2" d="m7 9 5-5 5 5" />
</svg>

Before

Width:  |  Height:  |  Size: 297 B

After

Width:  |  Height:  |  Size: 340 B

View file

@ -200,52 +200,44 @@ impl StockTableDelegate {
Column::new("price", "Price", Some(ColSort::Default)),
Column::new("change", "Chg", Some(ColSort::Default)),
Column::new("change_percent", "Chg%", Some(ColSort::Default)),
Column::new("volume", "Volume", Some(ColSort::Default)),
Column::new("turnover", "Turnover", Some(ColSort::Default)),
Column::new("market_cap", "Market Cap", Some(ColSort::Default)),
Column::new("ttm", "TTM", Some(ColSort::Default)),
Column::new("five_mins_ranking", "5m Ranking", Some(ColSort::Default)),
Column::new("th60_days_ranking", "60d Ranking", Some(ColSort::Default)),
Column::new("year_change_percent", "Year Chg%", Some(ColSort::Default)),
Column::new("bid", "Bid", Some(ColSort::Default)),
Column::new("bid_volume", "Bid Vol", Some(ColSort::Default)),
Column::new("ask", "Ask", Some(ColSort::Default)),
Column::new("ask_volume", "Ask Vol", Some(ColSort::Default)),
Column::new("open", "Open", Some(ColSort::Default)),
Column::new("prev_close", "Prev Close", Some(ColSort::Default)),
Column::new("high", "High", Some(ColSort::Default)),
Column::new("low", "Low", Some(ColSort::Default)),
Column::new("turnover_rate", "Turnover Rate", Some(ColSort::Default)),
Column::new("rise_rate", "Rise Rate", Some(ColSort::Default)),
Column::new("amplitude", "Amplitude", Some(ColSort::Default)),
Column::new("pe_status", "P/E", Some(ColSort::Default)),
Column::new("pb_status", "P/B", Some(ColSort::Default)),
Column::new("volume_ratio", "Volume Ratio", Some(ColSort::Default)),
Column::new("bid_ask_ratio", "Bid Ask Ratio", Some(ColSort::Default)),
Column::new(
"latest_pre_close",
"Latest Pre Close",
Some(ColSort::Default),
),
Column::new(
"latest_post_close",
"Latest Post Close",
Some(ColSort::Default),
),
Column::new("pre_market_cap", "Pre Mkt Cap", Some(ColSort::Default)),
Column::new("pre_market_percent", "Pre Mkt%", Some(ColSort::Default)),
Column::new("pre_market_change", "Pre Mkt Chg", Some(ColSort::Default)),
Column::new("post_market_cap", "Post Mkt Cap", Some(ColSort::Default)),
Column::new("post_market_percent", "Post Mkt%", Some(ColSort::Default)),
Column::new("post_market_change", "Post Mkt Chg", Some(ColSort::Default)),
Column::new("float_cap", "Float Cap", Some(ColSort::Default)),
Column::new("shares", "Shares", Some(ColSort::Default)),
Column::new("shares_float", "Float Shares", Some(ColSort::Default)),
Column::new("day_5_ranking", "5d Ranking", Some(ColSort::Default)),
Column::new("day_10_ranking", "10d Ranking", Some(ColSort::Default)),
Column::new("day_30_ranking", "30d Ranking", Some(ColSort::Default)),
Column::new("day_120_ranking", "120d Ranking", Some(ColSort::Default)),
Column::new("day_250_ranking", "250d Ranking", Some(ColSort::Default)),
Column::new("volume", "Volume", None),
Column::new("turnover", "Turnover", None),
Column::new("market_cap", "Market Cap", None),
Column::new("ttm", "TTM", None),
Column::new("five_mins_ranking", "5m Ranking", None),
Column::new("th60_days_ranking", "60d Ranking", None),
Column::new("year_change_percent", "Year Chg%", None),
Column::new("bid", "Bid", None),
Column::new("bid_volume", "Bid Vol", None),
Column::new("ask", "Ask", None),
Column::new("ask_volume", "Ask Vol", None),
Column::new("open", "Open", None),
Column::new("prev_close", "Prev Close", None),
Column::new("high", "High", None),
Column::new("low", "Low", None),
Column::new("turnover_rate", "Turnover Rate", None),
Column::new("rise_rate", "Rise Rate", None),
Column::new("amplitude", "Amplitude", None),
Column::new("pe_status", "P/E", None),
Column::new("pb_status", "P/B", None),
Column::new("volume_ratio", "Volume Ratio", None),
Column::new("bid_ask_ratio", "Bid Ask Ratio", None),
Column::new("latest_pre_close", "Latest Pre Close", None),
Column::new("latest_post_close", "Latest Post Close", None),
Column::new("pre_market_cap", "Pre Mkt Cap", None),
Column::new("pre_market_percent", "Pre Mkt%", None),
Column::new("pre_market_change", "Pre Mkt Chg", None),
Column::new("post_market_cap", "Post Mkt Cap", None),
Column::new("post_market_percent", "Post Mkt%", None),
Column::new("post_market_change", "Post Mkt Chg", None),
Column::new("float_cap", "Float Cap", None),
Column::new("shares", "Shares", None),
Column::new("shares_float", "Float Shares", None),
Column::new("day_5_ranking", "5d Ranking", None),
Column::new("day_10_ranking", "10d Ranking", None),
Column::new("day_30_ranking", "30d Ranking", None),
Column::new("day_120_ranking", "120d Ranking", None),
Column::new("day_250_ranking", "250d Ranking", None),
],
loop_selection: true,
col_resize: true,
@ -263,7 +255,7 @@ impl StockTableDelegate {
fn update_stocks(&mut self, size: usize) {
self.stocks = random_stocks(size);
self.is_eof = false;
self.is_eof = size <= 50;
self.loading = false;
self.full_loading = false;
}
@ -477,6 +469,17 @@ impl TableDelegate for StockTableDelegate {
ColSort::Descending => b.id.cmp(&a.id),
_ => a.id.cmp(&b.id),
}),
"symbol" => self.stocks.sort_by(|a, b| match sort {
ColSort::Descending => b.symbol.cmp(&a.symbol),
_ => a.id.cmp(&b.id),
}),
"change" | "change_percent" => self.stocks.sort_by(|a, b| match sort {
ColSort::Descending => b
.change
.partial_cmp(&a.change)
.unwrap_or(std::cmp::Ordering::Equal),
_ => a.id.cmp(&b.id),
}),
_ => {}
}
}
@ -652,6 +655,7 @@ impl TableStory {
fn toggle_col_resize(&mut self, checked: &bool, cx: &mut ViewContext<Self>) {
self.table.update(cx, |table, cx| {
table.delegate_mut().col_resize = *checked;
table.refresh(cx);
cx.notify();
});
}
@ -659,6 +663,7 @@ impl TableStory {
fn toggle_col_order(&mut self, checked: &bool, cx: &mut ViewContext<Self>) {
self.table.update(cx, |table, cx| {
table.delegate_mut().col_order = *checked;
table.refresh(cx);
cx.notify();
});
}
@ -666,6 +671,7 @@ impl TableStory {
fn toggle_col_sort(&mut self, checked: &bool, cx: &mut ViewContext<Self>) {
self.table.update(cx, |table, cx| {
table.delegate_mut().col_sort = *checked;
table.refresh(cx);
cx.notify();
});
}
@ -673,6 +679,7 @@ impl TableStory {
fn toggle_col_selection(&mut self, checked: &bool, cx: &mut ViewContext<Self>) {
self.table.update(cx, |table, cx| {
table.delegate_mut().col_selection = *checked;
table.refresh(cx);
cx.notify();
});
}

View file

@ -753,9 +753,14 @@ where
}
}
#[inline]
fn render_cell(&self, col_ix: usize, _cx: &mut ViewContext<Self>) -> Div {
let col_width = self.col_groups[col_ix].width;
let col_padding = self.col_groups[col_ix].padding;
let Some(col_group) = self.col_groups.get(col_ix) else {
return div();
};
let col_width = col_group.width;
let col_padding = col_group.padding;
div()
.w(col_width)
@ -1037,11 +1042,9 @@ where
// Render left fixed columns
this.child(
h_flex()
.id("table-head-fixed-left")
.relative()
.h_full()
.bg(cx.theme().table_head)
.border_r_1()
.border_color(cx.theme().border)
.children(
self.col_groups
.iter()
@ -1049,6 +1052,18 @@ where
.enumerate()
.map(|(col_ix, _)| self.render_th(col_ix, cx)),
)
.child(
// Fixed columns border
div()
.absolute()
.top_0()
.right_0()
.bottom_0()
.w_0()
.flex_shrink_0()
.border_r_1()
.border_color(cx.theme().border),
)
.child(
canvas(
move |bounds, cx| {
@ -1102,6 +1117,7 @@ where
row_ix: usize,
rows_count: usize,
left_cols_count: usize,
col_sizes: Rc<Vec<gpui::Size<Pixels>>>,
cols_count: usize,
cx: &mut ViewContext<Self>,
) -> impl IntoElement {
@ -1109,13 +1125,6 @@ where
let is_stripe_row = self.stripe && row_ix % 2 != 0;
let is_selected = self.selected_row == Some(row_ix);
let view = cx.view().clone();
let col_sizes: Rc<Vec<gpui::Size<Pixels>>> = Rc::new(
self.col_groups
.iter()
.skip(left_cols_count)
.map(|col| col.bounds.size)
.collect(),
);
if row_ix < rows_count {
self.delegate
@ -1135,13 +1144,12 @@ where
this.bg(cx.theme().table_hover)
}
})
.children(if left_cols_count > 0 {
.when(left_cols_count > 0, |this| {
// Left fixed columns
Some(
this.child(
h_flex()
.relative()
.h_full()
.border_r_1()
.border_color(cx.theme().table_row_border)
.children({
let mut items = Vec::with_capacity(left_cols_count);
@ -1155,10 +1163,20 @@ where
});
items
}),
})
.child(
// Fixed columns border
div()
.absolute()
.top_0()
.right_0()
.bottom_0()
.w_0()
.flex_shrink_0()
.border_r_1()
.border_color(cx.theme().border),
),
)
} else {
None
})
.child(
h_flex()
@ -1265,6 +1283,34 @@ where
}
}
/// Calculate the extra rows needed to fill the table empty space when `stripe` is true.
fn calculate_extra_rows_needed(&self, rows_count: usize) -> usize {
if !self.stripe {
return 0;
}
let mut extra_rows_needed = 0;
let row_height = self.size.table_row_height();
let total_height = self
.vertical_scroll_handle
.0
.borrow()
.base_handle
.bounds()
.size
.height;
let actual_height = row_height * rows_count as f32;
let remaining_height = total_height - actual_height;
if remaining_height > px(0.) {
extra_rows_needed = (remaining_height / row_height).ceil() as usize;
}
extra_rows_needed
}
#[inline]
fn measure_render_td(
&mut self,
@ -1341,35 +1387,7 @@ where
let left_cols_count = self.fixed_cols.left;
let rows_count = self.delegate.rows_count(cx);
let loading = self.delegate.loading(cx);
let row_height = self
.vertical_scroll_handle
.0
.borrow()
.last_item_size
.map(|size| size.item.height);
let total_height = self
.vertical_scroll_handle
.0
.borrow()
.base_handle
.bounds()
.size
.height;
// Calculate the extra rows needed to fill the table for stripe style.
let mut extra_rows_needed = 0;
if self.stripe {
if let Some(row_height) = row_height {
if row_height > px(0.) {
let actual_height = row_height * rows_count as f32;
let remaining_height = total_height - actual_height;
if remaining_height > px(0.) {
extra_rows_needed = (remaining_height / row_height).ceil() as usize;
}
}
}
}
let extra_rows_needed = self.calculate_extra_rows_needed(rows_count);
let inner_table = v_flex()
.key_context("Table")
@ -1405,6 +1423,17 @@ where
rows_count + extra_rows_needed,
{
move |table, visible_range, cx| {
// We must calculate the col sizes here, because the col sizes
// need render_th first, then that method will set the bounds of each col.
let col_sizes: Rc<Vec<gpui::Size<Pixels>>> = Rc::new(
table
.col_groups
.iter()
.skip(left_cols_count)
.map(|col| col.bounds.size)
.collect(),
);
table.load_more_if_need(rows_count, visible_range.end, cx);
table.update_visible_range_if_need(
visible_range.clone(),
@ -1430,6 +1459,7 @@ where
row_ix,
rows_count,
left_cols_count,
col_sizes.clone(),
cols_count,
cx,
));