Our review
A set of conventions for building TypeScript user interfaces in Datagrok: tabs, grids, layouts, dialogs, toggle menus and drag-and-drop.
Strengths
- Enforces lazy loading through getContent callbacks for tabControls and accordions, preventing needless construction of heavy components
- Pairs good and bad code samples side by side, making the rules easy to copy
- Gives precise API choices (DG.Viewer.grid vs DG.TableView.create, ui.splitH/divV, menu.items with isChecked)
- Includes concrete performance guidance (debounce, canvas rendering, in-place updates)
Limitations
- Tightly bound to the Datagrok ecosystem and its js-api, so it is useless outside that framework
- The document is truncated (the 'Common Anti-Patterns' section is cut off), so the full list of pitfalls is missing
- Assumes prior familiarity with DG classes (Viewer, JsViewer, Menu) without explaining them
Reach for it whenever you create or modify a UI component, viewer, dialog or drop zone inside a Datagrok TypeScript package.
Skip it for front-end work outside Datagrok, or when you need complete anti-pattern documentation that this file does not provide.
Security analysis
SafeThis skill provides static coding guidelines and patterns for building UI in Datagrok. It does not instruct any execution of commands, file operations, network requests, or data exfiltration. It is purely educational content about TypeScript UI development.
No concerns found
Examples
Refactor this Datagrok tab control so each pane builds its grid lazily with addPane and a getContent callback instead of eagerly creating every viewer.Build a tree plus content split panel in Datagrok with ui.splitH, embedding the selected DataFrame using DG.Viewer.grid rather than opening a full TableView.Create a DG.Menu.popup with Debug and Benchmark toggles that use menu.items with isChecked and closeOnClick = false, instead of prefixing labels with a checkmark.Add a droppable panel to my Datagrok viewer using ui.makeDroppable with acceptDrop and doDrop handlers so users can drag tables from the browse tree onto it.name: ui description: UI building guidelines for Datagrok TypeScript components, viewers, and drag-and-drop when-to-use: When creating or modifying UI components, viewers, dialogs, file viewers, layouts, grids, or drag-and-drop effort: low
Datagrok UI Building Guidelines
Rules and patterns for building UI in TypeScript packages and libraries. These are authoritative — follow them unless the user explicitly overrides.
Tab Controls
- Always use
addPanewith a lazygetContentcallback — never pass pre-built elements - This avoids creating heavy components (grids, viewers, DataFrames) for tabs the user may never open
// Good
const tabs = ui.tabControl();
tabs.addPane('Sheet 1', () => {
const df = buildDataFrame();
const grid = DG.Viewer.grid(df);
return grid.root;
});
// Bad — all tabs built eagerly
const tabs = ui.tabControl({
'Sheet 1': buildExpensiveGrid(),
'Sheet 2': buildExpensiveGrid(),
});
Grids and Viewers
- Prefer
DG.Viewer.grid(df)for embedding a grid inside a composite layout - Prefer
DG.TableView.create(df, false)when the grid IS the entire view - The second argument (
false) prevents the table from being added to the workspace
Layouts
- Use
ui.splitH/ui.splitVfor resizable split panels - Use
ui.divV/ui.divHfor simple stacking without resize handles - Set
flex: 1on the element that should fill remaining space - For tree + content layouts, use
ui.splitH([tree.root, contentPanel])
Dialogs and Inputs
- Use
ui.dialog()for modal interactions - Use
ui.input.choice(),ui.input.int(),ui.input.bool(), etc. for typed inputs - full set of input functions is injs-api/ui.ts. PreferonValueChangedin the options object over.onChanged.subscribe():
ui.input.bool('Debug', {value: DG.Test.isInDebug, onValueChanged: (v) => DG.Test.isInDebug = v});
Use ui.form([...inputs]) to render a labeled list of inputs inside a dialog
- For property panels, prefer
DG.JsViewerproperties (this.string(...),this.int(...)) which automatically appear in the context panel
Toggle Settings in Popup Menus
For toggleable settings in a DG.Menu.popup(), use menu.items() with isChecked — never use text-prefix hacks like `${flag ? '✓ ' : ''}Label`:
const toggles = [
{label: 'Debug', get: () => DG.Test.isInDebug, set: (v: boolean) => { DG.Test.isInDebug = v; }},
{label: 'Benchmark', get: () => DG.Test.isInBenchmark, set: (v: boolean) => { DG.Test.isInBenchmark = v; }},
];
const menu = DG.Menu.popup();
menu.closeOnClick = false;
const refresh = () => {
menu.clear();
menu.items(toggles, (t) => { t.set(!t.get()); refresh(); }, {isChecked: (t) => t.get()});
};
refresh();
menu.show();
Performance
- Debounce resize and selection handlers:
DG.debounce(observable, 50) - For large datasets, prefer canvas-based rendering over DOM elements
- Avoid re-creating viewers on every data change — update in place when possible
Accordion
- Use
ui.accordion()with lazygetContentcallbacks (same principle as tab controls)
const acc = ui.accordion();
acc.addPane('Details', () => buildDetailsPanel());
acc.addPane('Statistics', () => buildStatsPanel());
Drag and Drop
ui.makeDroppable(el, IDragAndDropOptions<T>)— receive entities dragged from the browse tree, grid, or other sources.acceptDrop(obj)— fast predicate for showing the zone.doDrop(args)— handle the drop.argsis aDragDropArgs<T>withdragObject,dragSource,dragObjectType,copying(Ctrl/Cmd),link(Alt),handled.- Rich hooks:
acceptDrag,onBeginDrag,onEndDrag,onMouseEnter/Over/Leave/Out,dropSuggestion,makeDropZone,dropZoneRectTransformation,dropIndication.
ui.makeDraggable(el, {getDragObject, getDragCaption})— make your own UI a drag source.- Sample:
ApiSamples/scripts/ui/interactivity/drag-and-drop.js.
Common Anti-Patterns
- Do not use raw
document.createElementwhenui.*helpers exist - Do not set
innerHTMLwith user data — useui.divText()ortextContent - Do not use
style.width = '100%'on tables — let them size to content - Do not build all content eagerly in multi-pane layouts (tabs, accordions)
Next.js App Router Expert
Development
A skill that turns Claude into a Next.js App Router expert.
README Generator
Development
Creates professional and comprehensive README.md files for your projects.
API Documentation Writer
Development
Generates comprehensive API documentation in OpenAPI/Swagger format.