fix: change dropdowns to menus to fix off-screen render (#948)
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
@import "files-and-videos/videos-page/transcript-settings/TranscriptSettings";
|
||||
@import "files-and-videos/videos-page/VideoThumbnail";
|
||||
@import "files-and-videos/videos-page/info-sidebar/transcript-item/LanguageSelect";
|
||||
@import "files-and-videos/videos-page/info-sidebar/transcript-item/TranscriptMenu";
|
||||
@import "files-and-videos/generic/table-components/GalleryCard";
|
||||
|
||||
.files-table {
|
||||
@@ -49,10 +51,10 @@
|
||||
.pgn__menu-item {
|
||||
width: 100%;
|
||||
justify-content: start;
|
||||
font-weight: 400;
|
||||
|
||||
&.focus,
|
||||
&:focus {
|
||||
font-weight: 500;
|
||||
&:hover {
|
||||
background-color: $light-300;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ describe('TranscriptTab', () => {
|
||||
fireEvent.click(menuButton);
|
||||
});
|
||||
|
||||
const deleteButton = screen.getByText(transcriptRowMessages.deleteTranscript.defaultMessage).closest('a');
|
||||
const deleteButton = screen.getByText(transcriptRowMessages.deleteTranscript.defaultMessage).closest('button');
|
||||
fireEvent.click(deleteButton);
|
||||
});
|
||||
|
||||
@@ -237,7 +237,7 @@ describe('TranscriptTab', () => {
|
||||
});
|
||||
downloadButton = screen.getByText(
|
||||
transcriptRowMessages.downloadTranscript.defaultMessage,
|
||||
).closest('a');
|
||||
).closest('button');
|
||||
});
|
||||
|
||||
it('should download transcript', async () => {
|
||||
@@ -291,7 +291,7 @@ describe('TranscriptTab', () => {
|
||||
});
|
||||
const replaceButton = screen.getByText(
|
||||
transcriptRowMessages.replaceTranscript.defaultMessage,
|
||||
).closest('a');
|
||||
).closest('button');
|
||||
fireEvent.click(replaceButton);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Dropdown, Icon } from '@openedx/paragon';
|
||||
import { Check, ExpandMore } from '@openedx/paragon/icons';
|
||||
|
||||
import {
|
||||
Button,
|
||||
Icon,
|
||||
ModalPopup,
|
||||
Menu,
|
||||
MenuItem,
|
||||
useToggle,
|
||||
} from '@openedx/paragon';
|
||||
import { Check, ExpandMore, ExpandLess } from '@openedx/paragon/icons';
|
||||
import { isEmpty } from 'lodash';
|
||||
|
||||
const LanguageSelect = ({
|
||||
@@ -12,47 +20,87 @@ const LanguageSelect = ({
|
||||
placeholderText,
|
||||
}) => {
|
||||
const currentSelection = isEmpty(value) ? placeholderText : options[value];
|
||||
|
||||
const [isOpen, , close, toggle] = useToggle();
|
||||
const [target, setTarget] = useState(null);
|
||||
|
||||
return (
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
variant="tertiary"
|
||||
size="sm"
|
||||
className="border border-gray-700 justify-content-between"
|
||||
style={{ minWidth: '100%' }}
|
||||
id={`language-select-dropdown-${currentSelection}`}
|
||||
data-testid="language-select-dropdown"
|
||||
<>
|
||||
<div className="col-9 p-0">
|
||||
<Button
|
||||
variant="tertiary"
|
||||
size="sm"
|
||||
className="border border-gray-700 justify-content-between"
|
||||
style={{ minWidth: '100%' }}
|
||||
id={`language-select-dropdown-${currentSelection}`}
|
||||
data-testid="language-select-dropdown"
|
||||
iconAfter={isOpen ? ExpandLess : ExpandMore}
|
||||
onClick={toggle}
|
||||
ref={setTarget}
|
||||
>
|
||||
{currentSelection}
|
||||
</Button>
|
||||
</div>
|
||||
<ModalPopup
|
||||
placement="bottom-end"
|
||||
positionRef={target}
|
||||
isOpen={isOpen}
|
||||
onClose={close}
|
||||
onEscapeKey={close}
|
||||
>
|
||||
{currentSelection}
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu className="m-0 position-fixed">
|
||||
<div style={{ height: '230px', overflowY: 'scroll' }}>
|
||||
{Object.entries(options).map(([valueKey, text]) => {
|
||||
if (valueKey === value) {
|
||||
<Menu
|
||||
className="language-select"
|
||||
>
|
||||
<div>
|
||||
{Object.entries(options).map(([valueKey, text]) => {
|
||||
if (valueKey === value) {
|
||||
return (
|
||||
<MenuItem
|
||||
as={Button}
|
||||
variant="tertiary"
|
||||
size="sm"
|
||||
key={`${valueKey}-item`}
|
||||
>
|
||||
<Icon size="inline" src={Check} />
|
||||
<span className="pl-1">{text}</span>
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
if (!previousSelection.includes(valueKey)) {
|
||||
return (
|
||||
<MenuItem
|
||||
as={Button}
|
||||
variant="tertiary"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
handleSelect(valueKey);
|
||||
close();
|
||||
}}
|
||||
key={`${valueKey}-item`}
|
||||
>
|
||||
<span className="pl-3">{text}</span>
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Dropdown.Item className="small" key={`${valueKey}-item`}>
|
||||
<Icon size="inline" src={Check} className="m-n2" /><span className="pl-3">{text}</span>
|
||||
</Dropdown.Item>
|
||||
);
|
||||
}
|
||||
if (!previousSelection.includes(valueKey)) {
|
||||
return (
|
||||
<Dropdown.Item className="small" onClick={() => handleSelect(valueKey)} key={`${valueKey}-item`}>
|
||||
<MenuItem
|
||||
disabled
|
||||
variant="tertiary"
|
||||
as={Button}
|
||||
size="sm"
|
||||
key={`${valueKey}-item`}
|
||||
>
|
||||
<span className="pl-3">{text}</span>
|
||||
</Dropdown.Item>
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Dropdown.Item disabled className="small" key={`${valueKey}-item`}>
|
||||
<span className="pl-3">{text}</span>
|
||||
</Dropdown.Item>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
})}
|
||||
</div>
|
||||
</Menu>
|
||||
<div className="row justify-content-center">
|
||||
<Icon src={ExpandMore} size="xs" />
|
||||
</div>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
</ModalPopup>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
.language-select {
|
||||
padding: 8px 0;
|
||||
margin: 0;
|
||||
overflow-x: hidden;
|
||||
max-height: 275px;
|
||||
width: 300px;
|
||||
|
||||
@include pgn-box-shadow(2, "down");
|
||||
|
||||
.pgn__menu-item {
|
||||
width: 100%;
|
||||
justify-content: start;
|
||||
font-weight: 400;
|
||||
|
||||
&:hover {
|
||||
background-color: $light-300;
|
||||
}
|
||||
|
||||
.pgn__menu-item-text {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,15 +84,13 @@ const Transcript = ({
|
||||
key={`transcript-${language}`}
|
||||
data-testid={`transcript-${language}`}
|
||||
>
|
||||
<div className="col-9 p-0">
|
||||
<LanguageSelect
|
||||
options={languages}
|
||||
value={newLanguage}
|
||||
placeholderText={intl.formatMessage(messages.languageSelectPlaceholder)}
|
||||
previousSelection={previousSelection}
|
||||
handleSelect={updateLangauge}
|
||||
/>
|
||||
</div>
|
||||
<LanguageSelect
|
||||
options={languages}
|
||||
value={newLanguage}
|
||||
placeholderText={intl.formatMessage(messages.languageSelectPlaceholder)}
|
||||
previousSelection={previousSelection}
|
||||
handleSelect={updateLangauge}
|
||||
/>
|
||||
{ transcript === '' ? (
|
||||
<IconButton
|
||||
iconAs={Icon}
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { FormattedMessage, injectIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Dropdown, Icon, IconButton } from '@openedx/paragon';
|
||||
import {
|
||||
Button,
|
||||
Icon,
|
||||
IconButton,
|
||||
ModalPopup,
|
||||
Menu,
|
||||
MenuItem,
|
||||
useToggle,
|
||||
} from '@openedx/paragon';
|
||||
import { MoreHoriz } from '@openedx/paragon/icons';
|
||||
|
||||
import messages from './messages';
|
||||
@@ -11,36 +19,59 @@ export const TranscriptActionMenu = ({
|
||||
launchDeleteConfirmation,
|
||||
handleTranscript,
|
||||
input,
|
||||
}) => (
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
id="dropdown-toggle-with-iconbutton-video-transcript-widget"
|
||||
as={IconButton}
|
||||
src={MoreHoriz}
|
||||
iconAs={Icon}
|
||||
variant="primary"
|
||||
alt="Actions dropdown"
|
||||
data-testid={`${language}-transcript-menu`}
|
||||
/>
|
||||
<Dropdown.Menu className="video_transcript position-fixed">
|
||||
<Dropdown.Item
|
||||
key={`transcript-actions-${language}-replace`}
|
||||
onClick={input.click}
|
||||
}) => {
|
||||
const [isOpen, , close, toggle] = useToggle();
|
||||
const [target, setTarget] = useState(null);
|
||||
return (
|
||||
<>
|
||||
<IconButton
|
||||
src={MoreHoriz}
|
||||
iconAs={Icon}
|
||||
onClick={toggle}
|
||||
ref={setTarget}
|
||||
alt="Actions dropdown"
|
||||
data-testid={`${language}-transcript-menu`}
|
||||
/>
|
||||
<ModalPopup
|
||||
placement="bottom-end"
|
||||
positionRef={target}
|
||||
isOpen={isOpen}
|
||||
onClose={close}
|
||||
onEscapeKey={close}
|
||||
>
|
||||
<FormattedMessage {...messages.replaceTranscript} />
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key={`transcript-actions-${language}-download`}
|
||||
onClick={() => handleTranscript({ language }, 'download')}
|
||||
>
|
||||
<FormattedMessage {...messages.downloadTranscript} />
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item key={`transcript-actions-${language}-delete`} onClick={launchDeleteConfirmation}>
|
||||
<FormattedMessage {...messages.deleteTranscript} />
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
);
|
||||
<Menu
|
||||
className="transcript-menu"
|
||||
>
|
||||
<MenuItem
|
||||
as={Button}
|
||||
variant="tertiary"
|
||||
key={`transcript-actions-${language}-replace`}
|
||||
onClick={input.click}
|
||||
>
|
||||
<FormattedMessage {...messages.replaceTranscript} />
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
as={Button}
|
||||
variant="tertiary"
|
||||
key={`transcript-actions-${language}-download`}
|
||||
onClick={() => handleTranscript({ language }, 'download')}
|
||||
>
|
||||
<FormattedMessage {...messages.downloadTranscript} />
|
||||
</MenuItem>
|
||||
<hr className="my-2" />
|
||||
<MenuItem
|
||||
as={Button}
|
||||
variant="tertiary"
|
||||
key={`transcript-actions-${language}-delete`}
|
||||
onClick={launchDeleteConfirmation}
|
||||
>
|
||||
<FormattedMessage {...messages.deleteTranscript} />
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</ModalPopup>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
TranscriptActionMenu.propTypes = {
|
||||
language: PropTypes.string.isRequired,
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
.transcript-menu {
|
||||
padding: 8px 0;
|
||||
margin: 0;
|
||||
width: 250px;
|
||||
|
||||
@include pgn-box-shadow(2, "down");
|
||||
|
||||
.pgn__menu-item {
|
||||
width: 100%;
|
||||
justify-content: start;
|
||||
font-weight: 400;
|
||||
|
||||
&:hover {
|
||||
background-color: $light-300;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user