#!/usr/bin/env -S uv run --script # /// script # dependencies = [ # "nicegui==3.16.0", # ] # /// from nicegui import events from nicegui import ui type TableValue = str | int | float type TableRow = dict[str, TableValue] STATUS_COLORS = { "Ready": "positive", "Low": "warning", "Backorder": "negative", } COLUMNS = [ { "name": "actions", "label": "Actions", "required": True, "align": "center", }, { "name": "name", "label": "Product", "field": "name", "required": True, "sortable": True, "align": "left", "headerClasses": "bg-grey-2 text-grey-9 font-bold", "classes": "font-medium", "headerStyle": "width: 40%; min-width: 12rem", "style": "width: 40%; min-width: 12rem", }, { "name": "category", "label": "Category", "field": "category", "sortable": True, "align": "left", "headerStyle": "width: 9rem", "style": "width: 9rem", }, { "name": "stock", "label": "In stock", "field": "stock", "sortable": True, "align": "right", "headerStyle": "width: 7rem", "style": "width: 7rem", ":classes": "row => row.stock < 10 ? 'text-negative font-bold' : ''", ":format": "value => value == null ? '' : `${value} units`", }, { "name": "price", "label": "Unit price", "field": "price", "sortable": True, "align": "right", "headerStyle": "width: 8rem", "style": "width: 8rem", ":format": "value => value == null ? '' : `$${value.toFixed(2)}`", }, { "name": "status", "label": "Status", "field": "status", "sortable": True, "align": "center", "headerStyle": "width: 8rem", "style": "width: 8rem", "colorByValue": STATUS_COLORS, }, { "name": "updated_at", "label": "Updated", "field": "updated_at", "sortable": True, "align": "left", "headerStyle": "width: 13rem", "style": "width: 13rem", ":sort": "(left, right) => Date.parse(left) - Date.parse(right)", ":format": """(() => { const formatter = new Intl.DateTimeFormat('en-US', { dateStyle: 'medium', timeStyle: 'short', timeZone: 'UTC', }); return value => { if (!value) return ''; const timestamp = Date.parse(value); return Number.isNaN(timestamp) ? 'Invalid date' : formatter.format(timestamp); }; })()""", }, ] ROWS: list[TableRow] = [ { "id": 101, "name": "Desk lamp", "category": "Lighting", "stock": 7, "price": 42.5, "status": "Low", "updated_at": "2026-08-31T16:20:00Z", }, { "id": 102, "name": "Task chair", "category": "Seating", "stock": 18, "price": 289.0, "status": "Ready", "updated_at": "2026-09-01T08:45:00Z", }, { "id": 103, "name": "Monitor arm", "category": "Hardware", "stock": 0, "price": 119.95, "status": "Backorder", "updated_at": "2026-08-29T11:05:00Z", }, { "id": 104, "name": "Cable tray", "category": "Hardware", "stock": 34, "price": 31.25, "status": "Ready", "updated_at": "2026-09-01T14:30:00Z", }, { "id": 105, "name": "Side table", "category": "Furniture", "stock": 9, "price": 164.5, "status": "Low", "updated_at": "2026-08-30T19:15:00Z", }, { "id": 106, "name": "Floor light", "category": "Lighting", "stock": 15, "price": 98.0, "status": "Ready", "updated_at": "2026-09-01T10:10:00Z", }, ] def render_table() -> ui.table: table = ui.table( columns=COLUMNS, column_defaults={"headerClasses": "text-grey-8"}, rows=ROWS, row_key="id", pagination={ "sortBy": "stock", "descending": True, "rowsPerPage": 5, }, ).classes("w-full max-w-5xl") ( table.props( # Surface and cell layout. "flat bordered separator=horizontal wrap-cells" ) .props( # Local sorting and page-size choices; zero means "all rows". 'binary-state-sort :rows-per-page-options="[5, 10, 0]"' ) .props( # Compact cells only below Quasar's medium breakpoint. ':dense="Quasar.Screen.lt.md"' ) .props( # Distinguish an empty dataset from a filter with no matches. 'no-data-label="No inventory items" no-results-label="No matching inventory items"' ) ) with table.add_slot("top-left"), ui.row(align_items="center").classes("gap-2"): ui.icon("inventory_2", size="sm", color="primary") ui.label("Inventory").classes("text-xl font-medium") ui.badge(str(len(ROWS)), color="grey-3", text_color="grey-9") with table.add_slot("top-right"): ui.input(placeholder="Search inventory").props("dense outlined clearable debounce=250").bind_value_to( table, "filter", ) with table.add_slot("body-cell-status"), table.cell("status"): ui.badge(outline=True).props(':label="props.value" :color="props.col.colorByValue[props.value] ?? \'grey\'"') def open_product(event: events.GenericEventArguments) -> None: product = next((row for row in table.rows if row[table.row_key] == event.args), None) if product is None: ui.notify("Product no longer exists", type="negative") return ui.notify(f"Opening {product['name']}") with ( table.add_slot("body-cell-actions"), table.cell("actions"), ui.button(icon="open_in_new") .props("round flat size='sm'") .on( "click.stop", handler=open_product, js_handler="() => emit(props.key)", ), ): ui.tooltip("Open product") with table.add_slot("no-data"), ui.row(align_items="center").classes("w-full justify-center gap-2 p-6 text-grey-7"): ui.icon("inventory_2", size="2em").props(":name=\"props.filter ? 'filter_alt_off' : 'inventory_2'\"") ui.element("span").props(':textContent="props.message"') optional_columns = [column for column in table.columns if not column.get("required")] def set_visible_columns(names: list[str]) -> None: table.props["visible-columns"] = names table.update() ui.select( {column["name"]: column["label"] for column in optional_columns}, value=[column["name"] for column in optional_columns], label="Visible columns", multiple=True, clearable=True, on_change=lambda event: set_visible_columns(event.value), ).props("outlined dense options-dense").classes("w-64") return table if __name__ in {"__main__", "__mp_main__"}: with ui.column(align_items="center").classes("w-full gap-4 p-4"): render_table() ui.run(port=8888, reload=True)