floating-runes Svelte Themes

Floating Runes

Uses Svelte 5 runes to wrap floating-ui with additional features like tethering and conditional triggers

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:

Other than that, just use it as you would use @floating-ui🎉

Happy coding!🦒


Usage

  1. Simple example
  2. Tethering
  3. Advanced use
  4. Portal action

Options and properties

  1. floatingUI
  2. use:float
  3. float.ref and float.tether
  4. float.untether

Usage

bun add floating-runes

  • use:float - Designating the floating elements
  • use:float.arrow - Designated arrow element; must be a direct child element of use: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 multiple use: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]
The arrow middleware does not take an element property. Instead apply the Svelte action use:float.arrow

.then(...)

Read more about
const 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 the arrow 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'}



Top categories

Loading Svelte Themes