[MM-62989][MM-63039][MM-63033][MM-64174][MM-63040][MM-63032][MM-63001][MM-63006][MM-63037] Various accessibility fixes for the Create Channel modal (#30888)
* [MM-62989] Replace channel purpose input with Input component * [MM-63039] Fix styles so that a11y--focused box shadow is applied to the private/public channel buttons * [MM-63033] Add aria-describedby and role=alert to the URL input on create channel modal * Fix lint * [MM-63035] Change legend to label, fieldset to div in the Input component * Fix i18n * [MM-64174] Stop propagation of enter event while editing the new channel * [MM-63037] Add role=img and an aria label to the error img icon * Fix snap * Revert "[MM-63035] Change legend to label, fieldset to div in the Input component" This reverts commit e8516f3e6a266c77db2b1695a036db717041a9ef. * [MM-63040] Remove tabindex=0 from GenericModal wrapper, fix issue with URLInput that I caused D: * Fix snap --------- Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
1efc3dacaf
Коммит
bd16f4f9bf
@@ -35,7 +35,6 @@ Object {
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
class="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
||||||
tabindex="0"
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="modal-header"
|
class="modal-header"
|
||||||
@@ -519,7 +518,6 @@ Object {
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
class="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
||||||
tabindex="0"
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="modal-header"
|
class="modal-header"
|
||||||
@@ -1163,7 +1161,6 @@ Object {
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
class="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
||||||
tabindex="0"
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="modal-header"
|
class="modal-header"
|
||||||
@@ -1526,7 +1523,6 @@ Object {
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
class="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
||||||
tabindex="0"
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="modal-header"
|
class="modal-header"
|
||||||
@@ -2108,7 +2104,6 @@ Object {
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
class="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
||||||
tabindex="0"
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="modal-header"
|
class="modal-header"
|
||||||
@@ -2690,7 +2685,6 @@ Object {
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
class="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
||||||
tabindex="0"
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="modal-header"
|
class="modal-header"
|
||||||
|
|||||||
@@ -9,15 +9,17 @@
|
|||||||
.new-channel-modal-purpose-textarea {
|
.new-channel-modal-purpose-textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 12px 16px;
|
|
||||||
border: 1px solid rgba(var(--center-channel-color-rgb), 0.16);
|
|
||||||
border-radius: 4px;
|
|
||||||
background: var(--center-channel-bg);
|
background: var(--center-channel-bg);
|
||||||
color: var(--center-channel-color);
|
color: var(--center-channel-color);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
resize: none;
|
resize: none;
|
||||||
|
|
||||||
|
.Input_wrapper textarea.form-control {
|
||||||
|
height: auto;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: rgba(var(--center-channel-color-rgb), 0.48);
|
border-color: rgba(var(--center-channel-color-rgb), 0.48);
|
||||||
}
|
}
|
||||||
@@ -43,26 +45,6 @@
|
|||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.new-channel-modal-purpose-error {
|
|
||||||
display: flex;
|
|
||||||
margin-top: 5px;
|
|
||||||
color: var(--error-text);
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 16px;
|
|
||||||
text-align: left;
|
|
||||||
|
|
||||||
i {
|
|
||||||
height: 14px;
|
|
||||||
align-self: baseline;
|
|
||||||
margin-right: 7px;
|
|
||||||
font-size: 14px;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -145,9 +145,9 @@ describe('components/new_channel_modal', () => {
|
|||||||
expect(privateChannelHeading).toBeInTheDocument();
|
expect(privateChannelHeading).toBeInTheDocument();
|
||||||
expect(privateChannelHeading.nextSibling).toHaveTextContent('Only invited members');
|
expect(privateChannelHeading.nextSibling).toHaveTextContent('Only invited members');
|
||||||
|
|
||||||
const purposeTextArea = screen.getByPlaceholderText('Enter a purpose for this channel (optional)');
|
const purposeTextArea = screen.getByLabelText('Channel Purpose');
|
||||||
expect(purposeTextArea).toBeInTheDocument();
|
expect(purposeTextArea).toBeInTheDocument();
|
||||||
expect(purposeTextArea).toHaveClass('new-channel-modal-purpose-textarea');
|
expect(purposeTextArea).toHaveClass('Input form-control medium');
|
||||||
|
|
||||||
const purposeDesc = screen.getByText('This will be displayed when browsing for channels.');
|
const purposeDesc = screen.getByText('This will be displayed when browsing for channels.');
|
||||||
expect(purposeDesc).toBeInTheDocument();
|
expect(purposeDesc).toBeInTheDocument();
|
||||||
@@ -263,7 +263,7 @@ describe('components/new_channel_modal', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Change purpose
|
// Change purpose
|
||||||
const ChannelPurposeTextArea = screen.getByPlaceholderText('Enter a purpose for this channel (optional)');
|
const ChannelPurposeTextArea = screen.getByLabelText('Channel Purpose');
|
||||||
expect(ChannelPurposeTextArea).toBeInTheDocument();
|
expect(ChannelPurposeTextArea).toBeInTheDocument();
|
||||||
|
|
||||||
userEvent.click(ChannelPurposeTextArea);
|
userEvent.click(ChannelPurposeTextArea);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import {switchToChannel} from 'actions/views/channel';
|
|||||||
import {closeModal} from 'actions/views/modals';
|
import {closeModal} from 'actions/views/modals';
|
||||||
|
|
||||||
import ChannelNameFormField from 'components/channel_name_form_field/channel_name_form_field';
|
import ChannelNameFormField from 'components/channel_name_form_field/channel_name_form_field';
|
||||||
|
import Input from 'components/widgets/inputs/input/input';
|
||||||
import PublicPrivateSelector from 'components/widgets/public-private-selector/public-private-selector';
|
import PublicPrivateSelector from 'components/widgets/public-private-selector/public-private-selector';
|
||||||
import WithTooltip from 'components/with_tooltip';
|
import WithTooltip from 'components/with_tooltip';
|
||||||
|
|
||||||
@@ -283,16 +284,18 @@ const NewChannelModal = () => {
|
|||||||
onChange={handleOnTypeChange}
|
onChange={handleOnTypeChange}
|
||||||
/>
|
/>
|
||||||
<div className='new-channel-modal-purpose-container'>
|
<div className='new-channel-modal-purpose-container'>
|
||||||
<textarea
|
<Input
|
||||||
id='new-channel-modal-purpose'
|
id='new-channel-modal-purpose'
|
||||||
className={classNames('new-channel-modal-purpose-textarea', {'with-error': purposeError})}
|
type='textarea'
|
||||||
placeholder={formatMessage({id: 'channel_modal.purpose.placeholder', defaultMessage: 'Enter a purpose for this channel (optional)'})}
|
|
||||||
rows={4}
|
|
||||||
maxLength={Constants.MAX_CHANNELPURPOSE_LENGTH}
|
|
||||||
autoComplete='off'
|
|
||||||
value={purpose}
|
value={purpose}
|
||||||
onChange={handleOnPurposeChange}
|
onChange={handleOnPurposeChange}
|
||||||
onKeyDown={handleOnPurposeKeyDown}
|
onKeyDown={handleOnPurposeKeyDown}
|
||||||
|
label={formatMessage({id: 'channel_modal.purpose.label', defaultMessage: 'Channel Purpose'})}
|
||||||
|
placeholder={formatMessage({id: 'channel_modal.purpose.placeholder', defaultMessage: 'Enter a purpose for this channel (optional)'})}
|
||||||
|
maxLength={Constants.MAX_CHANNELPURPOSE_LENGTH}
|
||||||
|
autoComplete='off'
|
||||||
|
className={classNames('new-channel-modal-purpose-textarea', {'with-error': purposeError})}
|
||||||
|
rows={4}
|
||||||
/>
|
/>
|
||||||
{purposeError ? (
|
{purposeError ? (
|
||||||
<div className='new-channel-modal-purpose-error'>
|
<div className='new-channel-modal-purpose-error'>
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ exports[`components/marketplace/ doesn't show web marketplace banner in FeatureF
|
|||||||
<div
|
<div
|
||||||
className="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
className="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
||||||
onKeyDown={[Function]}
|
onKeyDown={[Function]}
|
||||||
tabIndex={0}
|
|
||||||
>
|
>
|
||||||
<ModalHeader
|
<ModalHeader
|
||||||
bsClass="modal-header"
|
bsClass="modal-header"
|
||||||
@@ -148,7 +147,6 @@ exports[`components/marketplace/ hides search, shows web marketplace banner in F
|
|||||||
<div
|
<div
|
||||||
className="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
className="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
||||||
onKeyDown={[Function]}
|
onKeyDown={[Function]}
|
||||||
tabIndex={0}
|
|
||||||
>
|
>
|
||||||
<ModalHeader
|
<ModalHeader
|
||||||
bsClass="modal-header"
|
bsClass="modal-header"
|
||||||
@@ -261,7 +259,6 @@ exports[`components/marketplace/ should render default 1`] = `
|
|||||||
<div
|
<div
|
||||||
className="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
className="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
||||||
onKeyDown={[Function]}
|
onKeyDown={[Function]}
|
||||||
tabIndex={0}
|
|
||||||
>
|
>
|
||||||
<ModalHeader
|
<ModalHeader
|
||||||
bsClass="modal-header"
|
bsClass="modal-header"
|
||||||
@@ -425,7 +422,6 @@ exports[`components/marketplace/ should render with error banner 1`] = `
|
|||||||
<div
|
<div
|
||||||
className="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
className="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
||||||
onKeyDown={[Function]}
|
onKeyDown={[Function]}
|
||||||
tabIndex={0}
|
|
||||||
>
|
>
|
||||||
<ModalHeader
|
<ModalHeader
|
||||||
bsClass="modal-header"
|
bsClass="modal-header"
|
||||||
@@ -606,7 +602,6 @@ exports[`components/marketplace/ should render with no plugins available 1`] = `
|
|||||||
<div
|
<div
|
||||||
className="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
className="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
||||||
onKeyDown={[Function]}
|
onKeyDown={[Function]}
|
||||||
tabIndex={0}
|
|
||||||
>
|
>
|
||||||
<ModalHeader
|
<ModalHeader
|
||||||
bsClass="modal-header"
|
bsClass="modal-header"
|
||||||
@@ -778,7 +773,6 @@ exports[`components/marketplace/ should render with plugins available 1`] = `
|
|||||||
<div
|
<div
|
||||||
className="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
className="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
||||||
onKeyDown={[Function]}
|
onKeyDown={[Function]}
|
||||||
tabIndex={0}
|
|
||||||
>
|
>
|
||||||
<ModalHeader
|
<ModalHeader
|
||||||
bsClass="modal-header"
|
bsClass="modal-header"
|
||||||
@@ -968,7 +962,6 @@ exports[`components/marketplace/ should render with plugins installed 1`] = `
|
|||||||
<div
|
<div
|
||||||
className="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
className="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
||||||
onKeyDown={[Function]}
|
onKeyDown={[Function]}
|
||||||
tabIndex={0}
|
|
||||||
>
|
>
|
||||||
<ModalHeader
|
<ModalHeader
|
||||||
bsClass="modal-header"
|
bsClass="modal-header"
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ Object {
|
|||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
aria-label=""
|
aria-label=""
|
||||||
class="icon error icon-alert-circle-outline"
|
class="icon error icon-alert-circle-outline"
|
||||||
|
role="img"
|
||||||
/>
|
/>
|
||||||
<span>
|
<span>
|
||||||
Please enter a valid business email address.
|
Please enter a valid business email address.
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElem
|
|||||||
clearable?: boolean;
|
clearable?: boolean;
|
||||||
clearableTooltipText?: string;
|
clearableTooltipText?: string;
|
||||||
onClear?: () => void;
|
onClear?: () => void;
|
||||||
|
rows?: number;
|
||||||
validate?: (value: React.InputHTMLAttributes<HTMLInputElement | HTMLTextAreaElement>['value']) => CustomMessageInputType | undefined;
|
validate?: (value: React.InputHTMLAttributes<HTMLInputElement | HTMLTextAreaElement>['value']) => CustomMessageInputType | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +75,7 @@ const Input = React.forwardRef((
|
|||||||
onBlur,
|
onBlur,
|
||||||
onChange,
|
onChange,
|
||||||
onClear,
|
onClear,
|
||||||
|
rows,
|
||||||
validate,
|
validate,
|
||||||
...otherProps
|
...otherProps
|
||||||
}: InputProps,
|
}: InputProps,
|
||||||
@@ -223,7 +225,7 @@ const Input = React.forwardRef((
|
|||||||
aria-label={ariaLabel}
|
aria-label={ariaLabel}
|
||||||
aria-describedby={customInputLabel ? errorId : undefined}
|
aria-describedby={customInputLabel ? errorId : undefined}
|
||||||
aria-invalid={error || hasError}
|
aria-invalid={error || hasError}
|
||||||
rows={3}
|
rows={rows || 3}
|
||||||
name={name}
|
name={name}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
@@ -291,8 +293,9 @@ const Input = React.forwardRef((
|
|||||||
'icon-information-outline': (customInputLabel?.type || 'error') === ItemStatus.INFO,
|
'icon-information-outline': (customInputLabel?.type || 'error') === ItemStatus.INFO,
|
||||||
'icon-check': (customInputLabel?.type || 'error') === ItemStatus.SUCCESS,
|
'icon-check': (customInputLabel?.type || 'error') === ItemStatus.SUCCESS,
|
||||||
})}
|
})}
|
||||||
aria-hidden={Boolean(customInputLabel.value)}
|
role='img'
|
||||||
aria-label={customInputLabel.value ? '' : customInputLabel.type || 'error'}
|
aria-label={customInputLabel.value ? '' : customInputLabel.type || 'error'}
|
||||||
|
aria-hidden={Boolean(customInputLabel.value)}
|
||||||
/>
|
/>
|
||||||
<span>{customInputLabel?.value}</span>
|
<span>{customInputLabel?.value}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -70,13 +70,17 @@ function UrlInput({
|
|||||||
onBlur(event);
|
onBlur(event);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOnButtonClick = () => {
|
const handleOnButtonClick = () => {
|
||||||
if (!hasError) {
|
if (!hasError) {
|
||||||
setEditing(!editing);
|
setEditing(!editing);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handlePropagateKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
};
|
||||||
const urlInputLabel = (
|
const urlInputLabel = (
|
||||||
<span
|
<span
|
||||||
className='url-input-label'
|
className='url-input-label'
|
||||||
@@ -116,12 +120,14 @@ function UrlInput({
|
|||||||
hasError={hasError}
|
hasError={hasError}
|
||||||
onChange={handleOnInputChange}
|
onChange={handleOnInputChange}
|
||||||
onBlur={handleOnInputBlur}
|
onBlur={handleOnInputBlur}
|
||||||
|
aria-describedby='url-input-error'
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
className={classNames('url-input-button', {disabled: hasError})}
|
className={classNames('url-input-button', {disabled: hasError})}
|
||||||
disabled={hasError}
|
disabled={hasError}
|
||||||
onClick={handleOnButtonClick}
|
onClick={handleOnButtonClick}
|
||||||
|
onKeyDown={handlePropagateKeyDown}
|
||||||
>
|
>
|
||||||
<span className='url-input-button-label'>
|
<span className='url-input-button-label'>
|
||||||
{editing ? formatMessage({id: 'url_input.buttonLabel.done', defaultMessage: 'Done'}) : formatMessage({id: 'url_input.buttonLabel.edit', defaultMessage: 'Edit'})}
|
{editing ? formatMessage({id: 'url_input.buttonLabel.done', defaultMessage: 'Done'}) : formatMessage({id: 'url_input.buttonLabel.edit', defaultMessage: 'Edit'})}
|
||||||
@@ -131,7 +137,12 @@ function UrlInput({
|
|||||||
{error && (
|
{error && (
|
||||||
<div className='url-input-error'>
|
<div className='url-input-error'>
|
||||||
<i className='icon icon-alert-outline'/>
|
<i className='icon icon-alert-outline'/>
|
||||||
<span>{error}</span>
|
<span
|
||||||
|
id='url-input-error'
|
||||||
|
role='alert'
|
||||||
|
>
|
||||||
|
{error}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,14 +12,16 @@
|
|||||||
border: 1px solid rgba(var(--center-channel-color-rgb), 0.16);
|
border: 1px solid rgba(var(--center-channel-color-rgb), 0.16);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: var(--center-channel-bg);
|
background: var(--center-channel-bg);
|
||||||
|
|
||||||
|
&:not(.a11y--focused) {
|
||||||
box-shadow: var(--elevation-1);
|
box-shadow: var(--elevation-1);
|
||||||
|
}
|
||||||
|
|
||||||
&:not(:first-child) {
|
&:not(:first-child) {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.a11y--focused,
|
&:not(.a11y--focused):hover {
|
||||||
&:hover {
|
|
||||||
border: 1px solid rgba(var(--center-channel-color-rgb), 0.16);
|
border: 1px solid rgba(var(--center-channel-color-rgb), 0.16);
|
||||||
box-shadow: var(--elevation-2);
|
box-shadow: var(--elevation-2);
|
||||||
}
|
}
|
||||||
@@ -32,7 +34,7 @@
|
|||||||
fill: var(--button-bg);
|
fill: var(--button-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:not(.a11y--focused):hover {
|
||||||
border: 1px solid rgba(var(--sidebar-text-active-border-rgb), 0.4);
|
border: 1px solid rgba(var(--sidebar-text-active-border-rgb), 0.4);
|
||||||
box-shadow: var(--elevation-2);
|
box-shadow: var(--elevation-2);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3609,6 +3609,7 @@
|
|||||||
"channel_modal.name.placeholder": "Enter a name for your new channel",
|
"channel_modal.name.placeholder": "Enter a name for your new channel",
|
||||||
"channel_modal.name.shorter": "Channel names must have maximum 64 characters.",
|
"channel_modal.name.shorter": "Channel names must have maximum 64 characters.",
|
||||||
"channel_modal.purpose.info": "This will be displayed when browsing for channels.",
|
"channel_modal.purpose.info": "This will be displayed when browsing for channels.",
|
||||||
|
"channel_modal.purpose.label": "Channel Purpose",
|
||||||
"channel_modal.purpose.placeholder": "Enter a purpose for this channel (optional)",
|
"channel_modal.purpose.placeholder": "Enter a purpose for this channel (optional)",
|
||||||
"channel_modal.purposeTooLong": "The purpose exceeds the maximum of 250 characters",
|
"channel_modal.purposeTooLong": "The purpose exceeds the maximum of 250 characters",
|
||||||
"channel_modal.type.private.description": "Only invited members",
|
"channel_modal.type.private.description": "Only invited members",
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ exports[`GenericModal should match snapshot for base case 1`] = `
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
class="GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher"
|
||||||
tabindex="0"
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="modal-header"
|
class="modal-header"
|
||||||
|
|||||||
@@ -115,7 +115,6 @@ export const GenericModal: React.FC<Props> = ({
|
|||||||
compassDesign,
|
compassDesign,
|
||||||
backdrop,
|
backdrop,
|
||||||
backdropClassName,
|
backdropClassName,
|
||||||
tabIndex,
|
|
||||||
children,
|
children,
|
||||||
autoFocusConfirmButton,
|
autoFocusConfirmButton,
|
||||||
headerInput,
|
headerInput,
|
||||||
@@ -288,7 +287,6 @@ export const GenericModal: React.FC<Props> = ({
|
|||||||
<div
|
<div
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
onKeyDown={onEnterKeyDown}
|
onKeyDown={onEnterKeyDown}
|
||||||
tabIndex={tabIndex || 0}
|
|
||||||
className='GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher'
|
className='GenericModal__wrapper GenericModal__wrapper-enter-key-press-catcher'
|
||||||
>
|
>
|
||||||
{showHeader && (
|
{showHeader && (
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user