fix: tab navigation in modals

pull/3061/head
Audric Ackermann 3 months ago
parent 321478682c
commit ce1dfd2875

@ -2,6 +2,11 @@ import React, { ChangeEvent } from 'react';
import styled, { CSSProperties } from 'styled-components';
import { Flex } from './Flex';
const StyledButton = styled.button<{ disabled: boolean }>`
cursor: ${props => (props.disabled ? 'not-allowed' : 'pointer')};
min-height: 30px;
`;
const StyledInput = styled.input<{
filledSize: number;
outlineOffset: number;
@ -9,7 +14,6 @@ const StyledInput = styled.input<{
}>`
opacity: 0;
position: absolute;
cursor: ${props => (props.disabled ? 'not-allowed' : 'pointer')};
width: ${props => props.filledSize + props.outlineOffset}px;
height: ${props => props.filledSize + props.outlineOffset}px;
@ -71,7 +75,7 @@ export const SessionRadio = (props: SessionRadioProps) => {
style,
} = props;
const clickHandler = (e: ChangeEvent<any>) => {
const clickHandler = (e: React.SyntheticEvent<any>) => {
if (!disabled && onClick) {
// let something else catch the event if our click handler is not set
e.stopPropagation();
@ -83,7 +87,15 @@ export const SessionRadio = (props: SessionRadioProps) => {
const outlineOffset = 2;
return (
<button>
<StyledButton
onKeyDown={e => {
if (e.code === 'Space') {
clickHandler(e);
}
}}
onClick={clickHandler}
disabled={disabled}
>
<Flex
container={true}
flexDirection={radioPosition === 'left' ? 'row' : 'row-reverse'}
@ -97,6 +109,7 @@ export const SessionRadio = (props: SessionRadioProps) => {
aria-checked={active}
checked={active}
onChange={clickHandler}
tabIndex={-1} // clickHandler is on the parent button, so we need to skip this input while pressing Tab
filledSize={filledSize * 2}
outlineOffset={outlineOffset}
disabled={disabled}
@ -115,7 +128,7 @@ export const SessionRadio = (props: SessionRadioProps) => {
{label}
</StyledLabel>
</Flex>
</button>
</StyledButton>
);
};

@ -1,6 +1,6 @@
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useKey } from 'react-use';
import useKey from 'react-use/lib/useKey';
import {
deleteMessagesById,
deleteMessagesByIdForEveryone,
@ -35,28 +35,41 @@ export const SelectionOverlay = () => {
const isPublic = useSelectedIsPublic();
const dispatch = useDispatch();
useKey('Delete', event => {
const selectionMode = !!selectedMessageIds.length;
switch (event.key) {
case 'Escape':
if (selectionMode) {
dispatch(resetSelectedMessageIds());
}
break;
case 'Backspace':
case 'Delete':
if (selectionMode && selectedConversationKey) {
void deleteMessagesForX(selectedMessageIds, selectedConversationKey, isPublic);
}
break;
default:
}
});
function onCloseOverlay() {
dispatch(resetSelectedMessageIds());
}
/**
* This is a duplicate with the onKeyDown of SessionConversation.
* At some point we'll make a global handler to deal with the key presses
* and handle them depending on what is visible, but that's not part of this PR
*/
useKey(
shouldProcess => {
return (
shouldProcess.code === 'Escape' ||
shouldProcess.code === 'Backspace' ||
shouldProcess.code === 'Delete'
);
},
event => {
const selectionMode = !!selectedMessageIds.length;
switch (event.key) {
case 'Escape':
if (selectionMode) {
onCloseOverlay();
}
return true;
case 'Backspace':
case 'Delete':
if (selectionMode && selectedConversationKey) {
void deleteMessagesForX(selectedMessageIds, selectedConversationKey, isPublic);
}
return true;
default:
}
return false;
}
);
const isOnlyServerDeletable = isPublic;

Loading…
Cancel
Save