Dos and Don’ts
Practical rules for building maintainable SDK widgets.
Schema and Defaults
Do:
Keep defaults in schema
defaultfields.Add
titleanddescriptionfor every field users can edit.Use
levelwhen settings should be role-gated.
Don’t:
Duplicate defaults in both schema and runtime constants.
Hide side effects (workspace switch or variable update) behind unclear field names.
Custom Inputs
Do:
Use
INPUT_*shortcuts for Tango/workspace/variable fields.Use normalization helpers (
normalizeTangoAttributeInputs,normalizeTangoAttributeRows).
Don’t:
Hand-roll endpoint and attribute parsing repeatedly in each widget.
Mix incompatible value shapes for the same setting.
Data Flow
Do:
Expose explicit
useLiveDatabehavior when both stream and polling are valid.Render clear loading/error/empty states.
Use
useWidgetRefreshRate(instanceId)for polling cadence.
Don’t:
Assume stream payload shape is always complete.
Hardcode polling intervals unrelated to dashboard refresh settings.
Tables
Do:
Use
InteractiveTableanduseInteractiveTableState.Persist order/width/sort changes if users expect state to survive reloads.
Don’t:
Reimplement column drag/resize/sort mechanics for each widget.
Store persisted table state outside widget config without a clear reason.
Host State Integration
Do:
Use
useVariables,useWorkspace, anduseBrushfor shared behavior.Document click actions that update workspace/variables.
Don’t:
Use custom global state channels for behavior already provided by SDK hooks.
Trigger hidden global side effects from purely visual controls.
Plotly Chart Widgets
Do:
Use
usePlotlyResizefor container sizing — it wires a ResizeObserver, rAF, and 48 ms debounce for you.Use
useThemeObserver(andreadTheme) to read CSS custom properties for colors. Never hardcode hex values.Use
canonicalAttrto normalise attribute paths before comparing or displaying them.Use
parseMargins,buildAxisTitle,formatLegendName,dedupeLegendLabelsfrom the SDK instead of writing local copies.Use
getPlotlyLegendConfig(pos)for the legend anchor config; only add widget-specific margin adjustments locally.Use
applyVerticalColorRankingfor ranking trace colors by peak value.
Don’t:
Inline a ResizeObserver +
Plotly.Plots.resizepattern —usePlotlyResizealready does this.Inline a
MutationObserverondocument.bodyfor theme changes —useThemeObserveralready does this.Re-implement
parseMargins,canonicalAttr, orformatLegendNamelocally. These functions exist in the SDK and are tested there.Add
plotly.js-dist-minto the SDK — the SDK has no Plotly runtime dependency by design; use plain types or generics in any code contributed to the SDK.
Testing
Do:
Use
@ska-octopus-widget-sdk/widget-sdk/testingfor predictable mocks.Test schema/definition shape and critical runtime paths.
Don’t:
Depend on network services in unit tests.
Skip tests for config normalization and persistence callbacks.