Cell Buttons

Overview

Cell buttons are clickable canvas-drawn elements rendered at the right side of a cell. They are defined at the column level — the same buttons appear in every row of the column. A click fires a callback with the row index, column key, and button identifier.

use rs_grid_core::column::{ButtonDef, ButtonStyle, ColumnDef};

let mut col = ColumnDef::new("actions", "Actions", 160.0);
col.cell_buttons = vec![
    ButtonDef::new("edit",   "Edit",   ButtonStyle::Primary),
    ButtonDef::new("delete", "Delete", ButtonStyle::Danger),
];

ButtonDef

pub struct ButtonDef {
    /// Stable identifier passed to the click callback.
    /// Must be unique within a column.
    pub id: String,
    /// Label rendered on the button face.
    pub label: String,
    /// Visual style variant.
    pub style: ButtonStyle,
}

Use ButtonDef::new(id, label, style) to construct one:

ButtonDef::new("approve", "Approve", ButtonStyle::Primary)

ButtonStyle

VariantAppearance
PrimarySolid blue fill, white text
SecondaryMuted grey fill, dark text
DangerSolid red fill, white text
GhostTransparent fill, coloured border and text
pub enum ButtonStyle {
    Primary,
    Secondary,
    Danger,
    Ghost,
}

Layout

Buttons are laid out right-to-left: the first entry in cell_buttons is the rightmost button. This keeps positions stable when additional buttons are added later.

The button width is estimated from the label length — no Canvas2D measurement is performed at the scene layer. A column width of at least (label_chars × font_size × 0.65 + padding_x × 2) × button_count + gaps + margin is recommended.

Builder method

let col = ColumnDef::new("actions", "Actions", 160.0)
    .with_cell_buttons(vec![
        ButtonDef::new("edit",   "Edit",   ButtonStyle::Primary),
        ButtonDef::new("delete", "Delete", ButtonStyle::Danger),
    ]);

Click callback

Web layer (WebGridCanvas)

gc.set_on_cell_button_click(|row, col_key, button_id| {
    web_sys::console::log_1(
        &format!("row={row} col={col_key} btn={button_id}").into(),
    );
});

Leptos component

use rs_grid_leptos::{CellButtonClickCb, GridCanvas};

let on_click: CellButtonClickCb = Box::new(|row, col, btn| {
    match btn.as_str() {
        "edit"   => { /* open edit modal */ }
        "delete" => { /* confirm delete */ }
        _ => {}
    }
});

view! {
    <GridCanvas
        model=model
        on_cell_button_click=on_click
    />
}

The callback signature is (row: u64, col_key: String, button_id: String).

Combining with cell content

Buttons are rendered on top of the cell's text content. To avoid overlap, either widen the column or suppress text rendering by using an empty CellFormat::Boolean:

// Show buttons only — no text in the cell
col.format = Some(CellFormat::Boolean {
    true_label:  String::new(),
    false_label: String::new(),
});
col.cell_buttons = vec![
    ButtonDef::new("view", "View", ButtonStyle::Ghost),
];

Theme variables

All button colours and geometry are configurable via CSS custom properties:

CSS variableTheme fieldDefault (light)
--rs-grid-cell-btn-primary-bgcell_btn_primary_bg#2196f3
--rs-grid-cell-btn-primary-textcell_btn_primary_text#ffffff
--rs-grid-cell-btn-secondary-bgcell_btn_secondary_bg#e2e8f0
--rs-grid-cell-btn-secondary-textcell_btn_secondary_text#181d1f
--rs-grid-cell-btn-danger-bgcell_btn_danger_bg#ef4444
--rs-grid-cell-btn-danger-textcell_btn_danger_text#ffffff
--rs-grid-cell-btn-ghost-colorcell_btn_ghost_colorrgba(33,150,243,0.78)
--rs-grid-cell-btn-radiuscell_btn_radius4px
--rs-grid-cell-btn-padding-ycell_btn_padding_y4px
--rs-grid-cell-btn-padding-xcell_btn_padding_x8px
--rs-grid-cell-btn-gapcell_btn_gap4px
--rs-grid-cell-btn-margin-rcell_btn_margin_r8px

Interaction notes

  • A button click does not select the cell — the event is consumed before cell selection logic runs.
  • Buttons are hit-tested against the last rendered frame's ButtonZone list, so they are always in sync with the visible layout.
  • Hover styling is not yet implemented; it is planned for a future release.