Svelte 5 Runes powered wrapper for @floating-ui. An alternative approach to svelte-floating-ui which approx. does the same thing.
floating-runes will also:
autoPosition: false
is provided)$state
for .referenced
, .tethered
, .attached
(tethered ?? referenced)portal
actionOther than that, just use it as you would use @floating-ui
🎉
Happy coding!🦒
Usage
Options and properties
bun add floating-runes
use:float
- Designating the floating elementsuse:float.arrow
- Designated arrow element; must be a direct child element of use:float
use:float.ref
- The thing the floated element(s) is referencingSvelte Playground - Usage example
<script>
import floatingUI, { flip, shift, arrow } from 'floating-runes'
const float = floatingUI({
placement: 'top',
middleware: [
flip(),
shift(),
arrow()
]
})
</script>
<div>
<tooltip use:float>
<arrow use:float.arrow></arrow>
</tooltip>
<button use:float.ref> Hover me </button>
</div>
[!TIP]
P.S. you can use multipleuse:float
from the same declaration.
You can use float.tether(element)
to float to another element than the float.ref
. Then use float.untether()
and it returns to float.ref
.
Svelte Playground - Tethering example
<script>
import floatingUI, { flip, shift, arrow } from 'floating-runes'
let url = '/a' // demo example
const float = floatingUI()
</script>
{#snippet href(ref, text)}
<a
class:active={ref === url}
use:float.ref={() => ref === url}
use:float.tether={'pointerenter'}
href={ref}
>
{text}
</a>
{/snippet}
{#if float.tethered}
<div class='hovered' use:float={{ untether: false }}></div>
{/if}
<div class='active' use:float={{ tether: false }}></div>
<div use:float.untether={'pointerleave'}>
{@render href('/a', 'Hover me')}
{@render href('/b', 'I want attention')}
{@render href('/c', 'Guys... what about meeEeEe')}
{@render href('/d', 'Ignore my brother')}
</div>
As per the documentation of @floating-ui, you can access the .then(...) which works in the same way as their documentation.
So you can go wild🦒
<script>
import floatingUI, { ... } from 'floating-runes'
const float = floatingUI({
placement: 'top',
middleware: [
...
]
}).then(computedData => {
const { middlewareData } = computedData
...
})
</script>
As a bonus, you can use portal
to move an element to another (such as the body).
When the component is destroyed, the element that was portalled, will naturally, also get destroyed.
<script>
import { portal } from 'floating-runes'
</script>
<div use:portal> I'm in the body😏 </div>
<div use:portal={element}> I'm in another element </div>
FloatingRuneOptions extends ComputePositionConfig
Property | Type | Description |
---|---|---|
middleware? | Middleware[] | Array of middleware objects to modify the positioning or provide data for rendering |
platform? | Platform | Custom or extended platform object |
placement? | | 'top' | 'top-start' | 'top-end' | 'right' | 'right-start' | 'right-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end' |
Where to place the floating element relative to its reference element Default: 'bottom' |
strategy? | 'absolute' | 'fixed' |
The type of CSS position property to use Default: absolute |
autoUpdate? | AutoUpdateOptions | Whether or not to auto-update the floating element's position |
autoPosition? | boolean |
Whether or not to auto-position the floating element and the arrow, and auto-assign the position: to the strategy (absolute/fixed)Default: true |
[!NOTE]
Thearrow
middleware does not take anelement
property. Instead apply the Svelte actionuse:float.arrow
.then(...)
Read more aboutconst float = floatingUI(...).then((data: ComputePositionReturn) => void)
float.referenced
, float.tethered
and float.attached
The element that has been referenced to, or tethered to. Attached will return tethered ?? referenced
use:float
This Svelte action creates a floater, that floats relative to the reference- and tethered element.
use:float={FloatOptions}
Property | Type | Description |
---|---|---|
tether |
boolean |
Whether-to-tether. Default: true |
untether |
boolean |
If false it will stick to the last tethered target, instead of going back to the reference. Default: true |
float.arrow
use:float.arrow
This Svelte action creates reference to the element that serves as the arrow to a use:float
element. Must be a direct child.
<div use:float>
...
<arrow use:float.arrow>...</arrow>
</div>
[!TIP]
Remember to include thearrow
middleware, and put it after other middlewares if needed.
float.ref
and float.tether
use:float.ref
and use:float.tether
These Svelte actions sets the reference point for the use:float
element.
Additionally, they accept a trigger parameter: A conditional callback (() => boolean
) or an event (keyof WindowEventMap
).
Ex.
use:float.ref={() => url === href}
or
use:float.tether={'pointerenter'}
float.untether
float.untether
removes the tethering, so that the floating element will return to the reference (unless untether: false
is provided).
It can be used directly: float.untether()
Or like float.ref
and float.tether
have a condition to trigger;
Ex.
use:float.untether={() => condition}
or
use:float.untether={'pointerleave'}