feat: implement custom Range component for opacity control (#9009)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>release
parent
d29c3db7f6
commit
bd1590fc74
@ -0,0 +1,59 @@
|
||||
@import "../css/variables.module.scss";
|
||||
|
||||
.excalidraw {
|
||||
--Range-track-background: var(--button-bg);
|
||||
--Range-track-background-active: var(--color-primary);
|
||||
--Range-thumb-background: var(--color-on-surface);
|
||||
--Range-legend-color: var(--text-primary-color);
|
||||
|
||||
.range-wrapper {
|
||||
position: relative;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
|
||||
.range-input {
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
-webkit-appearance: none;
|
||||
background: var(--Range-track-background);
|
||||
border-radius: 2px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.range-input::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: var(--Range-thumb-background);
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.range-input::-moz-range-thumb {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: var(--Range-thumb-background);
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.value-bubble {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
transform: translateX(-50%);
|
||||
font-size: 12px;
|
||||
color: var(--Range-legend-color);
|
||||
}
|
||||
|
||||
.zero-label {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 4px;
|
||||
font-size: 12px;
|
||||
color: var(--Range-legend-color);
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { getFormValue } from "../actions/actionProperties";
|
||||
import { t } from "../i18n";
|
||||
import "./Range.scss";
|
||||
|
||||
export type RangeProps = {
|
||||
updateData: (value: number) => void;
|
||||
appState: any;
|
||||
elements: any;
|
||||
testId?: string;
|
||||
};
|
||||
|
||||
export const Range = ({
|
||||
updateData,
|
||||
appState,
|
||||
elements,
|
||||
testId,
|
||||
}: RangeProps) => {
|
||||
const rangeRef = React.useRef<HTMLInputElement>(null);
|
||||
const valueRef = React.useRef<HTMLDivElement>(null);
|
||||
const value = getFormValue(
|
||||
elements,
|
||||
appState,
|
||||
(element) => element.opacity,
|
||||
true,
|
||||
appState.currentItemOpacity,
|
||||
);
|
||||
useEffect(() => {
|
||||
if (rangeRef.current && valueRef.current) {
|
||||
const rangeElement = rangeRef.current;
|
||||
const valueElement = valueRef.current;
|
||||
const inputWidth = rangeElement.offsetWidth;
|
||||
const thumbWidth = 15; // 15 is the width of the thumb
|
||||
const position =
|
||||
(value / 100) * (inputWidth - thumbWidth) + thumbWidth / 2;
|
||||
valueElement.style.left = `${position}px`;
|
||||
rangeElement.style.background = `linear-gradient(to right, var(--color-primary) 0%, var(--color-primary) ${value}%, var(--button-bg) ${value}%, var(--button-bg) 100%)`;
|
||||
}
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<label className="control-label">
|
||||
{t("labels.opacity")}
|
||||
<div className="range-wrapper">
|
||||
<input
|
||||
ref={rangeRef}
|
||||
type="range"
|
||||
min="0"
|
||||
max="100"
|
||||
step="10"
|
||||
onChange={(event) => {
|
||||
updateData(+event.target.value);
|
||||
}}
|
||||
value={value}
|
||||
className="range-input"
|
||||
data-testid={testId}
|
||||
/>
|
||||
<div className="value-bubble" ref={valueRef}>
|
||||
{value !== 0 ? value : null}
|
||||
</div>
|
||||
<div className="zero-label">0</div>
|
||||
</div>
|
||||
</label>
|
||||
);
|
||||
};
|
Loading…
Reference in New Issue