|
1 | | -# create-svelte |
| 1 | +# svelte-floating-ui |
2 | 2 |
|
3 | | -Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte). |
| 3 | +[Floating UI](https://github.com/floating-ui/floating-ui/) for Svelte with [actions](https://svelte.dev/docs#use_action). No wrapper components or component bindings required! |
4 | 4 |
|
5 | | -## Creating a project |
6 | | - |
7 | | -If you're seeing this, you've probably already done this step. Congrats! |
| 5 | +## Installation |
8 | 6 |
|
9 | 7 | ```bash |
10 | | -# create a new project in the current directory |
11 | | -npm init svelte |
| 8 | +npm i svelte-floating-ui |
| 9 | +``` |
| 10 | + |
| 11 | +This is not yet published on npm |
| 12 | + |
| 13 | +Since Svelte automatically bundles all required dependencies, you only need to install this package as a dev dependency with the -D flag. |
| 14 | + |
| 15 | +## Usage |
| 16 | + |
| 17 | +`createFloatingActions` takes an optional [options object](https://floating-ui.com/docs/computePosition#options) for configuring the content placement. The content action also takes an optional [options object](https://floating-ui.com/docs/computePosition#options) for updating the options of the content placement. |
| 18 | + |
| 19 | +`createFloatingActions` also returns an `update` method as it's third value which can be used to [manually update](https://floating-ui.com/docs/computePosition#updating) the content position. |
12 | 20 |
|
13 | | -# create a new project in my-app |
14 | | -npm init svelte my-app |
| 21 | +### Example |
| 22 | + |
| 23 | +```svelte |
| 24 | +<script lang="ts"> |
| 25 | + import { offset, flip, shift } from "@floating-ui/dom"; |
| 26 | + import { createFloatingActions } from "svelte-floating-ui"; |
| 27 | +
|
| 28 | + const [ floatingRef, floatingContent ] = createFloatingActions({ |
| 29 | + strategy: "absolute", |
| 30 | + placement: "top", |
| 31 | + middleware: [ |
| 32 | + offset(6), |
| 33 | + flip(), |
| 34 | + shift(), |
| 35 | + ] |
| 36 | + }); |
| 37 | +
|
| 38 | + let showTooltip: boolean = false; |
| 39 | +</script> |
| 40 | +
|
| 41 | +<button |
| 42 | + on:mouseenter={() => showTooltip = true} |
| 43 | + on:mouseleave={() => showTooltip = false} |
| 44 | + use:floatingRef |
| 45 | +>Hover me</button> |
| 46 | +
|
| 47 | +{#if showTooltip} |
| 48 | + <div style="position:absolute" use:floatingContent> |
| 49 | + Tooltip |
| 50 | + </div> |
| 51 | +{/if} |
15 | 52 | ``` |
16 | 53 |
|
17 | | -## Developing |
| 54 | +## API |
18 | 55 |
|
19 | | -Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: |
| 56 | +### Setting Floating UI options |
20 | 57 |
|
21 | | -```bash |
22 | | -npm run dev |
| 58 | +Floating UI options can be set statically when creating the actions, or dynamically on the content action. |
23 | 59 |
|
24 | | -# or start the server and open the app in a new browser tab |
25 | | -npm run dev -- --open |
| 60 | +If both are set, then the dynamic options will be merged with the initial options. |
| 61 | + |
| 62 | +```svelte |
| 63 | +<script> |
| 64 | + // set once and no longer updated |
| 65 | + const [ floatingRef, floatingContent ] = createFloatingActions(initOptions); |
| 66 | +</script> |
| 67 | +
|
| 68 | +<!-- will be merged with initOptions --> |
| 69 | +<div use:floatingContent={ dynamicOptions }/> |
26 | 70 | ``` |
27 | 71 |
|
28 | | -## Building |
| 72 | +### Updating the Floating UI position |
29 | 73 |
|
30 | | -To create a production version of your app: |
| 74 | +The content element's position can be manually updated by using the third value returned by `createFloatingActions`. This method takes an optional options object which will be merged with the initial options. |
31 | 75 |
|
32 | | -```bash |
33 | | -npm run build |
| 76 | +```svelte |
| 77 | +<script> |
| 78 | + // Get update method |
| 79 | + const [ floatingRef, floatingContent, update] = createFloatingActions(initOptions); |
| 80 | +
|
| 81 | + update(updateOptions) |
| 82 | +</script> |
34 | 83 | ``` |
35 | 84 |
|
36 | | -You can preview the production build with `npm run preview`. |
| 85 | +### Applying custom styles on compute |
| 86 | + |
| 87 | +To apply styles manually, you can pass the `onComputed` option to `createFloatingActions`. This is a function that recieves a [`ComputePositionReturn`](https://floating-ui.com/docs/computeposition#return-value). This function is called every time the tooltip's position is computed. |
| 88 | + |
| 89 | +See [Arrow Middleware](#arrow-middleware) for an example on it's usage. |
| 90 | + |
| 91 | +## Arrow Middleware |
| 92 | + |
| 93 | +For convenience, a custom [Arrow middleware](https://floating-ui.com/docs/arrow) is provided. Rather than accepting an `HTMLElement`, this takes a `Writable<HTMLElement>`. Otherwise, this middleware works exactly as the regular Floating UI one, including needing to manually set the arrow styles. |
| 94 | + |
| 95 | +To set the styles, you can pass the [`onComputed`](#applying-custom-styles-on-compute) option. The below implementation is copied from the [Floating UI Tutorial](https://floating-ui.com/docs/tutorial#arrow-middleware). |
| 96 | + |
| 97 | +```svelte |
| 98 | +<script> |
| 99 | + import { writable } from "svelte/store"; |
| 100 | + import { arrow } from "svelte-floating-ui"; |
| 101 | +
|
| 102 | + const arrowRef = writable(null); |
| 103 | + const [ floatingRef, floatingContent, update] = createFloatingActions({ |
| 104 | + strategy: "absolute", |
| 105 | + placement: "bottom", |
| 106 | + middleware: [ |
| 107 | + arrow({ element: arrowRef }) |
| 108 | + ], |
| 109 | + onComputed({ placement, middlewareData }) { |
| 110 | + const { x, y } = middlewareData.arrow; |
| 111 | + const staticSide = { |
| 112 | + top: 'bottom', |
| 113 | + right: 'left', |
| 114 | + bottom: 'top', |
| 115 | + left: 'right', |
| 116 | + }[placement.split('-')[0]]; |
| 117 | +
|
| 118 | + Object.assign($arrowRef.style, { |
| 119 | + left: x != null ? `${x}px` : "", |
| 120 | + top: y != null ? `${y}px` : "", |
| 121 | + [staticSide]: "-4px" |
| 122 | + }); |
| 123 | + } |
| 124 | + }); |
| 125 | +</script> |
| 126 | +
|
| 127 | +<button |
| 128 | + on:mouseenter={() => showTooltip = true} |
| 129 | + on:mouseleave={() => showTooltip = false} |
| 130 | + use:floatingRef |
| 131 | +>Hover me</button> |
37 | 132 |
|
38 | | -> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. |
| 133 | +{#if showTooltip} |
| 134 | + <div class="tooltip" use:floatingContent> |
| 135 | + Tooltip this is some longer text than the button |
| 136 | + <div class="arrow" bind:this={$arrowRef} /> |
| 137 | + </div> |
| 138 | +{/if} |
| 139 | +``` |
0 commit comments