* [PATCH yew-widget-toolkit v4 0/2] data table: auto width
@ 2026-10-15 12:38 Dominik Csapak
2026-10-15 12:38 ` [PATCH yew-widget-toolkit v4 1/2] widget: data table: factor out cell rendering logic Dominik Csapak
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Dominik Csapak @ 2026-10-15 12:38 UTC (permalink / raw)
To: yew-devel
replaces the previous single patch[0]. It needs an upfront refactor so
there is an additional patch now.
changes from v3:
* new patch: factor out the cell rendering loop of the table rows, so
it can be reused for the sample records (for colspan)
* cache the rendered sizers and only recalculate them when the relevant
properties change, instead of on every render
* move the debug assertion into the sizer calculation, so it also
covers property updates, and fix it to allow exactly
VIRTUAL_SCROLL_TRIGGER records
* fix typos
* improve comments
Dominik Csapak (2):
widget: data table: factor out cell rendering logic
widget: data table: implement auto column sizing based on sample
records
src/widget/data_table/data_table.rs | 117 +++++++++++++++++++++++--
src/widget/data_table/header_widget.rs | 46 ++++++++++
src/widget/data_table/mod.rs | 5 +-
src/widget/data_table/rendered_cell.rs | 63 +++++++++++++
src/widget/data_table/row.rs | 66 +++++---------
5 files changed, 247 insertions(+), 50 deletions(-)
create mode 100644 src/widget/data_table/rendered_cell.rs
--
2.47.3
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH yew-widget-toolkit v4 1/2] widget: data table: factor out cell rendering logic
2026-10-15 12:38 [PATCH yew-widget-toolkit v4 0/2] data table: auto width Dominik Csapak
@ 2026-10-15 12:38 ` Dominik Csapak
2026-10-15 12:38 ` [PATCH yew-widget-toolkit v4 2/2] widget: data table: implement auto column sizing based on sample records Dominik Csapak
2026-10-16 7:42 ` [PATCH yew-widget-toolkit v4 0/2] data table: auto width Dietmar Maurer
2 siblings, 0 replies; 4+ messages in thread
From: Dominik Csapak @ 2026-10-15 12:38 UTC (permalink / raw)
To: yew-devel
Move the loop that renders the visible cells of a row, including the
colspan handling, into a separate function, so that it can be reused for
rendering invisible sample rows to size the columns.
No functional change intended.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
src/widget/data_table/mod.rs | 3 ++
src/widget/data_table/rendered_cell.rs | 59 +++++++++++++++++++++++
src/widget/data_table/row.rs | 66 +++++++++-----------------
3 files changed, 84 insertions(+), 44 deletions(-)
create mode 100644 src/widget/data_table/rendered_cell.rs
diff --git a/src/widget/data_table/mod.rs b/src/widget/data_table/mod.rs
index 2ab03b6..ba0d0ff 100644
--- a/src/widget/data_table/mod.rs
+++ b/src/widget/data_table/mod.rs
@@ -29,6 +29,9 @@ pub use cell_configuration::CellConfiguration;
mod cell_render_callback;
pub use cell_render_callback::{DataTableCellRenderArgs, DataTableCellRenderer};
+mod rendered_cell;
+pub(crate) use rendered_cell::render_row_cells;
+
mod header_render_callback;
pub use header_render_callback::{
DataTableHeaderRenderArgs, DataTableHeaderRenderer, DataTableHeaderTableLink,
diff --git a/src/widget/data_table/rendered_cell.rs b/src/widget/data_table/rendered_cell.rs
new file mode 100644
index 0000000..42ab8e6
--- /dev/null
+++ b/src/widget/data_table/rendered_cell.rs
@@ -0,0 +1,59 @@
+use yew::Html;
+
+use crate::widget::data_table::{CellConfiguration, DataTableCellRenderArgs, DataTableColumn};
+
+/// Contains the rendered cell contents plus meta info to properly show it in the data table
+pub(crate) struct RenderedCell<'a, T: 'static> {
+ pub column_num: usize,
+ pub config: CellConfiguration,
+ pub content: Html,
+ pub column: &'a DataTableColumn<T>,
+}
+
+/// Calculates the necessary index and colspan properties and renders the cell for a row.
+pub(crate) fn render_row_cells<'a, T>(
+ columns: &'a [DataTableColumn<T>],
+ columns_hidden: &[bool],
+ mut make_args: impl FnMut(usize) -> DataTableCellRenderArgs<'a, T>,
+) -> Vec<RenderedCell<'a, T>> {
+ let mut res = Vec::with_capacity(columns.len());
+
+ let mut col_index = 0;
+ let mut column_num = 0;
+
+ while let Some(column) = columns.get(column_num) {
+ if let Some(true) = columns_hidden.get(column_num) {
+ column_num += 1;
+ continue;
+ }
+
+ let mut args = make_args(col_index);
+
+ let content = column.apply_render(&mut args);
+
+ let mut colspan = 1;
+
+ for (attr_name, attr_value) in args.config.attributes.iter() {
+ if attr_name != "colspan" {
+ continue;
+ }
+
+ match attr_value.parse::<usize>() {
+ Ok(n) if n > 0 => colspan = n,
+ _ => {}
+ }
+ }
+
+ res.push(RenderedCell {
+ column_num,
+ config: args.config,
+ content,
+ column,
+ });
+
+ col_index += colspan;
+ column_num += colspan;
+ }
+
+ res
+}
diff --git a/src/widget/data_table/row.rs b/src/widget/data_table/row.rs
index 34bbbdf..9ce1f4d 100644
--- a/src/widget/data_table/row.rs
+++ b/src/widget/data_table/row.rs
@@ -13,7 +13,7 @@ use crate::widget::Container;
use super::{
CellConfiguration, DataTableCellRenderArgs, DataTableColumn, DataTableRowRenderArgs,
- DataTableRowRenderCallback,
+ DataTableRowRenderCallback, render_row_cells,
};
/// DataTable row properties.
@@ -119,15 +119,23 @@ impl<T: Clone + PartialEq + 'static> Component for PwtDataTableRow<T> {
let minheight_cell_style =
AttrValue::Rc(format!("vertical-align:top;height: {}px;", props.min_row_height).into());
- let mut col_index = 0;
- let mut column_num = 0;
-
- while let Some(column) = props.columns.get(column_num) {
- if let Some(true) = props.column_hidden.get(column_num) {
- column_num += 1;
- continue;
+ let rendered_cells = render_row_cells(&props.columns, &props.column_hidden, |col_index| {
+ DataTableCellRenderArgs {
+ selection: props.selection.clone(),
+ record: &props.record,
+ record_key: &props.record_key,
+ row_index: props.row_num,
+ column_index: col_index,
+ selected: props.selected,
+ config: (*props.cell_config).clone(),
+ is_expanded: props.is_expanded,
+ is_leaf: props.is_leaf,
+ level: props.level,
}
+ });
+ for cell in rendered_cells {
+ let column = cell.column;
let vertical_align = props
.vertical_align
.to_owned()
@@ -136,52 +144,22 @@ impl<T: Clone + PartialEq + 'static> Component for PwtDataTableRow<T> {
let text_align = column.justify.to_owned();
let cell_active = match props.active_cell {
- Some(active_cell) => active_cell == column_num,
+ Some(active_cell) => active_cell == cell.column_num,
None => false,
};
- let mut args = DataTableCellRenderArgs {
- selection: props.selection.clone(),
- record: &props.record,
- record_key: &props.record_key,
- row_index: props.row_num,
- column_index: col_index,
- selected: props.selected,
- config: (*props.cell_config).clone(),
- is_expanded: props.is_expanded,
- is_leaf: props.is_leaf,
- level: props.level,
- };
-
- let cell = column.apply_render(&mut args);
-
let mut td = Container::from_tag("td")
- .class(args.config.class)
+ .class(cell.config.class)
.class((cell_active && props.has_focus).then_some("cell-cursor"))
- .styles(args.config.style)
+ .styles(cell.config.style)
.style("vertical-align", vertical_align)
.style("text-align", text_align)
.attribute("role", "gridcell")
- .attribute("data-column-num", column_num.to_string())
+ .attribute("data-column-num", cell.column_num.to_string())
.attribute("tabindex", if cell_active { "0" } else { "-1" })
- .with_child(html! {<div role="none">{cell}</div>});
-
- let mut colspan = 1;
-
- for (attr_name, attr_value) in args.config.attributes.iter() {
- if attr_name == "colspan" {
- if let Ok(n) = attr_value.parse::<usize>() {
- if n > 0 {
- colspan = n
- }
- }
- }
- }
-
- td.as_std_props_mut().add_attributes(args.config.attributes);
+ .with_child(html! {<div role="none">{cell.content}</div>});
- col_index += colspan;
- column_num += colspan;
+ td.as_std_props_mut().add_attributes(cell.config.attributes);
row.add_child(td);
}
--
2.47.3
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH yew-widget-toolkit v4 2/2] widget: data table: implement auto column sizing based on sample records
2026-10-15 12:38 [PATCH yew-widget-toolkit v4 0/2] data table: auto width Dominik Csapak
2026-10-15 12:38 ` [PATCH yew-widget-toolkit v4 1/2] widget: data table: factor out cell rendering logic Dominik Csapak
@ 2026-10-15 12:38 ` Dominik Csapak
2026-10-16 7:42 ` [PATCH yew-widget-toolkit v4 0/2] data table: auto width Dietmar Maurer
2 siblings, 0 replies; 4+ messages in thread
From: Dominik Csapak @ 2026-10-15 12:38 UTC (permalink / raw)
To: yew-devel
When a column size is not explicitly given (like "100px" or "15em"), the
default size is implicitly determined by the header text. In cases where
the content should always be shown (like in an action column) and
depends on the theme/density (for padding/width/etc.) this leads to a
bad tradeoff:
Either a fixed size is used and it's sometimes too wide or too narrow,
or some css expression is used that dynamically determines the size.
Both are not ideal, so introduce 'sample records' that the data table
can use to (invisibly) render a set of dummy rows which can dynamically
determine the correct size. Use the same logic as the table rows for
rendering them.
This can be used for e.g. setting an example that should always fit, or
having a fixed set of ActionIcons, etc.
When multiple records are given, the largest one for each column wins.
Since too many rendered records can impact the performance, limit the
considered records and assert the number in debug mode. Reuse
VIRTUAL_SCROLL_TRIGGER as the limit, since that is also the cut-off for
the visible rows.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
src/widget/data_table/data_table.rs | 117 +++++++++++++++++++++++--
| 46 ++++++++++
src/widget/data_table/mod.rs | 2 +-
src/widget/data_table/rendered_cell.rs | 4 +
4 files changed, 163 insertions(+), 6 deletions(-)
diff --git a/src/widget/data_table/data_table.rs b/src/widget/data_table/data_table.rs
index 9407844..6ad4068 100644
--- a/src/widget/data_table/data_table.rs
+++ b/src/widget/data_table/data_table.rs
@@ -21,10 +21,13 @@ use crate::props::{
use crate::state::{DataStore, Selection, SelectionObserver};
use crate::widget::{Column, Container, get_unique_element_id};
+use pwt_macros::builder;
+
use super::{
- CellConfiguration, DataTableColumn, DataTableHeader, DataTableKeyboardEvent,
- DataTableMouseEvent, DataTableRow, DataTableRowRenderCallback, HeaderWidget, IndexedHeader,
- IntoOptionalDataTableRowRenderCallback, create_indexed_header_list,
+ CellConfiguration, DataTableCellRenderArgs, DataTableColumn, DataTableHeader,
+ DataTableKeyboardEvent, DataTableMouseEvent, DataTableRow, DataTableRowRenderCallback,
+ HeaderWidget, IndexedHeader, IntoOptionalDataTableRowRenderCallback,
+ create_indexed_header_list, render_row_cells,
};
pub enum HeaderMsg<T: 'static> {
@@ -109,6 +112,7 @@ pub enum MultiSelectMode {
/// * `End`: moves focus to the last cell in the row that contains focus.
#[derive(Properties, Derivative)]
#[derivative(Clone(bound = ""), PartialEq(bound = ""))]
+#[builder]
pub struct DataTable<S: DataStore> {
/// Yew key property.
#[prop_or_default]
@@ -173,6 +177,24 @@ pub struct DataTable<S: DataStore> {
#[prop_or(22)]
pub min_row_height: usize,
+ /// Sample records used for sizing the columns.
+ ///
+ /// Default column widths are computed from the header, because the table rows are rendered
+ /// separately (and only partially with virtual scrolling). These records are rendered
+ /// invisibly inside the header, using the column render functions, so content based widths
+ /// like "auto" or "max-content" account for them. For flex widths, they act as minimum width.
+ ///
+ /// To make it easier to handle with enum records (often used by trees), this is a list, so
+ /// multiple variants can be used simultaneously.
+ ///
+ /// The records are rendered with `level: 0` and not expanded, so tree indentation is
+ /// not considered.
+ ///
+ /// NOTE: Only up to [`VIRTUAL_SCROLL_TRIGGER`] records are supported for performance reasons.
+ #[prop_or_default]
+ #[builder]
+ pub sample_records: Vec<S::Record>,
+
/// Selection object.
#[prop_or_default]
pub selection: Option<Selection>,
@@ -240,7 +262,9 @@ impl<S: DataStore> CssPaddingBuilder for DataTable<S> {}
impl<S: DataStore> CssMarginBuilder for DataTable<S> {}
impl<S: DataStore> WidgetStyleBuilder for DataTable<S> {}
-static VIRTUAL_SCROLL_TRIGGER: usize = 30;
+/// The automatic cut-off for virtual scrolling. When the DataTable can be scrolled
+/// and there are more rows than this limit, virtual scrolling is automatically enabled.
+pub const VIRTUAL_SCROLL_TRIGGER: usize = 30;
impl<S: DataStore> DataTable<S> {
/// Create a new instance.
@@ -536,6 +560,9 @@ pub struct PwtDataTable<S: DataStore> {
keypress_timeout: Option<Timeout>,
focus_table: bool,
+
+ /// Cached column sizers so recalculation does not happen too frequently.
+ column_sizers: Vec<(usize, usize, Html)>,
}
/// Whether the header has measured the columns. A hidden header measures them as 0.
@@ -1059,6 +1086,69 @@ impl<S: DataStore> PwtDataTable<S> {
};
}
+ // Calculate and render the cells of the sizing records with the column renderers, wrapped like
+ // table cells, so that they get the same font and padding when the header measures them.
+ fn calculate_column_sizers(&mut self, props: &DataTable<S>) {
+ if props.sample_records.is_empty() {
+ self.column_sizers = Vec::new();
+ return;
+ }
+
+ debug_assert!(
+ props.sample_records.len() <= VIRTUAL_SCROLL_TRIGGER,
+ "More than {VIRTUAL_SCROLL_TRIGGER} sample records can have a negative performance \
+ impact. Anything more than that will not be rendered."
+ );
+
+ let records: Vec<(Key, &S::Record)> = props
+ .sample_records
+ .iter()
+ .take(VIRTUAL_SCROLL_TRIGGER)
+ .map(|record| (props.store.extract_key(record), record))
+ .collect();
+
+ let mut res = Vec::with_capacity(records.len() * self.columns.len());
+
+ for (row_index, (record_key, record)) in records.into_iter().enumerate() {
+ let rendered_cells =
+ render_row_cells(&self.columns, &self.column_hidden, |column_index| {
+ DataTableCellRenderArgs {
+ selection: props.selection.clone(),
+ record,
+ record_key: &record_key,
+ row_index,
+ column_index,
+ selected: false,
+ config: (*self.cell_config).clone(),
+ is_expanded: false,
+ is_leaf: true,
+ level: 0,
+ }
+ });
+
+ for cell in rendered_cells {
+ res.push((
+ cell.col_index,
+ cell.colspan,
+ Container::new()
+ .class(cell.config.class)
+ .styles(cell.config.style)
+ .style("white-space", "nowrap")
+ // cell widths get reduced by the border width, see
+ // render_empty_row_with_sizes
+ .style(
+ "border-inline-end",
+ props.bordered.then_some("1px solid transparent"),
+ )
+ .with_child(html! {<div role="none">{cell.content}</div>})
+ .into(),
+ ));
+ }
+ }
+
+ self.column_sizers = res;
+ }
+
fn init_headers(&mut self, props: &DataTable<S>) {
let headers = create_indexed_header_list(&props.headers);
@@ -1136,12 +1226,16 @@ impl<S: DataStore + 'static> Component for PwtDataTable<S> {
keypress_timeout: None,
focus_table: false,
+ column_sizers: Vec::new(),
};
me.init_headers(props);
me.update_scroll_info(props);
// fixme: remove unknown keys from selection
me.update_selection_status(props);
+
+ me.calculate_column_sizers(props);
+
me
}
@@ -1653,6 +1747,7 @@ impl<S: DataStore + 'static> Component for PwtDataTable<S> {
}
Msg::Header(HeaderMsg::ColumnHiddenChange(column_hidden)) => {
self.column_hidden = Rc::new(column_hidden);
+ self.calculate_column_sizers(props);
true
}
Msg::Header(HeaderMsg::ToggleSelectAll) => {
@@ -1794,7 +1889,8 @@ impl<S: DataStore + 'static> Component for PwtDataTable<S> {
.focusable(props.header_focusable && props.show_header)
.selection_status(self.selection_status)
.header_class(header_class)
- .reserve_scroll_space(self.scrollbar_size.unwrap_or_default()),
+ .reserve_scroll_space(self.scrollbar_size.unwrap_or_default())
+ .column_sizers(self.column_sizers.clone()),
)
.into_html_with_ref(self.header_scroll_ref.clone()),
)
@@ -1810,8 +1906,19 @@ impl<S: DataStore + 'static> Component for PwtDataTable<S> {
self.update_scroll_info(props);
}
+ let mut recalculate_sizers = false;
if props.headers != old_props.headers {
self.init_headers(props);
+ recalculate_sizers = true;
+ }
+
+ if props.sample_records != old_props.sample_records || props.bordered != old_props.bordered
+ {
+ recalculate_sizers = true;
+ }
+
+ if recalculate_sizers {
+ self.calculate_column_sizers(props);
}
true
--git a/src/widget/data_table/header_widget.rs b/src/widget/data_table/header_widget.rs
index b6f06f6..268b66c 100644
--- a/src/widget/data_table/header_widget.rs
+++ b/src/widget/data_table/header_widget.rs
@@ -43,6 +43,11 @@ pub struct HeaderWidget<T: 'static> {
pub focusable: bool,
reserve_scroll_space: f64,
+
+ /// Invisible content per visible column, used to size the column tracks. Contains
+ /// the visible column index, the `colspan` value and the content.
+ #[prop_or_default]
+ pub column_sizers: Vec<(usize, usize, Html)>,
}
impl<T: 'static> HeaderWidget<T> {
@@ -95,6 +100,17 @@ impl<T: 'static> HeaderWidget<T> {
pub fn set_reserve_scroll_space(&mut self, reserve_scroll_space: f64) {
self.reserve_scroll_space = reserve_scroll_space;
}
+
+ /// Builder style method to set the column sizers.
+ pub fn column_sizers(mut self, column_sizers: Vec<(usize, usize, Html)>) -> Self {
+ self.set_column_sizers(column_sizers);
+ self
+ }
+
+ /// Method to set the column sizers.
+ pub fn set_column_sizers(&mut self, column_sizers: Vec<(usize, usize, Html)>) {
+ self.column_sizers = column_sizers;
+ }
}
pub enum Msg {
@@ -635,6 +651,36 @@ impl<T: 'static> Component for PwtHeaderWidget<T> {
let column_count = self.state.visible_column_count();
+ // Put the sizers into their column tracks, so that content based track sizes account for
+ // them. They have no height and are invisible, so they do not change the header layout.
+ // Header cells end at row line 10, so use the row after that to avoid interfering with
+ // the auto placed group headers.
+ for (i, (grid_start, colspan, sizer)) in props.column_sizers.iter().enumerate() {
+ if *grid_start >= column_count {
+ continue;
+ }
+ let cols_left = column_count - grid_start;
+ let colspan = (*colspan).min(cols_left);
+
+ header_row.push(
+ Container::new()
+ .key(Key::from(format!("sizer-{i}")))
+ .class("pwt-datatable-content")
+ .attribute("role", "none")
+ .attribute("aria-hidden", "true")
+ .style("height", "0px")
+ .style("overflow", "clip")
+ .style("visibility", "hidden")
+ .style("grid-row", "10")
+ .style(
+ "grid-column",
+ format!("{} / span {}", grid_start + 1, colspan),
+ )
+ .with_child(sizer.clone())
+ .into(),
+ );
+ }
+
// add some space at the end to make room for the tables vertical scrollbar
let scrollbar_size = ctx.props().reserve_scroll_space;
if scrollbar_size > 0.0 {
diff --git a/src/widget/data_table/mod.rs b/src/widget/data_table/mod.rs
index ba0d0ff..9cf719e 100644
--- a/src/widget/data_table/mod.rs
+++ b/src/widget/data_table/mod.rs
@@ -48,7 +48,7 @@ mod data_table;
pub(crate) use data_table::HeaderMsg;
#[doc(hidden)]
pub use data_table::PwtDataTable;
-pub use data_table::{DataTable, MultiSelectMode, RowSelectionStatus};
+pub use data_table::{DataTable, MultiSelectMode, RowSelectionStatus, VIRTUAL_SCROLL_TRIGGER};
use yew::prelude::*;
diff --git a/src/widget/data_table/rendered_cell.rs b/src/widget/data_table/rendered_cell.rs
index 42ab8e6..77422b1 100644
--- a/src/widget/data_table/rendered_cell.rs
+++ b/src/widget/data_table/rendered_cell.rs
@@ -5,6 +5,8 @@ use crate::widget::data_table::{CellConfiguration, DataTableCellRenderArgs, Data
/// Contains the rendered cell contents plus meta info to properly show it in the data table
pub(crate) struct RenderedCell<'a, T: 'static> {
pub column_num: usize,
+ pub col_index: usize,
+ pub colspan: usize,
pub config: CellConfiguration,
pub content: Html,
pub column: &'a DataTableColumn<T>,
@@ -46,6 +48,8 @@ pub(crate) fn render_row_cells<'a, T>(
res.push(RenderedCell {
column_num,
+ col_index,
+ colspan,
config: args.config,
content,
column,
--
2.47.3
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH yew-widget-toolkit v4 0/2] data table: auto width
2026-10-15 12:38 [PATCH yew-widget-toolkit v4 0/2] data table: auto width Dominik Csapak
2026-10-15 12:38 ` [PATCH yew-widget-toolkit v4 1/2] widget: data table: factor out cell rendering logic Dominik Csapak
2026-10-15 12:38 ` [PATCH yew-widget-toolkit v4 2/2] widget: data table: implement auto column sizing based on sample records Dominik Csapak
@ 2026-10-16 7:42 ` Dietmar Maurer
2 siblings, 0 replies; 4+ messages in thread
From: Dietmar Maurer @ 2026-10-16 7:42 UTC (permalink / raw)
To: Dominik Csapak; +Cc: yew-devel
[-- Attachment #1: Type: text/plain, Size: 1724 bytes --]
As discussed offline, passing a store insteadfof records would
solve the tree rendering problem too. We just need some
IntoPrototypeStore trait to make this more usable (accept
single record, multiple records or a store)
On Thursday, 10/15/2026, 14:38, Dominik Csapak <d.csapak@proxmox.com> wrote:
>From : Dominik Csapak <d.csapak@proxmox.com>
Sent on : Thursday, 10/15/2026, 14:38
To : yew-devel@lists.proxmox.com
Subject : [PATCH yew-widget-toolkit v4 0/2] data table: auto width
replaces the previous single patch[0]. It needs an upfront refactor so
there is an additional patch now.
changes from v3:
* new patch: factor out the cell rendering loop of the table rows, so
it can be reused for the sample records (for colspan)
* cache the rendered sizers and only recalculate them when the relevant
properties change, instead of on every render
* move the debug assertion into the sizer calculation, so it also
covers property updates, and fix it to allow exactly
VIRTUAL_SCROLL_TRIGGER records
* fix typos
* improve comments
Dominik Csapak (2):
widget: data table: factor out cell rendering logic
widget: data table: implement auto column sizing based on sample
records
src/widget/data_table/data_table.rs | 117 +++++++++++++++++++++++--
src/widget/data_table/header_widget.rs | 46 ++++++++++
src/widget/data_table/mod.rs [http://mod.rs/] | 5 +-
src/widget/data_table/rendered_cell.rs | 63 +++++++++++++
src/widget/data_table/row.rs [http://row.rs/] | 66 +++++---------
5 files changed, 247 insertions(+), 50 deletions(-)
create mode 100644 src/widget/data_table/rendered_cell.rs
--
2.47.3
[-- Attachment #2: Type: text/html, Size: 3043 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-16 7:42 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-15 12:38 [PATCH yew-widget-toolkit v4 0/2] data table: auto width Dominik Csapak
2026-10-15 12:38 ` [PATCH yew-widget-toolkit v4 1/2] widget: data table: factor out cell rendering logic Dominik Csapak
2026-10-15 12:38 ` [PATCH yew-widget-toolkit v4 2/2] widget: data table: implement auto column sizing based on sample records Dominik Csapak
2026-10-16 7:42 ` [PATCH yew-widget-toolkit v4 0/2] data table: auto width Dietmar Maurer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox