Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .oxlintrc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"plugins": ["vitest", "import", "promise", "regex", "jsdoc"],
"plugins": ["vitest", "import", "promise", "jsdoc"],
"rules": {
"func-style": ["warn", "declaration"],
"no-floating-promises": "allow",
Expand Down
111 changes: 108 additions & 3 deletions packages/docs/components/Hoverable/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,124 @@ title: Hoverable examples

## Default

In this example, we showcase the default behaviour as well as [the `reversed`](./js-api.md#reversed) and [`contained` options](./js-api.md#contained).
Moves the target relative to the pointer inside rectangular bounds.

<llm-exclude>
<PreviewPlayground
:html="() => import('./stories/app.twig')"
:html="() => import('./stories/default.twig')"
:script="() => import('./stories/app.js?raw')"
/>
</llm-exclude>
<llm-only>

:::code-group

<<< ./stories/app.twig
<<< ./stories/default.twig
<<< ./stories/app.js

:::

</llm-only>

## Reversed

Inverts the movement direction for a counter-motion effect.

<llm-exclude>
<PreviewPlayground
:html="() => import('./stories/reversed.twig')"
:script="() => import('./stories/app.js?raw')"
/>
</llm-exclude>
<llm-only>

:::code-group

<<< ./stories/reversed.twig
<<< ./stories/app.js

:::

</llm-only>

## Contained

Stops updating when the pointer leaves the root element.

<llm-exclude>
<PreviewPlayground
:html="() => import('./stories/contained.twig')"
:script="() => import('./stories/app.js?raw')"
/>
</llm-exclude>
<llm-only>

:::code-group

<<< ./stories/contained.twig
<<< ./stories/app.js

:::

</llm-only>

## Reversed and contained

Combines reversed motion with contained pointer tracking.

<llm-exclude>
<PreviewPlayground
:html="() => import('./stories/reversed-contained.twig')"
:script="() => import('./stories/app.js?raw')"
/>
</llm-exclude>
<llm-only>

:::code-group

<<< ./stories/reversed-contained.twig
<<< ./stories/app.js

:::

</llm-only>

## Circle shape

Constrains movement to an inscribed circular area.

<llm-exclude>
<PreviewPlayground
:html="() => import('./stories/circle.twig')"
:script="() => import('./stories/app.js?raw')"
/>
</llm-exclude>
<llm-only>

:::code-group

<<< ./stories/circle.twig
<<< ./stories/app.js

:::

</llm-only>

## Ellipse shape

Constrains movement to an inscribed elliptical area.

<llm-exclude>
<PreviewPlayground
:html="() => import('./stories/ellipse.twig')"
:script="() => import('./stories/app.js?raw')"
/>
</llm-exclude>
<llm-only>

:::code-group

<<< ./stories/ellipse.twig
<<< ./stories/app.js

:::
Expand Down
21 changes: 20 additions & 1 deletion packages/docs/components/Hoverable/js-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The `Hoverable` component uses the [`withRelativePointer` decorator](https://js-
### `sensitivity`

- Type: `number`
- Default: `0.5`
- Default: `0.1`

A number between in the range `0–1` used to smoothen the transition between each position.

Expand All @@ -29,6 +29,13 @@ Use this option to reverse the movement of the target.

Use this option to stop moving the target element when the pointer has leaved the root element.

### `shape`

- Type: `'rect' | 'circle' | 'ellipse'`
- Default: `'rect'`

Use this option to constrain the target movement to an inscribed shape instead of the default rectangular bounds.

## Properties

### `props`
Expand All @@ -37,6 +44,16 @@ Use this option to stop moving the target element when the pointer has leaved th

The values used to calculate and render the position of the target element.

## Methods

### `constrainPosition`

- Signature: `(x: number, y: number, bounds = this.bounds) => { x: number, y: number }`

Constrains the given position to the configured bounding shape.

By default, this method supports the built-in `rect`, `circle` and `ellipse` shapes. You can override it in a custom component to implement more advanced constraints.

## Getters

### `target`
Expand All @@ -57,3 +74,5 @@ The element used to calculate the bound limits.

- Return: `{ yMin: number, yMax: number, xMin: number, xMax: number }`
- Default: the minimum and maximum position for the `target` element to stay in the `parent` bounds

The `shape` option uses these bounds as its base rectangle and constrains the target to either that rectangle, an inscribed circle, or an inscribed ellipse.
111 changes: 97 additions & 14 deletions packages/docs/components/Hoverable/stories/app.twig
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
<div class="grid gap-10 p-10">
<div class="flex flex-col s:flex-row items-center justify-center w-full gap-10">
<div
class="flex flex-col s:flex-row items-center justify-center w-full gap-10">
<div class="grid gap-2">
<p>Default</p>
<div data-component="Hoverable"
<p>
Default
</p>
<div
data-component="Hoverable"
class="relative w-64 h-64 overflow-hidden bg-gray-300">
<div class="z-10 absolute inset-0 ring"></div>
<div data-ref="target"
<div
data-ref="target"
class="absolute w-[120%] h-[120%] self-center justify-self-center pointer-events-none">
{% include '@ui/Figure/Figure.twig' with {
src: 'https://picsum.photos/600/600',
Expand All @@ -28,12 +33,16 @@
</div>

<div class="grid gap-2">
<p>Reversed</p>
<div data-component="Hoverable"
<p>
Reversed
</p>
<div
data-component="Hoverable"
data-option-reversed
class="relative w-64 h-64 overflow-hidden bg-gray-300">
<div class="z-10 absolute inset-0 ring"></div>
<div data-ref="target"
<div
data-ref="target"
class="absolute w-[120%] h-[120%] self-center justify-self-center pointer-events-none">
{% include '@ui/Figure/Figure.twig' with {
src: 'https://picsum.photos/600/600',
Expand All @@ -55,14 +64,19 @@
</div>
</div>
</div>
<div class="flex flex-col s:flex-row items-center justify-center w-full gap-10">
<div
class="flex flex-col s:flex-row items-center justify-center w-full gap-10">
<div class="grid gap-2">
<p>Contained</p>
<div data-component="Hoverable"
<p>
Contained
</p>
<div
data-component="Hoverable"
data-option-contained
class="relative w-64 h-64 overflow-hidden bg-gray-300">
<div class="z-10 absolute inset-0 ring"></div>
<div data-ref="target"
<div
data-ref="target"
class="absolute w-[120%] h-[120%] self-center justify-self-center pointer-events-none">
{% include '@ui/Figure/Figure.twig' with {
src: 'https://picsum.photos/600/600',
Expand All @@ -84,13 +98,17 @@
</div>
</div>
<div class="grid gap-2">
<p>Reversed & Contained</p>
<div data-component="Hoverable"
<p>
Reversed & Contained
</p>
<div
data-component="Hoverable"
data-option-contained
data-option-reversed
class="relative w-64 h-64 overflow-hidden bg-gray-300">
<div class="z-10 absolute inset-0 ring"></div>
<div data-ref="target"
<div
data-ref="target"
class="absolute w-[120%] h-[120%] self-center justify-self-center pointer-events-none">
{% include '@ui/Figure/Figure.twig' with {
src: 'https://picsum.photos/600/600',
Expand All @@ -112,4 +130,69 @@
</div>
</div>
</div>
<div
class="flex flex-col s:flex-row items-center justify-center w-full gap-10">
<div class="grid gap-2">
<p>
Circle
</p>
<div
data-component="Hoverable"
data-option-shape="circle"
class="relative w-64 h-64 overflow-hidden rounded-full bg-gray-300">
<div class="z-10 absolute inset-0 rounded-full ring"></div>
<div
data-ref="target"
class="absolute w-[120%] h-[120%] self-center justify-self-center pointer-events-none">
{% include '@ui/Figure/Figure.twig' with {
src: 'https://picsum.photos/600/600',
width: 600,
height: 600,
fit: 'cover',
absolute: true,
attr: {
data_option_enter_from: 'opacity-0'
},
inner_attr: {
class: 'bg-vp-bg rounded-full overflow-hidden'
},
img_attr: {
class: 'opacity-0 transform'
}
} only %}
</div>
</div>
</div>
<div class="grid gap-2">
<p>
Ellipse
</p>
<div
data-component="Hoverable"
data-option-shape="ellipse"
class="relative w-80 h-52 overflow-hidden rounded-[9999px] bg-gray-300">
<div class="z-10 absolute inset-0 rounded-[9999px] ring"></div>
<div
data-ref="target"
class="absolute w-[120%] h-[120%] self-center justify-self-center pointer-events-none">
{% include '@ui/Figure/Figure.twig' with {
src: 'https://picsum.photos/600/600',
width: 600,
height: 600,
fit: 'cover',
absolute: true,
attr: {
data_option_enter_from: 'opacity-0'
},
inner_attr: {
class: 'bg-vp-bg rounded-[9999px] overflow-hidden'
},
img_attr: {
class: 'opacity-0 transform'
}
} only %}
</div>
</div>
</div>
</div>
</div>
Loading
Loading