floating-runes
v1.0.0
Published
Uses Svelte 5 runes to wrap floating-ui with additional features like tethering and conditional triggers
Downloads
139
Readme
Floating Runes
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:
- Position arrow/floater automatically (unless
autoPosition: false
is provided) - Access the elements via
$state
for.referenced
,.tethered
,.attached
(tethered ?? referenced) - Tethering (temporary element reference)
- Conditional reference/tethering
- A
portal
action
Other than that, just use it as you would use @floating-ui
🎉
Happy coding!🦒
Usage
Options and properties
Usage
bun add floating-runes
use:float
- Designating the floating elementsuse:float.arrow
- Designated arrow element; must be a direct child element ofuse:float
use:float.ref
- The thing the floated element(s) is referencing
Svelte 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.
Tethering
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>
Advanced
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>
Bonus
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>
Options
floatingUI
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
float
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'}