table: Add to support fixed column on left to Table. (#295)
- Update table details, fix table head height. - Add `table_row_border` theme color and use this for row border. ## Demo https://github.com/user-attachments/assets/91df4b9d-f079-4ddb-b14d-fbcf303dcc44 Fix #292
This commit is contained in:
parent
33e5fdcb78
commit
13e42dfac3
3 changed files with 230 additions and 169 deletions
|
|
@ -13,7 +13,7 @@ use ui::{
|
||||||
input::{InputEvent, TextInput},
|
input::{InputEvent, TextInput},
|
||||||
label::Label,
|
label::Label,
|
||||||
prelude::FluentBuilder as _,
|
prelude::FluentBuilder as _,
|
||||||
table::{ColSort, Table, TableDelegate, TableEvent},
|
table::{ColFixed, ColSort, Table, TableDelegate, TableEvent},
|
||||||
v_flex, Selectable, Sizable, Size,
|
v_flex, Selectable, Sizable, Size,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -290,6 +290,14 @@ impl TableDelegate for StockTableDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn col_fixed(&self, col_ix: usize) -> Option<ui::table::ColFixed> {
|
||||||
|
if col_ix < 4 {
|
||||||
|
Some(ColFixed::Left)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn can_resize_col(&self, col_ix: usize) -> bool {
|
fn can_resize_col(&self, col_ix: usize) -> bool {
|
||||||
return self.col_resize && col_ix > 1;
|
return self.col_resize && col_ix > 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use crate::{
|
||||||
h_flex,
|
h_flex,
|
||||||
scroll::{ScrollableAxis, ScrollableMask, Scrollbar, ScrollbarState},
|
scroll::{ScrollableAxis, ScrollableMask, Scrollbar, ScrollbarState},
|
||||||
theme::ActiveTheme,
|
theme::ActiveTheme,
|
||||||
v_flex, Icon, IconName, Sizable, Size, StyledExt,
|
v_flex, Icon, IconName, Sizable, Size,
|
||||||
};
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, canvas, div, prelude::FluentBuilder, px, uniform_list, AppContext, Bounds, Div,
|
actions, canvas, div, prelude::FluentBuilder, px, uniform_list, AppContext, Bounds, Div,
|
||||||
|
|
@ -36,11 +36,17 @@ pub fn init(cx: &mut AppContext) {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum ColFixed {
|
||||||
|
Left,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
struct ColGroup {
|
struct ColGroup {
|
||||||
width: Option<Pixels>,
|
width: Option<Pixels>,
|
||||||
bounds: Bounds<Pixels>,
|
bounds: Bounds<Pixels>,
|
||||||
sort: Option<ColSort>,
|
sort: Option<ColSort>,
|
||||||
|
fixed: Option<ColFixed>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
@ -156,6 +162,11 @@ pub trait TableDelegate: Sized + 'static {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the fixed side of the column at the given index.
|
||||||
|
fn col_fixed(&self, col_ix: usize) -> Option<ColFixed> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
/// Perform sort on the column at the given index.
|
/// Perform sort on the column at the given index.
|
||||||
fn perform_sort(&mut self, col_ix: usize, sort: ColSort, cx: &mut ViewContext<Table<Self>>) {}
|
fn perform_sort(&mut self, col_ix: usize, sort: ColSort, cx: &mut ViewContext<Table<Self>>) {}
|
||||||
|
|
||||||
|
|
@ -299,6 +310,7 @@ where
|
||||||
width: self.delegate.col_width(col_ix),
|
width: self.delegate.col_width(col_ix),
|
||||||
bounds: Bounds::default(),
|
bounds: Bounds::default(),
|
||||||
sort: self.delegate.col_sort(col_ix),
|
sort: self.delegate.col_sort(col_ix),
|
||||||
|
fixed: self.delegate.col_fixed(col_ix),
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
|
@ -410,8 +422,8 @@ where
|
||||||
.overflow_hidden()
|
.overflow_hidden()
|
||||||
.whitespace_nowrap()
|
.whitespace_nowrap()
|
||||||
.map(|this| match self.size {
|
.map(|this| match self.size {
|
||||||
Size::XSmall => this.text_sm().py_0().px_1(),
|
Size::XSmall => this.text_sm().py_0p5().px_1(),
|
||||||
Size::Small => this.text_sm().py_0p5().px_1p5(),
|
Size::Small => this.text_sm().py_1().px_1p5(),
|
||||||
Size::Large => this.py_1p5().px_3(),
|
Size::Large => this.py_1p5().px_3(),
|
||||||
_ => this.py_1().px_2(),
|
_ => this.py_1().px_2(),
|
||||||
})
|
})
|
||||||
|
|
@ -473,8 +485,11 @@ where
|
||||||
return div().into_any_element();
|
return div().into_any_element();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let group_id = SharedString::from(format!("resizable-handle:{}", ix));
|
||||||
|
|
||||||
h_flex()
|
h_flex()
|
||||||
.id(("resizable-handle", ix))
|
.id(("resizable-handle", ix))
|
||||||
|
.group(group_id.clone())
|
||||||
.occlude()
|
.occlude()
|
||||||
.cursor_col_resize()
|
.cursor_col_resize()
|
||||||
.h_full()
|
.h_full()
|
||||||
|
|
@ -485,9 +500,9 @@ where
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.h_full()
|
.h_full()
|
||||||
.h_5()
|
|
||||||
.justify_center()
|
.justify_center()
|
||||||
.bg(cx.theme().border)
|
.bg(cx.theme().table_row_border)
|
||||||
|
.group_hover(group_id, |this| this.bg(cx.theme().border).h_full())
|
||||||
.w(px(1.)),
|
.w(px(1.)),
|
||||||
)
|
)
|
||||||
.on_drag_move(cx.listener(move |view, e: &DragMoveEvent<ResizeCol>, cx| {
|
.on_drag_move(cx.listener(move |view, e: &DragMoveEvent<ResizeCol>, cx| {
|
||||||
|
|
@ -616,6 +631,18 @@ where
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn move_col(&mut self, col_ix: usize, to_ix: usize, cx: &mut ViewContext<Self>) {
|
||||||
|
if col_ix == to_ix {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.delegate.move_col(col_ix, to_ix);
|
||||||
|
let col_group = self.col_groups.remove(col_ix);
|
||||||
|
self.col_groups.insert(to_ix, col_group);
|
||||||
|
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
|
||||||
fn render_sort_icon(
|
fn render_sort_icon(
|
||||||
&self,
|
&self,
|
||||||
col_ix: usize,
|
col_ix: usize,
|
||||||
|
|
@ -750,16 +777,182 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_col(&mut self, col_ix: usize, to_ix: usize, cx: &mut ViewContext<Self>) {
|
fn render_table_head(
|
||||||
if col_ix == to_ix {
|
&mut self,
|
||||||
return;
|
left_cols_count: usize,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) -> impl IntoElement {
|
||||||
|
let view = cx.view().clone();
|
||||||
|
let horizontal_scroll_handle = self.horizontal_scroll_handle.clone();
|
||||||
|
|
||||||
|
h_flex()
|
||||||
|
.w_full()
|
||||||
|
.flex_shrink_0()
|
||||||
|
.border_b_1()
|
||||||
|
.border_color(cx.theme().border)
|
||||||
|
.child(
|
||||||
|
// Render left fixed columns
|
||||||
|
h_flex()
|
||||||
|
.id("table-head-fixed-left")
|
||||||
|
.h_full()
|
||||||
|
.bg(cx.theme().table_head)
|
||||||
|
.border_r_1()
|
||||||
|
.border_color(cx.theme().border)
|
||||||
|
.children(
|
||||||
|
self.col_groups
|
||||||
|
.iter()
|
||||||
|
.filter(|col| col.fixed == Some(ColFixed::Left))
|
||||||
|
.enumerate()
|
||||||
|
.map(|(col_ix, _)| self.render_th(col_ix, cx)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
// Render other normal columns
|
||||||
|
uniform_list(view.clone(), "table-uniform-list-head", 1, {
|
||||||
|
let horizontal_scroll_handle = horizontal_scroll_handle.clone();
|
||||||
|
let view = view.clone();
|
||||||
|
move |table, _, cx| {
|
||||||
|
let view = view.clone();
|
||||||
|
|
||||||
|
// Columns
|
||||||
|
h_flex()
|
||||||
|
.id("table-head")
|
||||||
|
.h_full()
|
||||||
|
.w_full()
|
||||||
|
.overflow_scroll()
|
||||||
|
.relative()
|
||||||
|
.track_scroll(&horizontal_scroll_handle)
|
||||||
|
.bg(cx.theme().table_head)
|
||||||
|
.child(
|
||||||
|
h_flex()
|
||||||
|
.relative()
|
||||||
|
.children(
|
||||||
|
table
|
||||||
|
.col_groups
|
||||||
|
.iter()
|
||||||
|
.filter(|col| col.fixed == None)
|
||||||
|
.enumerate()
|
||||||
|
.map(|(col_ix, _)| {
|
||||||
|
table.render_th(left_cols_count + col_ix, cx)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.child(Self::last_empty_col(cx))
|
||||||
|
.child(
|
||||||
|
canvas(
|
||||||
|
move |bounds, cx| {
|
||||||
|
view.update(cx, |r, _| {
|
||||||
|
r.head_content_bounds = bounds
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|_, _, _| {},
|
||||||
|
)
|
||||||
|
.absolute()
|
||||||
|
.size_full(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.map(|this| vec![this])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.h_full()
|
||||||
|
.flex_1(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_table_row(
|
||||||
|
&mut self,
|
||||||
|
row_ix: usize,
|
||||||
|
rows_count: usize,
|
||||||
|
left_cols_count: usize,
|
||||||
|
cols_count: usize,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) -> impl IntoElement {
|
||||||
|
let horizontal_scroll_handle = self.horizontal_scroll_handle.clone();
|
||||||
|
let is_stripe_row = self.stripe && row_ix % 2 != 0;
|
||||||
|
let is_selected = self.selected_row == Some(row_ix);
|
||||||
|
|
||||||
|
if row_ix < rows_count {
|
||||||
|
self.delegate
|
||||||
|
.render_tr(row_ix, cx)
|
||||||
|
.id(("table-row", row_ix))
|
||||||
|
.w_full()
|
||||||
|
.when(row_ix > 0, |this| {
|
||||||
|
this.border_t_1().border_color(cx.theme().table_row_border)
|
||||||
|
})
|
||||||
|
.when(is_stripe_row, |this| this.bg(cx.theme().table_even))
|
||||||
|
.hover(|this| {
|
||||||
|
if is_selected {
|
||||||
|
this
|
||||||
|
} else {
|
||||||
|
this.bg(cx.theme().table_hover)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.children(if left_cols_count > 0 {
|
||||||
|
// Left fixed columns
|
||||||
|
Some(
|
||||||
|
h_flex()
|
||||||
|
.border_r_1()
|
||||||
|
.border_color(cx.theme().table_row_border)
|
||||||
|
.children((0..left_cols_count).map(|col_ix| {
|
||||||
|
self.col_wrap(col_ix, cx).child(
|
||||||
|
self.render_cell(col_ix, cx)
|
||||||
|
.child(self.delegate.render_td(row_ix, col_ix, cx)),
|
||||||
|
)
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
})
|
||||||
|
.child(
|
||||||
|
h_flex()
|
||||||
|
.flex_1()
|
||||||
|
.overflow_hidden()
|
||||||
|
.children((left_cols_count..cols_count).map(|col_ix| {
|
||||||
|
self
|
||||||
|
// Make the row scroll sync with the
|
||||||
|
// horizontal_scroll_handle to support horizontal scrolling.
|
||||||
|
.col_wrap(col_ix, cx)
|
||||||
|
.left(horizontal_scroll_handle.offset().x)
|
||||||
|
.child(
|
||||||
|
self.render_cell(col_ix, cx)
|
||||||
|
.child(self.delegate.render_td(row_ix, col_ix, cx)),
|
||||||
|
)
|
||||||
|
}))
|
||||||
|
.child(Self::last_empty_col(cx)),
|
||||||
|
)
|
||||||
|
// Row selected style
|
||||||
|
.when_some(self.selected_row, |this, _| {
|
||||||
|
this.when(
|
||||||
|
is_selected && self.selection_state == SelectionState::Row,
|
||||||
|
|this| this.bg(cx.theme().table_active),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.on_mouse_down(
|
||||||
|
MouseButton::Left,
|
||||||
|
cx.listener(move |this, _, cx| {
|
||||||
|
this.on_row_click(row_ix, cx);
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// Render fake rows to fill the rest table space
|
||||||
|
self.delegate
|
||||||
|
.render_tr(row_ix, cx)
|
||||||
|
.id(("table-row-fake", row_ix))
|
||||||
|
.w_full()
|
||||||
|
.h_full()
|
||||||
|
.border_t_1()
|
||||||
|
.border_color(cx.theme().table_row_border)
|
||||||
|
.when(is_stripe_row, |this| this.bg(cx.theme().table_even))
|
||||||
|
.children((0..cols_count).map(|col_ix| {
|
||||||
|
h_flex()
|
||||||
|
.left(horizontal_scroll_handle.offset().x)
|
||||||
|
.child(self.render_cell(col_ix, cx))
|
||||||
|
}))
|
||||||
|
.child(Self::last_empty_col(cx))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.delegate.move_col(col_ix, to_ix);
|
fn last_empty_col(_: &mut WindowContext) -> Div {
|
||||||
let col_group = self.col_groups.remove(col_ix);
|
h_flex().w(px(100.)).h_full().flex_shrink_0()
|
||||||
self.col_groups.insert(to_ix, col_group);
|
|
||||||
|
|
||||||
cx.notify();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -816,13 +1009,11 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn last_empty_col(_: &mut WindowContext) -> Div {
|
let left_cols_count = self
|
||||||
h_flex().w(px(100.)).h_full().flex_shrink_0()
|
.col_groups
|
||||||
}
|
.iter()
|
||||||
|
.filter(|col| col.fixed == Some(ColFixed::Left))
|
||||||
fn tr(_: &mut WindowContext) -> Div {
|
.count();
|
||||||
h_flex()
|
|
||||||
}
|
|
||||||
|
|
||||||
let inner_table = v_flex()
|
let inner_table = v_flex()
|
||||||
.key_context("Table")
|
.key_context("Table")
|
||||||
|
|
@ -835,59 +1026,7 @@ where
|
||||||
.on_action(cx.listener(Self::action_select_prev_col))
|
.on_action(cx.listener(Self::action_select_prev_col))
|
||||||
.size_full()
|
.size_full()
|
||||||
.overflow_hidden()
|
.overflow_hidden()
|
||||||
.child(
|
.child(self.render_table_head(left_cols_count, cx))
|
||||||
v_flex()
|
|
||||||
.flex_grow()
|
|
||||||
.h_10()
|
|
||||||
.w_full()
|
|
||||||
.flex_shrink_0()
|
|
||||||
.border_b_1()
|
|
||||||
.border_color(cx.theme().border)
|
|
||||||
.child(
|
|
||||||
uniform_list(view.clone(), "table-uniform-list-head", 1, {
|
|
||||||
let horizontal_scroll_handle = horizontal_scroll_handle.clone();
|
|
||||||
let view = view.clone();
|
|
||||||
move |table, _, cx| {
|
|
||||||
let view = view.clone();
|
|
||||||
// Columns
|
|
||||||
tr(cx)
|
|
||||||
.id("table-head")
|
|
||||||
.w_full()
|
|
||||||
.h_10()
|
|
||||||
.overflow_scroll()
|
|
||||||
.track_scroll(&horizontal_scroll_handle)
|
|
||||||
.bg(cx.theme().table_head)
|
|
||||||
.child(
|
|
||||||
div()
|
|
||||||
.h_flex()
|
|
||||||
.relative()
|
|
||||||
.children(
|
|
||||||
table
|
|
||||||
.col_groups
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(col_ix, _)| table.render_th(col_ix, cx)),
|
|
||||||
)
|
|
||||||
.child(last_empty_col(cx))
|
|
||||||
.child(
|
|
||||||
canvas(
|
|
||||||
move |bounds, cx| {
|
|
||||||
view.update(cx, |r, _| {
|
|
||||||
r.head_content_bounds = bounds
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|_, _, _| {},
|
|
||||||
)
|
|
||||||
.absolute()
|
|
||||||
.size_full(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.map(|this| vec![this])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.size_full(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.map(|this| {
|
.map(|this| {
|
||||||
if rows_count == 0 {
|
if rows_count == 0 {
|
||||||
this.child(div().size_full().child(self.delegate.render_empty(cx)))
|
this.child(div().size_full().child(self.delegate.render_empty(cx)))
|
||||||
|
|
@ -899,7 +1038,6 @@ where
|
||||||
"table-uniform-list",
|
"table-uniform-list",
|
||||||
rows_count + extra_rows_needed,
|
rows_count + extra_rows_needed,
|
||||||
{
|
{
|
||||||
let horizontal_scroll_handle = horizontal_scroll_handle.clone();
|
|
||||||
move |table, visible_range, cx| {
|
move |table, visible_range, cx| {
|
||||||
table.load_more(visible_range.clone(), cx);
|
table.load_more(visible_range.clone(), cx);
|
||||||
|
|
||||||
|
|
@ -914,100 +1052,13 @@ where
|
||||||
visible_range
|
visible_range
|
||||||
.map(|row_ix| {
|
.map(|row_ix| {
|
||||||
// Render real rows for available data
|
// Render real rows for available data
|
||||||
if row_ix < rows_count {
|
table.render_table_row(
|
||||||
table
|
row_ix,
|
||||||
.delegate
|
rows_count,
|
||||||
.render_tr(row_ix, cx)
|
left_cols_count,
|
||||||
.id(("table-row", row_ix))
|
cols_count,
|
||||||
.w_full()
|
cx,
|
||||||
.when(row_ix > 0, |this| {
|
)
|
||||||
this.border_t_1()
|
|
||||||
.border_color(cx.theme().border)
|
|
||||||
})
|
|
||||||
.when(
|
|
||||||
table.stripe && row_ix % 2 != 0,
|
|
||||||
|this| this.bg(cx.theme().table_even),
|
|
||||||
)
|
|
||||||
.hover(|this| {
|
|
||||||
if table.selected_row == Some(row_ix) {
|
|
||||||
this
|
|
||||||
} else {
|
|
||||||
this.bg(cx.theme().table_hover)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.children((0..cols_count).map(|col_ix| {
|
|
||||||
table
|
|
||||||
// Make the row scroll sync with the
|
|
||||||
// horizontal_scroll_handle to support horizontal scrolling.
|
|
||||||
.col_wrap(col_ix, cx)
|
|
||||||
.left(
|
|
||||||
horizontal_scroll_handle
|
|
||||||
.offset()
|
|
||||||
.x,
|
|
||||||
)
|
|
||||||
.child(
|
|
||||||
table
|
|
||||||
.render_cell(col_ix, cx)
|
|
||||||
.child(
|
|
||||||
table
|
|
||||||
.delegate
|
|
||||||
.render_td(
|
|
||||||
row_ix, col_ix,
|
|
||||||
cx,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}))
|
|
||||||
.child(last_empty_col(cx))
|
|
||||||
// Row selected style
|
|
||||||
.when_some(
|
|
||||||
table.selected_row,
|
|
||||||
|this, selected_row| {
|
|
||||||
this.when(
|
|
||||||
row_ix == selected_row
|
|
||||||
&& table.selection_state
|
|
||||||
== SelectionState::Row,
|
|
||||||
|this| {
|
|
||||||
this.bg(cx
|
|
||||||
.theme()
|
|
||||||
.table_active)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.on_mouse_down(
|
|
||||||
MouseButton::Left,
|
|
||||||
cx.listener(move |this, _, cx| {
|
|
||||||
this.on_row_click(row_ix, cx);
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
// Render fake rows to fill the rest table space
|
|
||||||
table
|
|
||||||
.delegate
|
|
||||||
.render_tr(row_ix, cx)
|
|
||||||
.id(("table-row-fake", row_ix))
|
|
||||||
.w_full()
|
|
||||||
.h_full()
|
|
||||||
.border_t_1()
|
|
||||||
.border_color(cx.theme().border)
|
|
||||||
.when(
|
|
||||||
table.stripe && row_ix % 2 != 0,
|
|
||||||
|this| this.bg(cx.theme().table_even),
|
|
||||||
)
|
|
||||||
.children((0..cols_count).map(|col_ix| {
|
|
||||||
h_flex()
|
|
||||||
.left(
|
|
||||||
horizontal_scroll_handle
|
|
||||||
.offset()
|
|
||||||
.x,
|
|
||||||
)
|
|
||||||
.child(
|
|
||||||
table.render_cell(col_ix, cx),
|
|
||||||
)
|
|
||||||
}))
|
|
||||||
.child(last_empty_col(cx))
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -315,6 +315,7 @@ pub struct Theme {
|
||||||
pub table: Hsla,
|
pub table: Hsla,
|
||||||
pub table_even: Hsla,
|
pub table_even: Hsla,
|
||||||
pub table_head: Hsla,
|
pub table_head: Hsla,
|
||||||
|
pub table_row_border: Hsla,
|
||||||
pub table_active: Hsla,
|
pub table_active: Hsla,
|
||||||
pub table_hover: Hsla,
|
pub table_hover: Hsla,
|
||||||
pub link: Hsla,
|
pub link: Hsla,
|
||||||
|
|
@ -396,6 +397,7 @@ impl From<Colors> for Theme {
|
||||||
table_even: colors.list_even,
|
table_even: colors.list_even,
|
||||||
table_active: colors.list_active,
|
table_active: colors.list_active,
|
||||||
table_hover: colors.list_active.opacity(0.8),
|
table_hover: colors.list_active.opacity(0.8),
|
||||||
|
table_row_border: colors.border.opacity(0.5),
|
||||||
link: colors.link,
|
link: colors.link,
|
||||||
link_hover: colors.link.lighten(0.2),
|
link_hover: colors.link.lighten(0.2),
|
||||||
link_active: colors.link.darken(0.2),
|
link_active: colors.link.darken(0.2),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue