Create and initialize the dimension slider UI component.
Builds the complete slider interface including styled containers, individual sliders for each non-displayed dimension, and status bar showing current slice positions. The UI follows napari-style aesthetics for scientific data visualization familiarity.
The sliders are automatically synchronized with sceneDimsManager - moving a slider triggers dimension changes which update all nD objects in the scene.
Configuration object for slider initialization
Configuration interface for initializing dimension sliders.
SliderConfig
DOM container where slider UI will be mounted
Current dimension state from scene manager
Navigable bounds for each dimension
Human-readable names for each dimension
OptionaldimensionUnits?: string[]Optional physical units for each dimension
OptionalselectedDimension?: numberZero-based position in the non-displayed dimension list selected for [ / ].
OptionalonSelectDimension?: (navigableIndex: number) => voidFired when the panel selects the [ / ] target itself: under a coarse pointer each dimension's name is a tappable chip, the finger's stand-in for the 1–9 keys. Receives the position in the non-displayed list.
// After scene loads and dims are initialized
const dims = sceneDimsManager.getDims();
const ranges = sceneDimsManager.getDimensionRanges();
const names = sceneDimsManager.getDimensionNames();
const sliders = new DimensionSliders({
container: getViewerContainer(),
dims,
dimensionRanges: ranges,
dimensionNames: names,
dimensionUnits: ['μm', 'μm', 'μm', 's', '']
});
// Sliders now appear at bottom of viewport
// User can drag sliders or use arrow keys to navigate
PrivatecontainerRoot DOM container for the slider UI
PrivateslidersGlass-surface root of the panel (positioning, sizing, visibility)
PrivatescrollInner scroll wrapper that holds all panel content. Scrolling must not
live on the glass root (its glass layers paint at inset: 0 behind it
and a scroll container clips them) — see UI_DESIGN_GUIDE §5.1.2/§7.4.
Created once, so clearing the content never destroys it.
PrivatestatusStatus text element in the title bar
PrivatedimsCurrent dimension state (reference to scene manager state)
PrivatedimensionNavigable bounds for each dimension
PrivatedimensionHuman-readable dimension names for UI labeling
PrivatedimensionPhysical units for each dimension
PrivateselectedZero-based position in the non-displayed dimension list selected for [ / ].
Private Optional ReadonlyonPrivateslidersMap of dimension indices to their corresponding HTML slider elements
PrivatedropdownsMap of dimension indices to their corresponding dropdown select elements
PrivatetogglesMap of dimension indices to their corresponding toggle elements (binary categoricals)
PrivatesliderCleanup group for all per-slider DOM listeners (input, keydown, change,
toggle click, play-button click + contextmenu). The group is rebuilt on
every createSliders() call so that disposing it removes every listener
from the previous render in one shot — no per-handler bookkeeping.
Hover/focus visual states are handled entirely by CSS :hover and
:focus pseudo-classes — no JS listeners are attached for those.
Private OptionalanimationAnimation manager for dimension playback (set by InputHandler)
PrivateplayMap of dimension indices to play button elements
PrivatesliderCached DOM refs for the per-slider visual children. Filled in
createSlider, read by updateSliderVisuals to avoid three
document.getElementById lookups per call (this method runs at
up to 60 fps during animation playback).
PrivateactiveActive context menu element (only one can be open at a time)
PrivatecontextStored event handlers for context menu cleanup
OptionalclickOutside?: (e: MouseEvent) => voidOptionalclickOutsideTimeout?: TimeoutPending setTimeout that will install the click-outside handler. Tracked so closeContextMenu() can cancel it if the menu is closed before the deferred handler is attached — without this, the listener gets attached but never removed, leaking on every Escape-cancel.
PrivateanimationCleanup group for animation-manager listeners. Rebuilt every time
setAnimationManager() is called so that re-binding to a new manager
(or detaching from the old one) is a single dispose.
Set animation manager and create animation controls for existing sliders Called by InputHandler after both DimensionSliders and DimensionAnimationManager are initialized
The animation manager instance
PrivatecreatePrivate
Create the main container element for sliders with napari-style styling.
Builds a fixed-position panel at bottom-center of viewport with:
overflow: visible (§5.1.2/§7.4)The glass root and the inner scroll wrapper that receives content
PrivatecreatePrivate
Creates individual slider controls for all non-displayed dimensions.
This method rebuilds the entire slider interface, creating a separate control for each dimension that isn't currently being displayed in the 3D scene. The logic ensures that users only see controls for dimensions they can actually navigate through.
UI structure:
PrivatecreatePrivate
Create a dropdown control optimized for grid layout.
Compact dropdown designed to fit in a responsive grid (max 3 per row). Used for categorical dimensions with < 10 categories.
Provides:
Zero-based index of dimension to create dropdown for
Grid container to append dropdown to
PrivatecreatePrivate
Create a binary toggle control for a dimension with exactly 2 values.
Segmented toggle button that shows both labels side by side with the active value highlighted. Single click toggles between the two values.
Provides:
Zero-based index of dimension to create toggle for
Grid container to append toggle to
PrivateupdatePrivate
Update a toggle element's text and visual state.
Shows the current value's label. When value is 1 (second option), applies the --on modifier for highlighted styling.
The toggle button element
The currently active value (0 or 1)
PrivatecreatePrivate
Create an individual slider control for a specific dimension.
Builds a complete slider UI with:
Handles both discrete (frame-based) and continuous (time-based) dimensions with appropriate step sizes and value formatting. For categorical dimensions with many categories (≥10), displays category labels.
Zero-based index of dimension to create slider for
PrivatewrapCoarse pointers only: ‹ track ›, one dimension step per tap (the
authored step, else 1 % of the range — the same base step as the [ / ]
keys), in the same wrapper the play button later joins.
A finger cannot scroll a slider by a single step, and a phone has no
bracket keys; the buttons are the missing precise input.
PrivatemakeCoarse pointers only: the dimension's name selects it as the [ / ] target.
PrivateupdatePrivate
Update visual elements of a slider to reflect current value.
Synchronizes all visual components:
Called during slider creation and whenever dimension value changes (from keyboard navigation or programmatic updates).
Dimension index to update visuals for
Current dimension value to display
If true, rounds value to integer for display
Get current visibility state of sliders.
true if sliders are currently visible, false if hidden
Hide the dimension sliders panel.
Sets display to 'none'. Sliders remain in DOM for fast re-showing. Use when temporarily hiding UI or when dataset has no non-displayed dimensions.
Updates the status bar text to reflect the current dimensional state.
The status bar shows the current keyboard-navigation target and the dimensions displayed in 3D. Per-dimension values remain visible on their own controls.
Format:
Update the dimension targeted by the global [ / ] keyboard shortcuts.
Synchronizes all controls (sliders and dropdowns) with the current dimension state.
This method is called by the scene dimension manager's observer system whenever dimensions change. It ensures the UI accurately reflects the current slice positions by updating control positions, value labels, and the status bar.
Critical for maintaining UI consistency during:
PrivateaddPrivate
Add animation controls to all existing sliders
PrivateaddPrivate
Add animation controls to a specific slider (compact layout with context menu)
PrivateshowPrivate
Show context menu for animation settings (Napari-style)
Close active context menu and clean up event listeners
PrivateupdatePrivate
Update play button appearance based on animation state
Set visibility of slider interface (show or hide).
Used by main application to control slider display based on dataset characteristics (nD vs 3D) or user preferences.
true to show sliders, false to hide them
Clean up slider UI and release resources.
Removes all DOM elements and clears internal state. Important for preventing memory leaks when visualization is destroyed or reinitialized with different dataset.
After calling dispose(), the DimensionSliders instance cannot be reused. Create a new instance if sliders are needed again.
Interactive UI component providing sliders for navigating through non-displayed dimensions.
This component creates a sophisticated slider interface that allows users to navigate through nD datasets by adjusting positions in dimensions not currently displayed in 3D. It provides both mouse and keyboard interaction with visual feedback and status display.
Key features:
Design philosophy:
Slider synchronization:
DimensionSliders