Skip to content

Commit bfa3069

Browse files
committed
feat: add special prop for passing refs to integrations
1 parent aec635a commit bfa3069

12 files changed

Lines changed: 62 additions & 57 deletions

File tree

README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,13 @@ import { useAdhesive } from '@adhesivejs/react';
7777
import { useRef } from 'react';
7878

7979
export function App() {
80-
const targetEl = useRef<HTMLElement>(null);
80+
const targetRef = useRef<HTMLElement>(null);
8181

82-
useAdhesive(targetEl, { position: 'top' });
82+
useAdhesive(targetRef, { position: 'top' });
8383

8484
return (
8585
<div>
86-
<header ref={targetEl}>This header will stick to the top</header>
86+
<header ref={targetRef}>This header will stick to the top</header>
8787

8888
<main>
8989
<p>Your main content here...</p>
@@ -122,9 +122,9 @@ import { AdhesiveContainer } from '@adhesivejs/vue';
122122
import { useAdhesive } from '@adhesivejs/vue';
123123
import { useTemplateRef } from 'vue';
124124
125-
const targetEl = useTemplateRef('target');
125+
const targetRef = useTemplateRef('target');
126126
127-
useAdhesive(targetEl, { position: 'top' });
127+
useAdhesive(targetRef, { position: 'top' });
128128
</script>
129129
130130
<template>
@@ -176,4 +176,3 @@ Contributions are welcome! Please feel free to submit a Pull Request.
176176
## 📄 License
177177

178178
This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details.
179-

packages/react/README.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,15 @@ import { useAdhesive, type AdhesivePosition } from '@adhesivejs/react';
6666
import { useRef, useState } from 'react';
6767

6868
export function App() {
69-
const targetEl = useRef<HTMLDivElement>(null);
70-
const boundingEl = useRef<HTMLDivElement>(null);
69+
const targetRef = useRef<HTMLDivElement>(null);
70+
const boundingRef = useRef<HTMLDivElement>(null);
7171
const [enabled, setEnabled] = useState(true);
7272
const [position, setPosition] = useState<AdhesivePosition>('top');
7373

7474
useAdhesive(
75-
targetEl,
75+
targetRef,
7676
{
77-
boundingEl,
77+
boundingRef,
7878
position,
7979
offset: 20,
8080
enabled,
@@ -85,7 +85,7 @@ export function App() {
8585
);
8686

8787
return (
88-
<div ref={boundingEl} style={{ height: '200vh' }}>
88+
<div ref={boundingRef} style={{ height: '200vh' }}>
8989
<button onClick={() => setEnabled(!enabled)}>
9090
{enabled ? 'Disable' : 'Enable'} Sticky
9191
</button>
@@ -94,7 +94,7 @@ export function App() {
9494
Switch to {position === 'top' ? 'bottom' : 'top'}
9595
</button>
9696

97-
<div ref={targetEl} className="sticky-element">
97+
<div ref={targetRef} className="sticky-element">
9898
<h2>Dynamic Sticky Element</h2>
9999
<p>Position: {position} | Enabled: {enabled ? 'Yes' : 'No'}</p>
100100
</div>
@@ -141,7 +141,8 @@ For more control over the sticky behavior.
141141

142142
| Option | Type | Default | Description |
143143
|--------|------|---------|-------------|
144-
| `boundingEl` | `React.RefObject` \| `string` | `undefined` | The element that defines the sticky boundaries |
144+
| `boundingRef` | `React.RefObject` \| `HTMLElement` \| `string` | `document.body` | The element that defines the sticky boundaries |
145+
| `boundingEl` | `HTMLElement` \| `string` | `document.body` | Alternative way to specify bounding element (for compatibility) |
145146
| `position` | `'top' \| 'bottom'` | `'top'` | Where the element should stick |
146147
| `offset` | `number` | `0` | Offset in pixels from the position |
147148
| `zIndex` | `number` | `1` | Z-index for the fixed element |

packages/react/src/components/AdhesiveContainer.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export type AdhesiveContainerProps = Partial<UseAdhesiveOptions> &
1616
* ```
1717
*/
1818
export function AdhesiveContainer({
19+
boundingRef,
1920
boundingEl,
2021
enabled = true,
2122
offset,
@@ -32,6 +33,7 @@ export function AdhesiveContainer({
3233

3334
const options = useMemo<UseAdhesiveOptions>(
3435
() => ({
36+
boundingRef,
3537
boundingEl,
3638
enabled,
3739
offset,
@@ -43,6 +45,7 @@ export function AdhesiveContainer({
4345
releasedClassName,
4446
}),
4547
[
48+
boundingRef,
4649
boundingEl,
4750
enabled,
4851
offset,

packages/react/src/hooks/useAdhesive.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@ import {
55
type MaybeElementOrSelectorRef,
66
} from "../utils/unrefElement.js";
77

8-
export type UseAdhesiveOptions = Partial<
9-
Omit<AdhesiveOptions, "targetEl" | "boundingEl">
10-
> & {
11-
boundingEl?: AdhesiveOptions["boundingEl"] | MaybeElementOrSelectorRef;
8+
export type UseAdhesiveOptions = Partial<Omit<AdhesiveOptions, "targetEl">> & {
9+
boundingRef?: MaybeElementOrSelectorRef;
1210
};
1311

1412
/**
@@ -27,17 +25,17 @@ export type UseAdhesiveOptions = Partial<
2725
* import { useAdhesive } from '@adhesivejs/react';
2826
*
2927
* function Component() {
30-
* const targetEl = useRef<HTMLDivElement>(null);
31-
* const boundingEl = useRef<HTMLDivElement>(null);
28+
* const targetRef = useRef<HTMLDivElement>(null);
29+
* const boundingRef = useRef<HTMLDivElement>(null);
3230
*
3331
* useAdhesive(
34-
* targetEl,
35-
* { boundingEl, position: 'top' }
32+
* targetRef,
33+
* { boundingRef, position: 'top' }
3634
* );
3735
*
3836
* return (
39-
* <div ref={boundingEl}>
40-
* <div ref={targetEl}>Sticky content</div>
37+
* <div ref={boundingRef}>
38+
* <div ref={targetRef}>Sticky content</div>
4139
* </div>
4240
* );
4341
* }
@@ -49,7 +47,8 @@ export function useAdhesive(
4947
) {
5048
function getValidatedOptions() {
5149
const targetEl = unrefElement(target);
52-
const boundingEl = unrefElement(options?.boundingEl);
50+
const boundingEl =
51+
unrefElement(options?.boundingRef) ?? options?.boundingEl;
5352

5453
if (!targetEl) {
5554
throw new Error("@adhesivejs/react: sticky element is not defined");

packages/react/src/utils/unrefElement.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import type { RefObject } from "react";
22

3-
type MaybeElementRefObject = RefObject<HTMLElement | HTMLDivElement | null>;
4-
53
export type MaybeElementOrSelectorRef =
6-
| MaybeElementRefObject
4+
| RefObject<HTMLElement | null>
75
| HTMLElement
86
| string
97
| null

packages/vue/README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,15 @@ import { AdhesiveContainer } from '@adhesivejs/vue';
7171
import { useAdhesive, type AdhesivePosition } from '@adhesivejs/vue';
7272
import { ref, useTemplateRef } from 'vue';
7373
74-
const targetEl = useTemplateRef('target');
75-
const boundingEl = useTemplateRef('bounding');
74+
const targetRef = useTemplateRef('target');
75+
const boundingRef = useTemplateRef('bounding');
7676
const enabled = ref(true);
7777
const position = ref<AdhesivePosition>('top');
7878
7979
useAdhesive(
80-
targetEl,
80+
targetRef,
8181
() => ({
82-
boundingEl: boundingEl.value,
82+
boundingRef: boundingRef.value,
8383
position: position.value,
8484
offset: 20,
8585
enabled: enabled.value,
@@ -148,7 +148,8 @@ For more control over the sticky behavior with full Vue reactivity support.
148148

149149
| Option | Type | Default | Description |
150150
|--------|------|---------|-------------|
151-
| `boundingEl` | `TemplateRef` \| `string` | `undefined` | The element that defines the sticky boundaries |
151+
| `boundingRef` | `TemplateRef` \| `HTMLElement` \| `string` | `document.body` | The element that defines the sticky boundaries |
152+
| `boundingEl` | `HTMLElement` \| `string` | `document.body` | Alternative way to specify bounding element (for compatibility) |
152153
| `position` | `'top' \| 'bottom'` | `'top'` | Where the element should stick |
153154
| `offset` | `number` | `0` | Offset in pixels from the position |
154155
| `zIndex` | `number` | `1` | Z-index for the fixed element |

packages/vue/src/components/AdhesiveContainer.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export default { name: "AdhesiveContainer" };
3535

3636
<script setup lang="ts">
3737
const {
38+
boundingRef,
3839
boundingEl,
3940
enabled = true,
4041
offset,
@@ -49,6 +50,7 @@ const {
4950
const targetRef = useTemplateRef("target");
5051
5152
const options = computed<UseAdhesiveOptions>(() => ({
53+
boundingRef,
5254
boundingEl,
5355
enabled,
5456
offset,

packages/vue/src/composables/useAdhesive.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,8 @@ import {
1111
type MaybeElementOrSelectorRef,
1212
} from "../utils/unrefElement.js";
1313

14-
export type UseAdhesiveOptions = Partial<
15-
Omit<AdhesiveOptions, "targetEl" | "boundingEl">
16-
> & {
17-
boundingEl?: AdhesiveOptions["boundingEl"] | MaybeElementOrSelectorRef;
14+
export type UseAdhesiveOptions = Partial<Omit<AdhesiveOptions, "targetEl">> & {
15+
boundingRef?: MaybeElementOrSelectorRef;
1816
};
1917

2018
/**
@@ -33,12 +31,12 @@ export type UseAdhesiveOptions = Partial<
3331
* import { useTemplateRef } from 'vue';
3432
* import { useAdhesive } from '@adhesivejs/vue';
3533
*
36-
* const targetEl = useTemplateRef('target');
37-
* const boundingEl = useTemplateRef('bounding');
34+
* const targetRef = useTemplateRef('target');
35+
* const boundingRef = useTemplateRef('bounding');
3836
*
3937
* useAdhesive(
40-
* targetEl,
41-
* () => ({ boundingEl: boundingEl.value, position: 'top' })
38+
* targetRef,
39+
* () => ({ boundingRef: boundingRef.value, position: 'top' })
4240
* );
4341
* </script>
4442
*
@@ -55,12 +53,12 @@ export type UseAdhesiveOptions = Partial<
5553
* import { ref } from 'vue';
5654
* import { useAdhesive } from '@adhesivejs/vue';
5755
*
58-
* const targetEl = useTemplateRef('target');
56+
* const targetRef = useTemplateRef('target');
5957
* const enabled = ref(true);
6058
* const offset = ref(10);
6159
*
6260
* // Reactive options
63-
* useAdhesive(targetEl, () => ({
61+
* useAdhesive(targetRef, () => ({
6462
* position: 'top',
6563
* enabled: enabled.value,
6664
* offset: offset.value,
@@ -76,7 +74,8 @@ export function useAdhesive(
7674
const optionsValue = toValue(options);
7775

7876
const targetEl = unrefElement(target);
79-
const boundingEl = unrefElement(optionsValue?.boundingEl);
77+
const boundingEl =
78+
unrefElement(optionsValue?.boundingRef) ?? optionsValue?.boundingEl;
8079

8180
if (!targetEl) {
8281
throw new Error("@adhesivejs/vue: sticky element is not defined");

playground/react/src/App.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ export function App() {
1313
const [enabled, setEnabled] = useState(true);
1414
const [position, setPosition] = useState<AdhesivePosition>("top");
1515

16-
const targetEl = useRef<HTMLDivElement>(null);
17-
const boundingEl = useRef<HTMLDivElement>(null);
16+
const targetRef = useRef<HTMLDivElement>(null);
17+
const boundingRef = useRef<HTMLDivElement>(null);
1818

19-
useAdhesive(targetEl, { boundingEl, enabled, position });
19+
useAdhesive(targetRef, { boundingRef, enabled, position });
2020

2121
return (
2222
<div>
@@ -31,8 +31,8 @@ export function App() {
3131
</button>
3232
<br />
3333
<br />
34-
<div ref={boundingEl}>
35-
<div ref={targetEl}>Sticky Element</div>
34+
<div ref={boundingRef}>
35+
<div ref={targetRef}>Sticky Element</div>
3636
<a href="https://vite.dev" target="_blank" rel="noopener noreferrer">
3737
<img src={viteLogo} className="logo" alt="Vite logo" />
3838
</a>

playground/vue/src/App.vue

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ const count = ref(0);
1010
const enabled = ref(true);
1111
const position = ref<AdhesivePosition>("top");
1212
13-
const targetEl = useTemplateRef("target");
14-
const boundingEl = useTemplateRef("bounding");
13+
const targetRef = useTemplateRef("target");
14+
const boundingRef = useTemplateRef("bounding");
1515
16-
useAdhesive(targetEl, () => ({
17-
boundingEl: boundingEl.value,
16+
useAdhesive(targetRef, () => ({
17+
boundingRef: boundingRef.value,
1818
enabled: enabled.value,
1919
position: position.value,
2020
}));
@@ -25,7 +25,10 @@ useAdhesive(targetEl, () => ({
2525
<button type="button" @click="enabled = !enabled">
2626
{{ enabled ? "Disable" : "Enable" }} Sticky
2727
</button>
28-
<button type="button" @click="position === 'top' ? 'bottom' : 'top'">
28+
<button
29+
type="button"
30+
@click="position = position === 'top' ? 'bottom' : 'top'"
31+
>
2932
Switch to {{ position === "top" ? "bottom" : "top" }}
3033
</button>
3134
<br />

0 commit comments

Comments
 (0)