Skip to content

Commit 2688341

Browse files
authored
Merge pull request #48 from skeletonlabs/dev
Merge for release May 6, 2024
2 parents 16deaed + accc3fd commit 2688341

40 files changed

+5530
-4101
lines changed

.changeset/beige-flies-mate.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@skeletonlabs/floating-ui-svelte": minor
3+
---
4+
5+
Added `useRole` hook

.changeset/config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"fixed": [],
66
"linked": [],
77
"access": "restricted",
8-
"baseBranch": "main",
8+
"baseBranch": "dev",
99
"updateInternalDependencies": "patch",
1010
"ignore": []
1111
}

.changeset/curvy-snakes-tickle.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@skeletonlabs/floating-ui-svelte": minor
3+
---
4+
5+
Added the `useHover` hook

.changeset/nine-hounds-flow.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@skeletonlabs/floating-ui-svelte": minor
3+
---
4+
5+
feature: added the FloatingArrow component

.changeset/red-cobras-unite.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@skeletonlabs/floating-ui-svelte": minor
3+
---
4+
5+
Added the `useInteractions` hook

.eslintrc.cjs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,19 @@ module.exports = {
2727
parser: '@typescript-eslint/parser'
2828
}
2929
}
30-
]
30+
],
31+
rules: {
32+
'@typescript-eslint/no-unused-vars': [
33+
'error',
34+
{
35+
args: 'all',
36+
argsIgnorePattern: '^_',
37+
caughtErrors: 'all',
38+
caughtErrorsIgnorePattern: '^_',
39+
destructuredArrayIgnorePattern: '^_',
40+
varsIgnorePattern: '^_',
41+
ignoreRestSiblings: true
42+
}
43+
]
44+
}
3145
};

.prettierignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ pnpm-lock.yaml
33
package-lock.json
44
yarn.lock
55
/coverage
6+
**/*.mdx
7+
**/*.md

README.md

Lines changed: 244 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,49 +2,269 @@
22

33
A Floating UI wrapper for Svelte.
44

5-
## Attribution
5+
## Installation
66

