pl-fe: Allow adjusting interface size

Signed-off-by: Nicole Mikołajczyk <git@mkljczk.pl>
This commit is contained in:
Nicole Mikołajczyk
2025-05-22 17:55:57 +02:00
parent b2c7028e27
commit bc675bbf49
7 changed files with 114 additions and 9 deletions

View File

@@ -59,12 +59,15 @@ const Avatar = (props: IAvatar) => {
}).catch(() => setColor(undefined));
}, [src, isCat]);
const style: React.CSSProperties = React.useMemo(() => ({
width: size,
height: size,
fontSize: size,
color,
}), [size, color]);
const style: React.CSSProperties = React.useMemo(() => {
const value = `${size / 16}rem`;
return {
width: value,
height: value,
fontSize: value,
color,
};
}, [size, color]);
if (disableUserProvidedMedia) {
if (isAvatarMissing || !alt || isDefaultAvatar(src)) return null;

View File

@@ -0,0 +1,81 @@
import throttle from 'lodash/throttle';
import React, { useRef } from 'react';
import { getPointerPosition } from 'pl-fe/features/video';
interface IStepSlider {
/** Value between 0 and the amount of steps minus one. */
value: number;
/** Steps available in the slider. */
steps: number;
/** Callback when the value changes. */
onChange(value: number): void;
}
/** Slider allowing selecting integers in a given range. */
const StepSlider: React.FC<IStepSlider> = ({ value, steps, onChange }) => {
const node = useRef<HTMLDivElement>(null);
const handleMouseDown: React.MouseEventHandler = e => {
document.addEventListener('mousemove', handleMouseSlide, true);
document.addEventListener('mouseup', handleMouseUp, true);
document.addEventListener('touchmove', handleMouseSlide, true);
document.addEventListener('touchend', handleMouseUp, true);
handleMouseSlide(e);
e.preventDefault();
e.stopPropagation();
};
const handleMouseUp = () => {
document.removeEventListener('mousemove', handleMouseSlide, true);
document.removeEventListener('mouseup', handleMouseUp, true);
document.removeEventListener('touchmove', handleMouseSlide, true);
document.removeEventListener('touchend', handleMouseUp, true);
};
const handleMouseSlide = throttle(e => {
if (node.current) {
const { x } = getPointerPosition(node.current, e);
if (!isNaN(x)) {
let slideamt = x;
if (x > 1) {
slideamt = 1;
} else if (x < 0) {
slideamt = 0;
}
slideamt = Math.floor((slideamt + 0.5 / steps) * (steps - 1));
onChange(slideamt);
}
}
}, 60);
return (
<div
className='relative inline-flex h-6 cursor-pointer transition'
onMouseDown={handleMouseDown}
ref={node}
>
<div className='absolute top-1/2 h-1 w-full -translate-y-1/2 rounded-full bg-primary-200 dark:bg-primary-700' />
<div className='absolute top-1/2 h-1 -translate-y-1/2 rounded-full bg-accent-500' style={{ width: `${value / (steps - 1) * 100}%` }} />
{[...Array(steps).fill(undefined)].map((_, step) => (
<span
key={step}
className='absolute top-1/2 z-10 h-3 w-1 -translate-y-1/2 bg-accent-300'
style={{ left: `${(step) / (steps - 1) * 100}%` }}
/>
))}
<span
className='absolute top-1/2 z-10 -ml-1.5 size-3 -translate-y-1/2 rounded-full bg-accent-500 shadow'
tabIndex={0}
style={{ left: `${value / (steps - 1) * 100}%` }}
/>
</div>
);
};
export { StepSlider as default };