use-move
Handles move behavior over any element, use to build custom sliders, color pickers, etc.
Import
Source
Docs
Package
Usage
use-move
handles move behavior over any element:
Values { x: 20, y: 60 }
import { useState } from 'react';
import { Group, Text, Code, rem } from '@mantine/core';
import { useMove } from '@mantine/hooks';
function Demo() {
const [value, setValue] = useState({ x: 0.2, y: 0.6 });
const { ref, active } = useMove(setValue);
return (
<>
<Group justify="center">
<div
ref={ref}
style={{
width: rem(400),
height: rem(120),
backgroundColor: 'var(--mantine-color-blue-light)',
position: 'relative',
}}
>
<div
style={{
position: 'absolute',
left: `calc(${value.x * 100}% - ${rem(8)})`,
top: `calc(${value.y * 100}% - ${rem(8)})`,
width: rem(16),
height: rem(16),
backgroundColor: active ? 'var(--mantine-color-teal-7)' : 'var(--mantine-color-blue-7)',
}}
/>
</div>
</Group>
<Text ta="center" mt="sm">
Values <Code>{`{ x: ${Math.round(value.x * 100)}, y: ${Math.round(value.y * 100)} }`}</Code>
</Text>
</>
);
}
API
The hook accepts a callback that is called when user moves pressed mouse over the given element
and returns an object with ref
and active state:
const {
ref, // -> pass ref to target element
active, // -> is user changing something right now?
} = useMove(({ x, y }) => setValue({ x, y }));
x
and y
values are always between 0
and 1
, you can use them to calculate value in your boundaries.
Horizontal slider
You can ignore changes for one of the axis:
Value: 20
import { useState } from 'react';
import { Group, Text, rem } from '@mantine/core';
import { useMove } from '@mantine/hooks';
function Demo() {
const [value, setValue] = useState(0.2);
const { ref } = useMove(({ x }) => setValue(x));
return (
<>
<Group justify="center">
<div
ref={ref}
style={{
width: rem(400),
height: rem(16),
backgroundColor: 'var(--mantine-color-blue-light)',
position: 'relative',
}}
>
{/* Filled bar */}
<div
style={{
width: `${value * 100}%`,
height: rem(16),
backgroundColor: 'var(--mantine-color-blue-filled)',
}}
/>
{/* Thumb */}
<div
style={{
position: 'absolute',
left: `calc(${value * 100}% - ${rem(8)})`,
top: 0,
width: rem(16),
height: rem(16),
backgroundColor: 'var(--mantine-color-blue-7)',
}}
/>
</div>
</Group>
<Text ta="center" mt="sm">
Value: {Math.round(value * 100)}
</Text>
</>
);
}
Vertical slider
Moving the slider down increases the value, to reverse that set value to 1 - y
in your setValue
function:
Value: 20
import { useState } from 'react';
import { Group, Text, rem } from '@mantine/core';
import { useMove } from '@mantine/hooks';
function Demo() {
const [value, setValue] = useState(0.2);
const { ref } = useMove(({ y }) => setValue(1 - y));
return (
<>
<Group justify="center">
<div
ref={ref}
style={{
width: rem(16),
height: rem(120),
backgroundColor: 'var(--mantine-color-blue-light)',
position: 'relative',
}}
>
{/* Filled bar */}
<div
style={{
position: 'absolute',
bottom: 0,
height: `${value * 100}%`,
width: rem(16),
backgroundColor: 'var(--mantine-color-blue-filled)',
}}
/>
{/* Thumb */}
<div
style={{
position: 'absolute',
bottom: `calc(${value * 100}% - ${rem(8)})`,
left: 0,
width: rem(16),
height: rem(16),
backgroundColor: 'var(--mantine-color-blue-7)',
}}
/>
</div>
</Group>
<Text ta="center" mt="sm">
Value: {Math.round(value * 100)}
</Text>
</>
);
}
Color picker
import { useState } from 'react';
import { rem } from '@mantine/core';
import { useMove } from '@mantine/hooks';
function Demo() {
const [value, setValue] = useState({ x: 0.2, y: 0.6 });
const { ref } = useMove(setValue);
return (
<div>
<div
ref={ref}
style={{
width: rem(300),
height: rem(150),
backgroundColor: 'red',
position: 'relative',
}}
>
{/* Gradient overlays */}
<div
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundImage: 'linear-gradient(90deg, #fff, transparent)',
}}
/>
<div
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundImage: 'linear-gradient(0deg, #000, transparent)',
}}
/>
{/* Thumb */}
<div
style={{
position: 'absolute',
left: `calc(${value.x * 100}% - ${rem(8)})`,
top: `calc(${value.y * 100}% - ${rem(8)})`,
width: rem(16),
height: rem(16),
border: `${rem(2)} solid #fff`,
borderRadius: rem(16),
}}
/>
</div>
</div>
);
}
Definition
function useMove<T extends HTMLElement = HTMLDivElement>(
onChange: (value: UseMovePosition) => void,
handlers?: useMoveHandlers,
dir?: 'ltr' | 'rtl'
): {
ref: MutableRefObject<T>;
active: boolean;
};
Welcome to Mantine, React components library that you always wished for
Build fully functional accessible web applications faster than ever