solid-floating-ui
v1.0.1
Published
SolidJS bindings for Floating UI
Maintainers
Readme
solid-floating-ui
SolidJS bindings for Floating UI, covering the same surface as
@floating-ui/react.
Install
npm install --save @floating-ui/dom solid-floating-uiyarn add @floating-ui/dom solid-floating-uipnpm add @floating-ui/dom solid-floating-uiUsage
useFloating positions a floating element against a reference element and
returns the context every interaction hook and floating component needs.
import { createSignal, Show } from 'solid-js';
import {
autoUpdate,
flip,
offset,
shift,
useClick,
useDismiss,
useFloating,
useInteractions,
useRole,
} from 'solid-floating-ui';
function App() {
const [open, setOpen] = createSignal(false);
const floating = useFloating({
get open() {
return open();
},
onOpenChange: (value) => {
setOpen(value);
},
placement: 'bottom-start',
middleware: [offset(8), flip(), shift()],
whileElementsMounted: autoUpdate,
});
const interactions = useInteractions([
useClick(floating.context),
useDismiss(floating.context),
useRole(floating.context, { role: 'dialog' }),
]);
return (
<>
<button
{...interactions.getReferenceProps()}
ref={(element) => floating.refs.setReference(element)}
>
Toggle
</button>
<Show when={open()}>
<div
{...interactions.getFloatingProps()}
ref={(element) => floating.refs.setFloating(element)}
style={floating.floatingStyles}
>
Floating content
</div>
</Show>
</>
);
}Options are read reactively
Every hook takes a plain options object whose properties are read lazily, the way SolidJS reads component props. Pass a getter for anything that changes:
useHover(floating.context, {
get enabled() {
return enabled();
},
delay: { open: 200, close: 100 },
});The same holds for what the hooks return. floating.placement,
floating.floatingStyles and floating.context.open are live reads, so using
them inside JSX keeps the markup up to date without any extra wiring.
Documentation
Run pnpm dev for the playground, an app
with a demo of every hook and component.
The docs/ directory covers the whole surface:
- Getting started
- Reactivity
- Positioning
- Interactions
- Components
- Transitions
- Utilities
- Recipes
- Migrating from
@floating-ui/react
Claude Code plugin
plugins/solid-floating-ui is a Claude Code
plugin for building these patterns:
/plugin marketplace add lxsmnsyc/solid-floating-ui
/plugin install solid-floating-ui@solid-floating-uiIt adds one skill, solid-floating-ui, which loads on its own whenever the work
involves anchored or overlay UI in a SolidJS project. The skill carries the
reactivity rules that decide whether the result updates at all, plus a complete
working recipe for each pattern: tooltip, popover, dialog, select, nested menus,
context menu, cursor tracking, composite, transitions, delay groups and the
arrow.
Two commands come with it:
/floating-ui-recipe <name>scaffolds one of those patterns into the current project, matching the conventions already in the codebase./floating-ui-audit [path]reviews existing usage for the mistakes that type-check and render but silently stop updating.
What is included
Positioning:
useFloating,usePosition,useFloatingRootContext- The middleware re-exported from
@floating-ui/dom, plus anarrowthat accepts an accessor
Interactions, composed through useInteractions:
useClick,useClientPoint,useDismiss,useFocus,useHover,useListNavigation,useRole,useTypeaheadsafePolygonforuseHover
Components:
FloatingArrow,FloatingFocusManager,FloatingListwithuseListItem,FloatingOverlay,FloatingPortal,FloatingTreewithFloatingNodeFloatingDelayGroupand the experimentalNextFloatingDelayGroupCompositeandCompositeItem
Utilities:
useMergeRefs,useTransitionStatus,useTransitionStylessolid-floating-ui/utilsfor the DOM helpers Floating UI exposes
Differences from @floating-ui/react
- Options and returned values are reactive getters, read where they are used, rather than values captured on render.
- There are no ref containers. Anything the library reads from you is an
accessor, such as
itemsor thearrowelement, and anything it produces arrives through a callback, such asFloatingList'sonElementsChange. CompositeandCompositeItemtake arendercallback only.- Prop getters produce SolidJS event names, so focus is handled through
onFocusInandonFocusOut.
Updating the position
useFloating recomputes the position when the elements or the positioning
options change. Pass autoUpdate as whileElementsMounted to keep the
floating element anchored while scrolling and resizing:
useFloating({
whileElementsMounted: (reference, floating, update) =>
autoUpdate(reference, floating, update, { animationFrame: true }),
});You can also recompute at will:
const floating = useFloating();
floating.update();Virtual elements
See Virtual Elements for
details. Pass one through refs.setPositionReference:
const floating = useFloating();
floating.refs.setPositionReference({
getBoundingClientRect() {
return {/* ... */};
},
});Sponsors
License
MIT © lxsmnsyc