7-
This project is maintained by [Hugo Korte](https://github.com/Hugos68), [Skeleton Labs](https://www.skeletonlabs.co/), and the [Svelte](https://svelte.dev/) community. Based on the amazing work by [Floating UI](https://github.com/floating-ui/floating-ui).
7+
```bash
8+
npm install @skeletonlabs/floating-ui-svelte
9+
# pnpm install @skeletonlabs/floating-ui-svelte
10+
# yarn install @skeletonlabs/floating-ui-svelte
11+
# bun install @skeletonlabs/floating-ui-svelte
12+
```
813

9-
## Contributing
14+
## Usage
1015

11-
### Developing
16+
### Making elements "float"
1217

13-
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
18+
We want it to float on top of the UI though, so it doesn’t disrupt the flow of the document. Add this class to all floating elements. Note that Floating UI does not have opinions about how your elements stack on the z-axis.
1419

15-
```bash
16-
npm run dev
20+
```css
21+
.floating {
22+
width: max-content;
23+
position: absolute;
24+
top: 0;
25+
left: 0;
26+
}
1727

18-
# or start the server and open the app in a new browser tab
19-
npm run dev -- --open
2028
```
2129

22-
Everything inside `src/lib` is part of your library, everything inside `src/routes` can be used as a showcase or preview app.
30+
### The Basics
2331

24-
### Building
32+
Import the desired hook or component from floating-ui-svelte. [View each example](https://floating-ui-svelte.vercel.app/) for additional guidance.
2533

26-
To build your library:
34+
```js
35+
import { useFloating, type UseFloatingOptions } from '@skeletonlabs/floating-ui-svelte';
2736

28-
```bash
29-
npm run package
37+
const options: UseFloatingOptions = { /* ... */ };
38+
const floating = useFloating(options);
3039
```
3140

32-
To create a production version of your showcase app:
41+
## API
3342

34-
```bash
35-
npm run build
43+
### useFloating
44+
45+
The `useFloating` Svelte hook acts as a controller for all other Floating UI Svelte features. It handles positioning your floating elements (tooltips, popovers, etc.) relative to an anchored element. Automatically calculates the best placement and updates it as needed, providing access to properties for position and style.
46+
47+
#### Usage
48+
49+
```html
50+
<script lang="ts">
51+
import { useFloating } from '@skeletonlabs/floating-ui-svelte';
52+
53+
const elements: { reference: HTMLElement | null; floating: HTMLElement | null } = $state({ reference: null, floating: null });
54+
const floating = useFloating({ elements });
55+
</script>
56+
57+
<button bind:this="{elements.reference}">Reference</button>
58+
<div bind:this="{elements.floating}" style="{floating.floatingStyles}" class="floating">Floating</div>
3659
```
3760

38-
You can preview the production build with `npm run preview`.
61+
> [!WARNING]
62+
> Destructured variables are not supported as this would break reactivity.
3963
40-
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
64+
#### Options
4165

42-
### Publishing
66+
| Property | Description | Type | Default Value |
67+
| -------- | ----------- | ---- | ------------- |
68+
| open | Represents the open/close state of the floating element. | boolean | true |
69+
| onOpenChange | Event handler that can be invoked whenever the open state changes. | (open: boolean, event?: Event, reason?: OpenChangeReason) => void | - |
70+
| placement | Where to place the floating element relative to its reference element. | Placement | 'bottom' |
71+
| strategy | The type of CSS position property to use. | Strategy | 'absolute' |
72+
| middleware | Supports all [Floating UI middleware](https://floating-ui.com/docs/middleware). | Array<Middleware \| undefined \| null \| false> | undefined |
73+
| transform | Whether to use `transform` instead of `top` and `left` styles to position the floating element (`floatingStyles`). | boolean | true |
74+
| elements | The reference and floating elements. | FloatingElements | - |
75+
| whileElementsMounted | Callback to handle mounting/unmounting of the elements. | (reference: ReferenceElement, floating: FloatingElement, update: () => void) => () => void | - |
4376

44-
Go into the `package.json` and give your package the desired name through the `"name"` option. Also consider adding a `"license"` field and point it to a `LICENSE` file which you can create from a template (one popular option is the [MIT license](https://opensource.org/license/mit/)).
77+
#### Return Value
4578

46-
To publish your library to [npm](https://www.npmjs.com):
79+
| Property | Description | Type |
80+
| -------- | ----------- | ---- |
81+
| x | The x-coord of the floating element. | number |
82+
| y | The y-coord of the floating element. | number |
83+
| placement | The stateful placement, which can be different from the initial `placement` passed as options. | Placement |
84+
| strategy | The stateful strategy, which can be different from the initial `strategy` passed as options. | Strategy |
85+
| middlewareData | Additional data from middleware. | MiddlewareData |
86+
| isPositioned | The boolean that let you know if the floating element has been positioned. | boolean |
87+
| floatingStyles | CSS styles to apply to the floating element to position it. | string |
88+
| update | The function to update floating position manually. | () => void |
89+
| context | Context object containing internal logic to alter the behavior of the floating element. | FloatingContext |
4790

48-
```bash
49-
npm publish
91+
### useInteractions
92+
93+
The `useInteractions` Svelte hook allows you to consume multiple interactions. It ensures that event listeners from different hooks are properly registered instead of being overruled by one another.
94+
95+
#### Usage
96+
97+
```html
98+
<script>
99+
import { useFloating, useInteractions, useHover, useFocus } from '@skeletonlabs/floating-ui-svelte';
100+
101+
const floating = useFloating();
102+
103+
const hover = useHover(floating.context);
104+
const focus = useFocus(floating.context);
105+
106+
const interactions = useInteractions([hover, focus]);
107+
</script>
108+
109+
<div {...interactions.getReferenceProps()}>Reference</div>
110+
<div {...interactions.getFloatingProps()}>Floating</div>
111+
```
112+
113+
If you want to apply an event handler the an element that is using a props getter make sure to pass them through the getter instead of applying them directly:
114+
```diff
115+
- <div {...interactions.getReferenceProps()} onclick={/* ... */}>Reference</div>
116+
+ <div {...interactions.getReferenceProps({ onclick: /* ... */})}>Reference</div>
117+
```
118+
This will ensure all event handlers will be registered rather being overruled by eachother.
119+
120+
#### Return Value
121+
122+
| Property | Description | Type |
123+
| -------- | ----------- | ---- |
124+
| getReferenceProps | The merged attributes for the `reference` element. | (userProps?: HTMLAttributes<Element>) => Record<string, unknown> |
125+
| getFloatingProps | The merged attributes for the `floating` element. | (userProps?: HTMLAttributes<Element>) => Record<string, unknown> |
126+
| getItemProps | The merged attributes for when dealing with a list inside the `floating` element. | (userProps?: HTMLAttributes<Element> & ExtendedUserProps) => Record<string, unknown> |
127+
128+
### useHover
129+
130+
#### Usage
131+
132+
```html
133+
<script>
134+
import { useFloating, useInteractions, useHover } from '@skeletonlabs/floating-ui-svelte';
135+
136+
const floating = useFloating();
137+
const hover = useHover(floating.context);
138+
const interactions = useInteractions([hover]);
139+
</script>
140+
141+
<button {...interactions.getReferenceProps()}>Reference</button>
142+
<div {...interactions.getFloatingProps()}>Tooltip</div>
143+
```
144+
145+
#### Options
146+
147+
| Property | Description | Type | Default Value |
148+
| -------- | ----------- | ---- | ------------- |
149+
| enabled | Enables the hook. | boolean | true |
150+
| mouseOnly | Only allow pointers of type mouse to trigger the hover (thus excluding pens and touchscreens). | boolean | false |
151+
| delay | Time in ms that will delay the change of the open state. Also accepts an object with open and close properties for finer grained control. | number | 0 |
152+
| restMs | Time in ms that the pointer must rest on the reference element before the open state is set to true. | number | 0 |
153+
| move | Whether moving the pointer over the floating element will open it, without a regular hover event required. | boolean | true |
154+
| handleClose | Callback to handle the closing of the floating element. | HandleCloseFn | null |
155+
156+
### useFocus
157+
158+
(tbd)
159+
160+
### useClick
161+
162+
(tbd)
163+
164+
### useRole
165+
166+
#### Usage
167+
168+
```html
169+
<script>
170+
import { useFloating, useInteractions, useRole } from '@skeletonlabs/floating-ui-svelte';
171+
172+
const floating = useFloating();
173+
const role = useRole(floating.context, { role: 'tooltip' });
174+
const interactions = useInteractions([role]);
175+
</script>
176+
177+
<button {...interactions.getReferenceProps()}>Reference</button>
178+
<div {...interactions.getFloatingProps()}>Tooltip</div>
50179
```
180+
181+
#### Options
182+
183+
| Property | Description | Type | Default Value |
184+
| -------- | ----------- | ---- | ------------- |
185+
| enabled | Enables the interaction | boolean | true |
186+
| role | The role that the floating element should be | [AriaRole](https://floating-ui.com/docs/useRole#native-roles) \| [ComponentRole](https://floating-ui.com/docs/useRole#component-roles) | 'dialog' |
187+
188+
### useDismiss
189+
190+
(tbd)
191+
192+
### useTransition
193+
194+
(tbd)
195+
196+
### FloatingArrow
197+
198+
Renders a customizable `<svg>` pointing arrow triangle inside the floating element that gets automatically positioned.
199+
200+
```html
201+
<script lang="ts">
202+
import { arrow, useFloating, FloatingArrow, autoUpdate, offset } from '$lib/index.js';
203+
204+
let arrowRef: HTMLElement | null = $state(null);
205+
206+
const elements: { reference: HTMLElement | null; floating: HTMLElement | null } = $state({
207+
reference: null,
208+
floating: null
209+
});
210+
211+
const floating = useFloating({
212+
elements,
213+
get middleware() {
214+
return [
215+
offset(10),
216+
arrowRef && arrow({ element: arrowRef })
217+
];
218+
}
219+
});
220+
</script>
221+
222+
<button bind:this={elements.reference}>Reference</button>
223+
<div bind:this={elements.floating} style={floating.floatingStyles} class="floating">
224+
<div>Floating</div>
225+
<FloatingArrow
226+
bind:ref={arrowRef}
227+
context={floating.context}
228+
classes="fill-surface-500"
229+
/>
230+
</div>
231+
```
232+
233+
#### Props
234+
235+
| Prop | Description | Default | Type |
236+
| -------- | ----------- | ---- | ---- |
237+
| ref* | Binded element reference. | - | HTMLElement, null |
238+
| context* | The context object returned from useFloating(). | - | FloatingContext |
239+
| width | The width of the arrow. | `14` | number |
240+
| height | The height of the arrow. | `7` | number |
241+
| tipRadius | The radius (rounding) of the arrow tip. | `0` (sharp) | number |
242+
| staticOffset | A static offset override of the arrow from the floating element edge. Often desirable if the floating element is smaller than the reference element along the relevant axis and has an edge alignment (`start`/`end`). | `undefined` (use dynamic path) | string, number, null |
243+
| d | A custom path for the arrow. Useful if you want fancy rounding. The path should be inside a square SVG and placed at the `bottom` of it. The path is designed for the 'bottom' placement, which will be rotated for other placements. | `"black"` (browser default) | string |
244+
| fill | The color of the arrow. | xxx | string |
245+
| stroke | The stroke (border) color of the arrow. This must match (or be less than) the floating element’s border width. | `"none"` | string |
246+
| strokeWidth | The stroke (border) width of the arrow. | `0` | number |
247+
248+
#### Utility Classes and Styles
249+
250+
Provide artibrary utility classes using the standard attribute.
251+
252+
```html
253+
<FloatingArrow class="fill-white" />
254+
```
255+
256+
### FloatingOverlay
257+
258+
(tbd)
259+
260+
### FloatingFocusManager
261+
262+
(tbd)
263+
264+
## Attribution
265+
266+
Based on [Floating UI](https://github.com/floating-ui/floating-ui) and [Floating UI React](https://floating-ui.com/docs/react). Maintained by [Hugo Korte](https://github.com/Hugos68), [Skeleton Labs](https://www.skeletonlabs.co/), and the [Svelte community](https://svelte.dev/).
267+
268+
## License
269+
270+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
"!dist/**/*.spec.*"
2929
],
3030
"dependencies": {
31-
"@floating-ui/dom": "^1.6.3"
31+
"@floating-ui/dom": "^1.6.3",
32+
"@floating-ui/utils": "^0.2.2"
3233
},
3334
"peerDependencies": {
3435
"svelte": "^5.0.0-next.1"
@@ -40,6 +41,7 @@
4041
"@sveltejs/package": "^2.0.0",
4142
"@sveltejs/vite-plugin-svelte": "^3.0.0",
4243
"@testing-library/jest-dom": "^6.4.2",
44+
"@testing-library/svelte": "^5.1.0",
4345
"@types/eslint": "^8.56.0",
4446
"@typescript-eslint/eslint-plugin": "^7.0.0",
4547
"@typescript-eslint/parser": "^7.0.0",

0 commit comments

Comments
 (0)