Skip to content

Commit

Permalink
fix(designer-ui): Allow color picker sliders to be accessed by keyboa…
Browse files Browse the repository at this point in the history
…rd (#4884)

* Allow keyboard to be used with color picker

* Enforce debouncing so color picker is easier with keyboard

* Remove debug log
  • Loading branch information
ek68794998 authored May 24, 2024
1 parent 1fc4497 commit 98fb4bc
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { transformColor } from '@microsoft/logic-apps-shared';
import type { LexicalEditor } from 'lexical';
import { useEffect, useMemo, useRef, useState } from 'react';
import constants from '../../../constants';
import { useDebouncedState } from '@react-hookz/web';

interface DropdownColorPickerProps {
disabled?: boolean;
Expand All @@ -17,7 +18,7 @@ interface DropdownColorPickerProps {
buttonIconSrc?: string;
buttonLabel?: string;
color: string;
onChange?: (color: string) => void;
onChange: (color: string) => void;
title?: string;
editor: LexicalEditor;
}
Expand All @@ -34,6 +35,7 @@ export const DropdownColorPicker = ({
const { isInverted } = useTheme();
const [selfColor, setSelfColor] = useState(transformColor('hex', color));
const [inputColor, setInputColor] = useState(color);
const [exposedColor, setExposedColor] = useDebouncedState(selfColor, 300);
const innerDivRef = useRef(null);

const arrowNavigationAttributes = useArrowNavigationGroup({ axis: 'horizontal', circular: true });
Expand Down Expand Up @@ -81,11 +83,17 @@ export const DropdownColorPicker = ({

useEffect(() => {
// Check if the dropdown is actually active
if (innerDivRef.current !== null && onChange) {
onChange(selfColor.hex);
if (innerDivRef.current !== null) {
if (exposedColor.hex !== selfColor.hex) {
setExposedColor(selfColor);
}
setInputColor(selfColor.hex);
}
}, [selfColor, onChange]);
}, [exposedColor, selfColor, setExposedColor]);

useEffect(() => {
onChange(exposedColor.hex);
}, [exposedColor, onChange]);

useEffect(() => {
if (color === undefined) {
Expand Down Expand Up @@ -120,6 +128,7 @@ export const DropdownColorPicker = ({
className="color-picker-saturation"
style={{ backgroundColor: `hsl(${selfColor.hsv.hue}, 100%, 50%)` }}
onChange={onMoveSaturation}
value={saturationPosition}
>
<div
className="color-picker-saturation_cursor"
Expand All @@ -130,7 +139,7 @@ export const DropdownColorPicker = ({
}}
/>
</MoveWrapper>
<MoveWrapper className="color-picker-hue" onChange={onMoveHue}>
<MoveWrapper className="color-picker-hue" onChange={onMoveHue} value={{ ...huePosition, y: 0 }}>
<div
className="color-picker-hue_cursor"
style={{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,31 @@ import type { Position } from './util';
import { useRef } from 'react';

interface MoveWrapperProps {
children: JSX.Element;
className?: string;
style?: React.CSSProperties;
onChange: (position: Position) => void;
children: JSX.Element;
style?: React.CSSProperties;
value: Position;
}

export const MoveWrapper = ({ className, style, onChange, children }: MoveWrapperProps) => {
const keyMoveMap: Record<string, Position> = {
ArrowLeft: { x: -1, y: 0 },
ArrowRight: { x: 1, y: 0 },
ArrowUp: { x: 0, y: -1 },
ArrowDown: { x: 0, y: 1 },
};

export const MoveWrapper = ({ children, className, onChange, style, value }: MoveWrapperProps) => {
const divRef = useRef<HTMLDivElement>(null);

const getBoundingClientRect = (): DOMRect | undefined => {
return divRef.current?.getBoundingClientRect();
}

const move = (e: React.MouseEvent | MouseEvent): void => {
if (divRef.current) {
const { current: div } = divRef;
const { width, height, left, top, right } = div.getBoundingClientRect();
const rect = getBoundingClientRect();
if (rect) {
const { width, height, left, top, right } = rect;

if (e.clientX <= right && e.clientX >= left) {
const x = clamp(e.clientX - left, width, 0);
Expand Down Expand Up @@ -47,8 +59,26 @@ export const MoveWrapper = ({ className, style, onChange, children }: MoveWrappe
document.addEventListener('mouseup', onMouseUp, false);
};

const onKeyDown = (e: React.KeyboardEvent): void => {
const { key } = e;
const rect = getBoundingClientRect();

if (rect && key in keyMoveMap) {
const { width, height } = rect;
const multiplier = e.shiftKey ? 10 : 1;
const offset = keyMoveMap[key];

onChange({
x: clamp(value.x + (multiplier * offset.x), width, 0),
y: clamp(value.y + (multiplier * offset.y), height, 0),
});

e.preventDefault();
}
}

return (
<div ref={divRef} className={className} style={style} onMouseDown={onMouseDown}>
<div ref={divRef} className={className} style={style} tabIndex={0} onMouseDown={onMouseDown} onKeyDown={onKeyDown}>
{children}
</div>
);
Expand Down

0 comments on commit 98fb4bc

Please sign in to comment.