Skip to content

Commit

Permalink
fix: unfocus item when overlay button or menu item is clicked (#197)
Browse files Browse the repository at this point in the history
* fix: unfocus item when overlay button or menu item is clicked

* fix: recast all argumnets in item.handler
  • Loading branch information
flops authored Sep 18, 2024
1 parent 20f8a36 commit b0b6b9a
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/components/DashKit/__stories__/DashKitShowcase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ export class DashKitShowcase extends React.Component<{}, DashKitDemoState> {
ref={this.dashKitRef}
overlayControls={this.state.enableOverlayControls ? this.controls : null}
overlayMenuItems={this.state.overlayMenuItems}
focusable={!editMode}
focusable={true}
/>
</DemoRow>
</Demo>
Expand Down
4 changes: 4 additions & 0 deletions src/components/DashKit/__stories__/Demo.scss
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,8 @@
flex: 1;
}
}

.dashkit_focused {
outline: 1px dashed var(--g-color-text-danger);
}
}
46 changes: 41 additions & 5 deletions src/components/GridItem/GridItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';

import PropTypes from 'prop-types';

import {FOCUSED_CLASS_NAME} from '../../constants';
import {DashKitContext} from '../../context/DashKitContext';
import {cn} from '../../utils/cn';
import Item from '../Item/Item';
Expand Down Expand Up @@ -85,16 +86,46 @@ class GridItem extends React.PureComponent {
return null;
}

const {item} = this.props;
const {item, focusable} = this.props;

return (
<React.Fragment>
<div className={b('overlay')} />
<OverlayControls configItem={item} />
<OverlayControls
configItem={item}
onItemClick={focusable ? this.onOverlayItemClick : null}
/>
</React.Fragment>
);
}

onOverlayItemClick = () => {
// Creating button element to trigger focus out
const focusDummy = document.createElement('button');
const styles = {
width: '0',
height: '0',
opacity: '0',
position: 'fixed',
top: '0',
left: '0',
};

Object.entries(styles).forEach(([key, value]) => {
focusDummy.style[key] = value;
});

// requestAnimationFrame to make call after alert() or confirm()
requestAnimationFrame(() => {
// Adding elment an changing focus
document.body.appendChild(focusDummy);
focusDummy.focus();
document.body.removeChild(focusDummy);

this.setState({isFocused: false});
});
};

onFocusHandler = () => {
this.setState({isFocused: true});

Expand Down Expand Up @@ -166,9 +197,14 @@ class GridItem extends React.PureComponent {
const width = Number.parseInt(style.width, 10);
const height = Number.parseInt(style.height, 10);
const transform = style.transform;
const preparedClassName = editMode
? className
: className.replace('react-resizable', '').replace('react-draggable', '');
const preparedClassName =
(editMode
? className
: className
.replace('react-resizable', '')
.replace('react-draggable', '')
.replace(FOCUSED_CLASS_NAME, '')) +
(this.state.isFocused ? ` ${FOCUSED_CLASS_NAME}` : '');
const preparedChildren = editMode ? children : null;
const reactGridLayoutProps = editMode
? {onMouseDown, onMouseUp, onTouchEnd, onTouchStart}
Expand Down
26 changes: 21 additions & 5 deletions src/components/OverlayControls/OverlayControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ interface OverlayControlsDefaultProps {

interface OverlayControlsProps extends OverlayControlsDefaultProps {
configItem: ConfigItem;
onItemClick?: () => void | null;
}

type PreparedCopyItemOptionsArg = Pick<ConfigItem, 'data' | 'type' | 'defaults' | 'namespace'> & {
Expand Down Expand Up @@ -123,7 +124,7 @@ class OverlayControls extends React.Component<OverlayControlsProps> {
};

private renderControlsItem = (item: OverlayControlItem, index: number, length: number) => {
const {view, size} = this.props;
const {view, size, onItemClick} = this.props;
const {title, handler, icon, iconSize, qa} = item;

const onItemClickHandler = typeof handler === 'function' ? handler : noop;
Expand All @@ -134,7 +135,10 @@ class OverlayControls extends React.Component<OverlayControlsProps> {
size={size}
title={title}
pin={this.getControlItemPinStyle(index, length)}
onClick={() => onItemClickHandler(this.props.configItem)}
onClick={() => {
onItemClickHandler(this.props.configItem);
onItemClick?.();
}}
qa={qa}
>
<Icon data={icon || Gear} size={icon ? iconSize : OVERLAY_ICON_SIZE} />
Expand Down Expand Up @@ -246,7 +250,7 @@ class OverlayControls extends React.Component<OverlayControlsProps> {
);
}
private renderDropdownMenu(isOnlyOneItem: boolean) {
const {view, size} = this.props;
const {view, size, onItemClick} = this.props;
const {menu: contextMenu, itemsParams, itemsState} = this.context;

const configItem = this.props.configItem;
Expand Down Expand Up @@ -279,7 +283,11 @@ class OverlayControls extends React.Component<OverlayControlsProps> {

const itemAction =
typeof itemHandler === 'function'
? () => itemHandler(configItem, itemParams, itemState)
? () => {
const result = itemHandler(configItem, itemParams, itemState);
onItemClick?.();
return result;
}
: this.getDropDownMenuItemConfig(item.id)?.action || (() => {});

memo.push({
Expand Down Expand Up @@ -322,6 +330,7 @@ class OverlayControls extends React.Component<OverlayControlsProps> {
// выбираем только items-ы у которых проставлено поле `allWidgetsControls:true`
// те контролы, которые будут показываться слева от меню
let controls: OverlayControlItem[] = [];
const {onItemClick} = this.props;

for (const controlItem of Object.values(this.context.overlayControls || {})) {
controls = controls.concat(
Expand All @@ -344,7 +353,11 @@ class OverlayControls extends React.Component<OverlayControlsProps> {
...item,
handler:
typeof item.handler === 'function'
? item.handler
? (...args) => {
const result = item.handler?.(...args);
onItemClick?.();
return result;
}
: this.getDropDownMenuItemConfig(item.id)?.action || (() => {}),
};
}),
Expand Down Expand Up @@ -376,13 +389,16 @@ class OverlayControls extends React.Component<OverlayControlsProps> {
localStorage.setItem(COPIED_WIDGET_STORE_KEY, JSON.stringify(options));
// https://stackoverflow.com/questions/35865481/storage-event-not-firing
window.dispatchEvent(new Event('storage'));
this.props.onItemClick?.();
};
private onEditItem = () => {
this.context.editItem(this.props.configItem);
this.props.onItemClick?.();
};
private onRemoveItem = () => {
const {id} = this.props.configItem;
this.context.removeItem(id);
this.props.onItemClick?.();
};
private getControlItemPinStyle(index: number, itemsLength: number) {
const isOnlyOneItem = itemsLength === 1;
Expand Down
2 changes: 2 additions & 0 deletions src/constants/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ export const DEFAULT_GROUP = '__default';
export const COMPACT_TYPE_HORIZONTAL_NOWRAP = 'horizontal-nowrap';

export const DRAGGABLE_CANCEL_CLASS_NAME = 'dashkit_draggable_cancel';

export const FOCUSED_CLASS_NAME = 'dashkit_focused';

0 comments on commit b0b6b9a

Please sign in to comment.