fix: focustrap when no buttons are mounted right away

pull/3074/head
Audric Ackermann 1 month ago
parent ab718c2343
commit 85c247eaf0

@ -0,0 +1,27 @@
import FocusTrap from 'focus-trap-react';
import React from 'react';
import styled from 'styled-components';
const DefaultFocusButton = styled.button`
opacity: 0;
width: 0;
height: 0;
`;
/**
* The FocusTrap always require at least one element to be tabbable.
* On some dialogs, we don't have any until the content is loaded, and depending on what is loaded, we might not have any tabbable elements in it.
* This component renders the children inside a FocusTrap and always adds an invisible button to make FocusTrap happy.
*/
export function SessionDialogFocusTrap(props: { children: React.ReactNode }) {
// FocusTrap needs a single child so props.children and the default button needs to be wrapped in a container.
// This might cause some styling issues, but I didn't find any with our current dialogs
return (
<FocusTrap focusTrapOptions={{ initialFocus: false, allowOutsideClick: true }}>
<div style={{ position: 'absolute' }}>
<DefaultFocusButton />
{props.children}
</div>
</FocusTrap>
);
}

@ -1,11 +1,11 @@
import classNames from 'classnames';
import FocusTrap from 'focus-trap-react';
import React, { useRef } from 'react';
import useKey from 'react-use/lib/useKey';
import { SessionIconButton } from './icon';
import { SessionButton, SessionButtonColor, SessionButtonType } from './basic/SessionButton';
import { SessionDialogFocusTrap } from './SessionFocusTrap';
export type SessionWrapperModalType = {
title?: string;
@ -17,7 +17,7 @@ export type SessionWrapperModalType = {
cancelText?: string;
showExitIcon?: boolean;
headerIconButtons?: Array<any>;
children: any;
children: React.ReactNode;
headerReverse?: boolean;
additionalClassName?: string;
};
@ -64,7 +64,7 @@ export const SessionWrapperModal = (props: SessionWrapperModalType) => {
};
return (
<FocusTrap focusTrapOptions={{ initialFocus: false, allowOutsideClick: true }}>
<SessionDialogFocusTrap>
<div
className={classNames('loki-dialog modal', additionalClassName || null)}
onClick={handleClick}
@ -128,6 +128,6 @@ export const SessionWrapperModal = (props: SessionWrapperModalType) => {
</div>
</div>
</div>
</FocusTrap>
</SessionDialogFocusTrap>
);
};

@ -1,5 +1,6 @@
import FocusTrap from 'focus-trap-react';
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import useKey from 'react-use/lib/useKey';

@ -4,10 +4,10 @@ import { createPortal } from 'react-dom';
import { useSelector } from 'react-redux';
import styled from 'styled-components';
import { getUnreadConversationRequests } from '../../state/selectors/conversations';
import { isSearching } from '../../state/selectors/search';
import { getHideMessageRequestBanner } from '../../state/selectors/userConfig';
import { SessionIcon, SessionIconSize, SessionIconType } from '../icon';
import { MessageRequestBannerContextMenu } from '../menu/MessageRequestBannerContextMenu';
import { isSearching } from '../../state/selectors/search';
const StyledMessageRequestBanner = styled.div`
height: 64px;
@ -137,6 +137,6 @@ export const MessageRequestsBanner = (props: { handleOnClick: () => any }) => {
);
};
const Portal = ({ children }: { children: any }) => {
const Portal = ({ children }: { children: React.ReactNode }) => {
return createPortal(children, document.querySelector('.inbox.index') as Element);
};

@ -34,7 +34,7 @@ type PropsHousekeeping = {
type Props = { conversationId: string } & PropsHousekeeping;
const Portal = ({ children }: { children: any }) => {
const Portal = ({ children }: { children: React.ReactNode }) => {
return createPortal(children, document.querySelector('.inbox.index') as Element);
};

@ -1,10 +1,10 @@
import { ipcRenderer } from 'electron';
import React from 'react';
import { createGlobalStyle } from 'styled-components';
import { switchThemeTo } from './switchTheme';
import { classicDark } from './classicDark';
import { getOppositeTheme, isThemeMismatched } from '../util/theme';
import { declareCSSVariables, THEME_GLOBALS } from './globals';
import { classicDark } from './classicDark';
import { THEME_GLOBALS, declareCSSVariables } from './globals';
import { switchThemeTo } from './switchTheme';
// Defaults to Classic Dark theme
const SessionGlobalStyles = createGlobalStyle`
@ -14,7 +14,7 @@ const SessionGlobalStyles = createGlobalStyle`
};
`;
export const SessionTheme = ({ children }: { children: any }) => (
export const SessionTheme = ({ children }: { children: React.ReactNode }) => (
<>
<SessionGlobalStyles />
{children}

Loading…
Cancel
Save