Controllers

A controller is a small class that adds one behavior to an element: listening, dismissing, positioning, moving focus, dragging. Radiant UI components are assembled from them, and so can yours be.

Controllers need a browser. Pure logic with no DOM (dates, masks, numbers, ordering math) is in Helpers. Both entries are tree-shakeable: a bundle contains only what it imports.

import { createSwipeController } from '@ecopages/radiant-ui/controllers';

The shape of a controller

Every controller is a plain class with attach() and destroy(). The constructor does nothing; attach() starts work and destroy() ends all of it, and both are safe to call again. Each class has a createX(host, config) factory that attaches on connect and destroys on disconnect, where host is a RadiantElement or anything with registerConnectedCallback and registerCleanupCallback. Without a host, construct the class and call attach() and destroy(), as the examples on these pages do. See bindController.

Config is getters (getItems, getTarget) and callbacks (onChange), so the element keeps its own state and the controller never reaches into it. Where a decision may need to differ, a controller documents a protected hook; see Composing a component.

Controllers

ControllerWhat it doesReach for it when
bindControllerThe contract and the connect and cleanup wiring behind every factory.You write a new controller, or hold one without a factory.
EventListenerControllerListens to event types on a target while attached; typed from target and type.Listeners on document or window, added and removed at runtime, or with once.
MutationControllerA MutationObserver on a node.You react to children or attributes changing.
ResizeControllerA ResizeObserver on elements.You react to an element changing size.
DismissControllerReports a pointer press outside a surface, focus leaving it, or Escape.A dialog, drawer or popup that closes itself.
PopoverControllerPortal mount, floating position, dismissal and teardown of a popup.A popup, hover card or menu panel beside an anchor.
PortalControllerMoves a node into document.body (or a container) and carries the origin theme.A surface that must escape clipping or stacking contexts.
FocusTrapControllerKeeps Tab inside a modal surface and returns focus on destroy.A modal dialog.
ScrollLockControllerLocks scroll on the page or a scroll container, counted across controllers.A modal that must stop the page or a container scrolling.
RovingControllerRoving tabindex with arrows, Home and End over the items you return.Tabs, toolbars, lists and grids with one tab stop.
SwipeControllerReports a left, right, up or down swipe on release.A carousel or pager.
PointerDragControllerPointer capture, move, end and cancel, with position, delta and the element under the pointer.A slider, splitter, resize handle or free-form drag.
SortableControllerReorders items, or moves them between containers, by pointer or keyboard with announcements. It never moves a node: onChange does.A reorderable list or board, including drag between lists.
MenuTreeControllerNested submenu coordination: timers, keyboard, popovers.A menu button or menubar with submenus.

DOM utilities

The same entry exports functions that touch elements. They have no page of their own; the TSDoc of each says how to use it.

ExportWhat it doesReach for it when
applyFloatingPosition, attachFloatingFloating placement with flip and clamping, applied to an element and kept on scroll and resize.You position a surface without a popover.
queryFocusableCandidates, getFocusableElements, findFirstFocusableCandidate, queryRovingTabindexItemsQuery focusable descendants; getFocusableElements also skips hidden ones (needs layout).Custom focus loops and initial focus.
applyRovingTabindex, focusRovingItem, navigateRovingTabindexThe roving tabindex functions RovingController composes.One-off roving navigation without a controller.
getVisibleCollectionOptions, setCollectionActive, clearCollectionActivearia-activedescendant and data-active bookkeeping for option collections.Active-descendant lists, such as a combobox you build yourself.
SORTABLE_*_ATTRIBUTE, SORTABLE_OFFSET_PROPERTIESThe data-sortable-* attributes and --sortable-dx and --sortable-dy the sortable sets.Styling a sortable.

How the examples run

Each example on these pages is a mount(root) function in the page's script. It receives one [data-example="<name>"] element, wires the controllers to that element and returns the function that undoes it, which is where destroy() goes. A controller that listens on document or window must be destroyed there, or it keeps listening after the example is gone.

The page script ends with a call to mountExample, which the code blocks leave out. It mounts each matching element once when the page loads and again for the new elements the router swaps in (eco:page-load and eco:after-swap), and it runs the returned function for an element that left the page. A script is a module and runs once per tab, so the page cannot rely on it running again after a navigation.