<Halo />
Shows a contextual toolbar of action handles anchored to a single element or
link. By default an element gets remove, clone, fork, link, unlink and rotate
handles, and a link gets remove and direction. Wraps the JointJS+ ui.Halo
widget and renders no DOM of its own β the halo is created and updated
imperatively on the paper.
Use it in either mode:
- Outside
renderElement: pass the target via thecellprop, usually driven by selection state. Passnullto detach the halo. - Inside
renderElement: omitcell; the rendered cell is targeted automatically from context (passingcellthere is ignored β a console warning is logged and the halo is disabled).
Replace or transform the buttons with the handles / groups props (compose
built-in handles with getHaloDefaultHandle), and reach any native
option through the HaloOptions options escape hatch. See
HaloProps for every supported prop.
Seeβ
Examplesβ
Attach to the selected element
import { GraphProvider, Paper, type CellId, Halo } from '@joint/react-plus';
import { useState } from 'react';
function Editor() {
const [selectedId, setSelectedId] = useState<CellId | null>(null);
return (
<GraphProvider>
<Paper
renderElement={() => <rect width={80} height={40} fill="#3498db" />}
onElementPointerClick={({ id }) => setSelectedId(id)}
/>
{selectedId && <Halo cell={selectedId} />}
</GraphProvider>
);
}
Inside renderElement (no cell needed)
import { GraphProvider, Paper } from '@joint/react';
import { Halo } from '@joint/react-plus';
// Targets the rendered cell automatically.
<GraphProvider>
<Paper renderElement={() => <Halo />} />
</GraphProvider>;
Propsβ
cell?β
readonly optional cell?: ID | Cell<Attributes<Selectors>, ModelSetOptions> | null;
Cell to attach the halo to: accepts a dia.Cell instance or a cell id.
Required when used outside renderElement. Inside renderElement the
cell is taken from CellIdContext; passing cell there is ambiguous, so
it is ignored (a console warning is logged and the halo is disabled). Pass
null to disable the halo explicitly.
groups?β
readonly optional groups?: object;
Named handle groups keyed by group name: each entry positions and aligns
the handles assigned to it (position, alignment, gap, className).
Index Signatureβ
[groupName: string]: HandleGroup
Defaultβ
JointJS default group layout
handles?β
readonly optional handles?: HaloHandles;
Halo handles. Pass an array to fully override the defaults, or a function
(defaultHandles) => HaloHandle[] to transform the cell-type defaults
(e.g. element vs link). The function form receives the handles this
component would apply by default for the current cell type (element:
remove, clone, fork, link, unlink, rotate; link: remove, direction),
useful for filtering / tweaking individual handles without re-listing them
all. Compose individual built-in handles with getHaloDefaultHandle.
Each handle accepts a title: a button tooltip set as the title
attribute on the handle (mapped to the native attrs). Built-in handles
carry a default title; pass your own to override.
A handle's events callbacks receive contextual params
({ event, x, y, model, paper, graph }) => void instead of native
positional (evt, x, y) arguments.
Defaultβ
The built-in handles for the cell type (element or link).
options?β
readonly optional options?: Partial<Options>;
Raw ui.Halo.Options passthrough for anything joint-react-plus doesn't
expose as a dedicated prop: bbox, loopLinkPreferredSide,
loopLinkWidth, clone, magnet, the pie* fields (irrelevant for the
overlay type), plus mvc internals.
Element / link creation is configured per handle via the handle's
makeElement / makeLink (see HaloHandle); a global native
makeElement / makeLink can still be passed here.
Avoid overriding joint-react-plus-controlled options (cellView).
Future improvement: expose magnet as a dedicated prop once its signature
is reviewed for the React-context world (needs a port-linking demo to validate).
rotateAngleGrid?β
readonly optional rotateAngleGrid?: number;
Snap rotation to multiples of this angle (degrees) when using the rotate handle.
Defaultβ
15