Skip to content

Commit 91e993e

Browse files
committed
feat(core): add data attr for adhesive status
1 parent 79cf74c commit 91e993e

File tree

3 files changed

+51
-0
lines changed

3 files changed

+51
-0
lines changed

packages/core/README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,26 @@ adhesive.cleanup();
120120
#### Static Methods
121121

122122
- `Adhesive.create(options)` - Create and initialize in one call
123+
124+
#### Markup & styling hooks
125+
126+
Adhesive wraps your target element in two divs. The outer wrapper receives a data attribute reflecting the current status so you can style with attribute selectors or utilities:
127+
128+
- `data-adhesive-status="initial"`
129+
- `data-adhesive-status="fixed"`
130+
- `data-adhesive-status="relative"`
131+
132+
Example CSS:
133+
134+
```css
135+
[data-adhesive-status="fixed"] { box-shadow: 0 1px 3px rgba(0,0,0,.1); }
136+
[data-adhesive-status="relative"] { opacity: .95; }
137+
```
138+
139+
Tailwind/UnoCSS example (using arbitrary variants):
140+
141+
```html
142+
<div id="sticky-element">
143+
<span class="[[data-adhesive-status=initial]_&]:text-red-500 [[data-adhesive-status=fixed]_&]:text-green-500 [[data-adhesive-status=relative]_&]:text-blue-500">Dynamic styling based on status</span>
144+
</div>
145+
```

packages/core/src/lib/Adhesive.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,9 @@ const expectNever = (value: never): never => {
261261
* Adhesive.create({ targetEl: '#target-element' });
262262
* ```
263263
*
264+
* Styling hook: the outer wrapper gets `data-adhesive-status` with values
265+
* `initial` | `fixed` | `relative` to enable attribute-based styling.
266+
*
264267
* @example Advanced configuration
265268
* ```ts
266269
* Adhesive.create({
@@ -808,6 +811,7 @@ export class Adhesive {
808811

809812
overwriteClassNames(this.#outerWrapper, outerClasses);
810813
overwriteClassNames(this.#innerWrapper, innerClasses);
814+
this.#outerWrapper.dataset.adhesiveStatus = this.#state.status;
811815
}
812816

813817
#rerender(): void {

test/unit/core.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,30 @@ describe("Core", () => {
744744
const outerDomClassName = outerDomElement.className;
745745
expect(outerDomClassName).toBe(`${outerClassName} adhesive--initial`);
746746
});
747+
748+
it("sets data attribute for current status on outer wrapper", async () => {
749+
const adhesive = createInitializedAdhesive({
750+
boundingEl,
751+
offset: 10,
752+
position: "top",
753+
});
754+
755+
const innerEl = targetEl.parentElement!;
756+
const outerEl = innerEl.parentElement!;
757+
758+
// Initial state
759+
expect(outerEl.dataset.adhesiveStatus).toBe("initial");
760+
761+
// Fixed state
762+
await simulateScrollToPosition(200);
763+
expect(outerEl.dataset.adhesiveStatus).toBe("fixed");
764+
765+
// Relative state at boundary
766+
await simulateScrollToPosition(2000);
767+
expect(outerEl.dataset.adhesiveStatus).toBe("relative");
768+
769+
adhesive.cleanup();
770+
});
747771
});
748772
});
749773

0 commit comments

Comments
 (0)