# Rows > Row height, markers, selection, freezing, and trailing rows. --- .. llms_copy::references/rows .. toc:: ### Overview Rows contain your data and can be customized for height, selection behavior, markers, and more. ### Basic Usage Define your data rows with the default `rowHeight` of 34 pixels. .. exec::examples.reference.rows.basic :code: false ```python # File: examples/reference/rows/basic.py import dash_glide_grid as dgg columns = [ {"title": "Name", "id": "name", "width": 150}, {"title": "Email", "id": "email", "width": 220}, {"title": "Role", "id": "role", "width": 120}, {"title": "Status", "id": "status", "width": 100}, ] data = [ {"name": "Alice Johnson", "email": "alice@example.com", "role": "Engineer", "status": "Active"}, {"name": "Bob Smith", "email": "bob@example.com", "role": "Designer", "status": "Active"}, {"name": "Carol White", "email": "carol@example.com", "role": "Manager", "status": "Away"}, {"name": "David Brown", "email": "david@example.com", "role": "Engineer", "status": "Inactive"}, ] component = dgg.GlideGrid( id={"type": "glide-grid", "index": "rows-basic"}, columns=columns, data=data, height=200, rowHeight=34, ) ``` :defaultExpanded: true :withExpandedButton: true ### Row Height Adjust `rowHeight` to control the vertical sizing of your data rows. Row height can also be a function for dynamic heights per row. .. exec::examples.reference.rows.height :code: false ```python # File: examples/reference/rows/height.py from dash import Input, Output, callback import dash_glide_grid as dgg import dash_mantine_components as dmc columns = [ {"title": "Name", "id": "name", "width": 150}, {"title": "Department", "id": "dept", "width": 120}, {"title": "Salary", "id": "salary", "width": 100}, {"title": "Status", "id": "status", "width": 100}, ] data = [ {"name": "Alice Johnson", "dept": "Engineering", "salary": 95000, "status": "Active"}, {"name": "Bob Smith", "dept": "Marketing", "salary": 72000, "status": "Active"}, {"name": "Carol White", "dept": "Engineering", "salary": 88000, "status": "Away"}, {"name": "David Brown", "dept": "Sales", "salary": 65000, "status": "Inactive"}, {"name": "Eve Davis", "dept": "HR", "salary": 70000, "status": "Active"}, ] component = dmc.Stack( [ dmc.NumberInput( id="row-height-val", label="Row Height (px)", value=34, min=24, max=80, w=140, ), dgg.GlideGrid( id={"type": "glide-grid", "index": "rows-height"}, columns=columns, data=data, height=260, rowHeight=34, rowMarkers="number", ), ] ) @callback( Output({"type": "glide-grid", "index": "rows-height"}, "rowHeight"), Input("row-height-val", "value"), ) def update_row_height(value): return value or 34 ``` :defaultExpanded: false :withExpandedButton: true ### Row Markers Row markers appear on the left side of the grid and can show row numbers, checkboxes, or both. Configure the appearance with `rowMarkerStartIndex` and `rowMarkerWidth`. .. exec::examples.reference.rows.markers :code: false ```python # File: examples/reference/rows/markers.py from dash import Input, Output, callback import dash_glide_grid as dgg import dash_mantine_components as dmc columns = [ {"title": "Name", "id": "name", "width": 150}, {"title": "Department", "id": "dept", "width": 120}, {"title": "Salary", "id": "salary", "width": 100}, {"title": "Start Date", "id": "start", "width": 120}, ] data = [ {"name": "Alice Johnson", "dept": "Engineering", "salary": 95000, "start": "2022-01-15"}, {"name": "Bob Smith", "dept": "Marketing", "salary": 72000, "start": "2021-06-01"}, {"name": "Carol White", "dept": "Engineering", "salary": 88000, "start": "2023-03-10"}, {"name": "David Brown", "dept": "Sales", "salary": 65000, "start": "2022-09-20"}, ] component = dmc.Stack( [ dmc.Group( [ dmc.Select( id="row-marker-type", label="Row Marker Type", data=[ {"value": "none", "label": "None"}, {"value": "number", "label": "Number"}, {"value": "checkbox", "label": "Checkbox"}, {"value": "both", "label": "Both"}, {"value": "checkbox-visible", "label": "Checkbox (Visible)"}, {"value": "clickable-number", "label": "Clickable Number"}, ], value="both", w=180, ), dmc.NumberInput( id="row-marker-start", label="Start Index", value=1, min=0, max=100, w=100, ), dmc.NumberInput( id="row-marker-width", label="Marker Width", value=50, min=30, max=100, w=120, ), ] ), dgg.GlideGrid( id={"type": "glide-grid", "index": "rows-markers"}, columns=columns, data=data, height=200, rowMarkers="both", rowMarkerStartIndex=1, rowMarkerWidth=50, rowSelect="multi", ), ] ) @callback( Output({"type": "glide-grid", "index": "rows-markers"}, "rowMarkers"), Input("row-marker-type", "value"), ) def update_row_markers(marker_type): return marker_type @callback( Output({"type": "glide-grid", "index": "rows-markers"}, "rowMarkerStartIndex"), Input("row-marker-start", "value"), ) def update_start_index(start): return start or 1 @callback( Output({"type": "glide-grid", "index": "rows-markers"}, "rowMarkerWidth"), Input("row-marker-width", "value"), ) def update_marker_width(width): return width or 50 ``` :defaultExpanded: false :withExpandedButton: true ### Row Selection Control how rows can be selected with `rowSelect`. Use `rowSelectionMode` to determine if modifier keys are required, and `rowSelectionBlending` to control how selections interact. .. exec::examples.reference.rows.selection :code: false ```python # File: examples/reference/rows/selection.py from dash import Input, Output, callback import dash_glide_grid as dgg import dash_mantine_components as dmc columns = [ {"title": "Name", "id": "name", "width": 150}, {"title": "Department", "id": "dept", "width": 120}, {"title": "Salary", "id": "salary", "width": 100}, {"title": "Status", "id": "status", "width": 100}, ] data = [ {"name": "Alice Johnson", "dept": "Engineering", "salary": 95000, "status": "Active"}, {"name": "Bob Smith", "dept": "Marketing", "salary": 72000, "status": "Active"}, {"name": "Carol White", "dept": "Engineering", "salary": 88000, "status": "Away"}, {"name": "David Brown", "dept": "Sales", "salary": 65000, "status": "Inactive"}, {"name": "Eve Davis", "dept": "HR", "salary": 70000, "status": "Active"}, ] component = dmc.Stack( [ dmc.Group( [ dmc.Select( id="rows-row-select-mode", label="Row Select", data=[ {"value": "none", "label": "None"}, {"value": "single", "label": "Single"}, {"value": "multi", "label": "Multi"}, ], value="multi", w=120, ), dmc.Select( id="rows-selection-mode", label="Selection Mode", data=[ {"value": "auto", "label": "Auto (Ctrl/Cmd)"}, {"value": "multi", "label": "Multi (No modifier)"}, ], value="auto", w=160, ), ] ), dgg.GlideGrid( id={"type": "glide-grid", "index": "rows-selection"}, columns=columns, data=data, height=220, rowMarkers="checkbox-visible", rowSelect="multi", rowSelectionMode="auto", ), dmc.Text(id="rows-selection-output", size="sm", c="dimmed"), ] ) @callback( Output({"type": "glide-grid", "index": "rows-selection"}, "rowSelect"), Input("rows-row-select-mode", "value"), ) def update_row_select(value): return value @callback( Output({"type": "glide-grid", "index": "rows-selection"}, "rowSelectionMode"), Input("rows-selection-mode", "value"), ) def update_selection_mode(value): return value @callback( Output("rows-selection-output", "children"), Input({"type": "glide-grid", "index": "rows-selection"}, "selectedRows"), ) def show_selection(rows): if rows: return f"Selected rows: {rows}" return "Click row markers to select rows" ``` :defaultExpanded: false :withExpandedButton: true ### Freezing Rows Use `freezeTrailingRows` to pin rows at the bottom of the grid. This is useful for summary or totals rows that should remain visible while scrolling. .. exec::examples.reference.rows.freeze :code: false ```python # File: examples/reference/rows/freeze.py import dash_glide_grid as dgg columns = [ {"title": "Product", "id": "product", "width": 140}, {"title": "Category", "id": "category", "width": 100}, {"title": "Jan", "id": "jan", "width": 80}, {"title": "Feb", "id": "feb", "width": 80}, {"title": "Mar", "id": "mar", "width": 80}, {"title": "Q1 Total", "id": "q1_total", "width": 100}, ] # Generate sample sales data products = [ ("Widget A", "Electronics"), ("Widget B", "Electronics"), ("Gadget X", "Hardware"), ("Gadget Y", "Hardware"), ("Tool 1", "Tools"), ("Tool 2", "Tools"), ("Part Alpha", "Parts"), ("Part Beta", "Parts"), ("Supply A", "Supplies"), ("Supply B", "Supplies"), ] data = [] totals = {"jan": 0, "feb": 0, "mar": 0, "q1_total": 0} for i, (product, category) in enumerate(products): jan = 1000 + (i * 150) feb = 1200 + (i * 120) mar = 1100 + (i * 180) q1 = jan + feb + mar data.append({ "product": product, "category": category, "jan": jan, "feb": feb, "mar": mar, "q1_total": q1 }) totals["jan"] += jan totals["feb"] += feb totals["mar"] += mar totals["q1_total"] += q1 # Add totals row at the end data.append({ "product": "TOTAL", "category": "", "jan": totals["jan"], "feb": totals["feb"], "mar": totals["mar"], "q1_total": totals["q1_total"] }) component = dgg.GlideGrid( id={"type": "glide-grid", "index": "rows-freeze"}, columns=columns, data=data, height=280, freezeTrailingRows=1, fixedShadowY=True, rowMarkers="number", ) ``` :defaultExpanded: false :withExpandedButton: true ### Trailing Row (Add Row) Add a trailing row at the bottom of the grid for appending new rows. Configure with `trailingRowOptions` and handle new row additions via the `rowAppended` callback. .. exec::examples.reference.rows.trailing :code: false ```python # File: examples/reference/rows/trailing.py from dash import Input, Output, State, callback import dash_glide_grid as dgg import dash_mantine_components as dmc columns = [ {"title": "ID", "id": "id", "width": 60}, {"title": "Name", "id": "name", "width": 150}, {"title": "Email", "id": "email", "width": 200}, {"title": "Department", "id": "dept", "width": 120}, ] initial_data = [ {"id": 1, "name": "Alice Smith", "email": "alice@example.com", "dept": "Engineering"}, {"id": 2, "name": "Bob Johnson", "email": "bob@example.com", "dept": "Marketing"}, {"id": 3, "name": "Carol Williams", "email": "carol@example.com", "dept": "Sales"}, ] component = dmc.Stack( [ dmc.Text( "Click the trailing row at the bottom to add new rows", size="sm", c="dimmed", ), dgg.GlideGrid( id={"type": "glide-grid", "index": "rows-trailing"}, columns=columns, data=initial_data, height=250, rowMarkers="number", trailingRowOptions={ "hint": "Click to add new row...", "sticky": True, "tint": True, }, ), dmc.Text(id="rows-trailing-output", size="sm", c="dimmed"), ] ) @callback( Output({"type": "glide-grid", "index": "rows-trailing"}, "data"), Output("rows-trailing-output", "children"), Input({"type": "glide-grid", "index": "rows-trailing"}, "rowAppended"), State({"type": "glide-grid", "index": "rows-trailing"}, "data"), prevent_initial_call=True, ) def handle_row_appended(row_appended, current_data): if not row_appended: return current_data, "" max_id = max(row["id"] for row in current_data) if current_data else 0 new_id = max_id + 1 new_row = { "id": new_id, "name": f"New User {new_id}", "email": f"user{new_id}@example.com", "dept": "Unassigned", } new_data = current_data + [new_row] return new_data, f"Added row {new_id}" ``` :defaultExpanded: false :withExpandedButton: true ### Row Hover Highlighting [dgg] Enable visual feedback when hovering over rows with `hoverRow`. When enabled, the entire row is highlighted when the mouse hovers over any cell. Customize the highlight color via the `bgRowHovered` theme property. .. exec::examples.reference.rows.hover :code: false ```python # File: examples/reference/rows/hover.py import dash_glide_grid as dgg columns = [ {"title": "Name", "id": "name", "width": 150}, {"title": "Department", "id": "dept", "width": 130}, {"title": "Role", "id": "role", "width": 120}, {"title": "Location", "id": "location", "width": 120}, {"title": "Status", "id": "status", "width": 100}, ] data = [ {"name": "Alice Johnson", "dept": "Engineering", "role": "Senior Dev", "location": "New York", "status": "Active"}, {"name": "Bob Smith", "dept": "Marketing", "role": "Manager", "location": "London", "status": "Active"}, {"name": "Carol White", "dept": "Engineering", "role": "Lead Dev", "location": "Berlin", "status": "Away"}, {"name": "David Brown", "dept": "Sales", "role": "Director", "location": "Tokyo", "status": "Active"}, {"name": "Eve Davis", "dept": "HR", "role": "Coordinator", "location": "Paris", "status": "Active"}, {"name": "Frank Miller", "dept": "Finance", "role": "Analyst", "location": "Sydney", "status": "Busy"}, {"name": "Grace Lee", "dept": "Engineering", "role": "Junior Dev", "location": "Toronto", "status": "Active"}, {"name": "Henry Wilson", "dept": "Marketing", "role": "Designer", "location": "Amsterdam", "status": "Active"}, ] component = dgg.GlideGrid( id={"type": "glide-grid", "index": "rows-hover"}, columns=columns, data=data, height=300, rowMarkers="both", hoverRow=True, theme={ "bgRowHovered": "rgba(0, 100, 200, 0.08)", }, ) ``` :defaultExpanded: false :withExpandedButton: true ### Props Reference #### Row Height Props | Property | Type | Default | Description | |----------|------|---------|-------------| | `rowHeight` | number \| function | 34 | Height of data rows in pixels | #### Row Marker Props | Property | Type | Default | Description | |----------|------|---------|-------------| | `rowMarkers` | string | 'none' | Marker type: 'none', 'number', 'checkbox', 'both', 'checkbox-visible', 'clickable-number' | | `rowMarkerStartIndex` | number | 1 | Starting number for row numbering | | `rowMarkerWidth` | number | auto | Width of the marker column in pixels | | `rowMarkerTheme` | dict | - | Theme overrides for the row marker column | #### Row Selection Props | Property | Type | Default | Description | |----------|------|---------|-------------| | `rowSelect` | string | 'none' | Selection mode: 'none', 'single', or 'multi' | | `rowSelectionMode` | string | 'auto' | 'auto' (requires Ctrl/Cmd) or 'multi' (no modifier) | | `rowSelectionBlending` | string | 'exclusive' | 'exclusive' clears other selections, 'mixed' allows combining | #### Row Freezing & Movement Props | Property | Type | Default | Description | |----------|------|---------|-------------| | `freezeTrailingRows` | number | 0 | Number of rows to freeze at the bottom | | `fixedShadowY` | boolean | True | Show shadow above frozen trailing rows | | `rowMovable` | boolean | True | Allow rows to be reordered by dragging | #### Trailing Row Props | Property | Type | Default | Description | |----------|------|---------|-------------| | `trailingRowOptions` | dict | - | Configuration for the add-row trailing row | | `trailingRowOptions.hint` | string | - | Hint text shown in the trailing row | | `trailingRowOptions.sticky` | boolean | - | Keep trailing row visible at bottom | | `trailingRowOptions.tint` | boolean | - | Apply tinted background to trailing row | | `trailingRowOptions.addIcon` | string | - | Icon to show in the trailing row | | `trailingRowOptions.targetColumn` | number | - | Column index to target for clicks | #### Row Hover Props | Property | Type | Default | Description | |----------|------|---------|-------------| | `hoverRow` | boolean | False | Highlight entire row when hovering over any cell | | `theme.bgRowHovered` | string | 'rgba(0,0,0,0.04)' | Background color for hovered row | #### Row Callback Props | Property | Type | Description | |----------|------|-------------| | `selectedRows` | list | Currently selected row indices (read-only) | | `rowMoved` | dict | Info about last row move: `{startIndex, endIndex}` | | `rowAppended` | dict | Triggered when trailing row is clicked: `{timestamp}` | --- *Source: /reference/rows* *Generated with dash-improve-my-llms*