diff --git a/src/constants.js b/src/constants.js
index 163a16ef84..bf4696d734 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -76,3 +76,7 @@ export const REGEX_RULES = {
specialCharsRule: /^[a-zA-Z0-9_\-.'*~\s]+$/,
noSpaceRule: /^\S*$/,
};
+
+export const IFRAME_FEATURE_POLICY = (
+ 'microphone *; camera *; midi *; geolocation *; encrypted-media *, clipboard-write *'
+);
diff --git a/src/course-unit/CourseUnit.test.jsx b/src/course-unit/CourseUnit.test.jsx
index 896fad036c..bce5f5c1b6 100644
--- a/src/course-unit/CourseUnit.test.jsx
+++ b/src/course-unit/CourseUnit.test.jsx
@@ -52,8 +52,9 @@ import CourseUnit from './CourseUnit';
import configureModalMessages from '../generic/configure-modal/messages';
import addComponentMessages from './add-component/messages';
import {
- PUBLISH_TYPES, UNIT_VISIBILITY_STATES, IFRAME_FEATURE_POLICY, messageTypes,
+ PUBLISH_TYPES, UNIT_VISIBILITY_STATES, messageTypes,
} from './constants';
+import { IFRAME_FEATURE_POLICY } from '../constants';
import messages from './messages';
import xblockContainerIframeMessages from './xblock-container-iframe/messages';
import { getContentTaxonomyTagsApiUrl, getContentTaxonomyTagsCountApiUrl } from '../content-tags-drawer/data/api';
@@ -452,6 +453,26 @@ describe('', () => {
window.open = open;
});
+ it('updates iframe height when dropdown menu is toggled', async () => {
+ const { getByTitle } = render();
+
+ const ACTION_DROPDOWN_HEIGHT = 300;
+
+ await waitFor(() => {
+ const iframe = getByTitle(xblockContainerIframeMessages.xblockIframeTitle.defaultMessage);
+ expect(iframe.getAttribute('style')).toContain('height: 0px;');
+ });
+
+ simulatePostMessageEvent(messageTypes.toggleDropdownMenu, {
+ subMenuHeight: ACTION_DROPDOWN_HEIGHT,
+ });
+
+ await waitFor(() => {
+ const iframe = getByTitle(xblockContainerIframeMessages.xblockIframeTitle.defaultMessage);
+ expect(iframe.getAttribute('style')).toContain(`height: ${ACTION_DROPDOWN_HEIGHT}px;`);
+ });
+ });
+
it('checks courseUnit title changing when edit query is successfully', async () => {
const {
findByText,
diff --git a/src/course-unit/constants.js b/src/course-unit/constants.js
index 6de376da23..c5b0c820ea 100644
--- a/src/course-unit/constants.js
+++ b/src/course-unit/constants.js
@@ -58,8 +58,5 @@ export const messageTypes = {
duplicateXBlock: 'duplicateXBlock',
refreshPositions: 'refreshPositions',
newXBlockEditor: 'newXBlockEditor',
+ toggleDropdownMenu: 'toggleDropdownMenu',
};
-
-export const IFRAME_FEATURE_POLICY = (
- 'microphone *; camera *; midi *; geolocation *; encrypted-media *, clipboard-write *'
-);
diff --git a/src/course-unit/xblock-container-iframe/index.tsx b/src/course-unit/xblock-container-iframe/index.tsx
index 0c7bfd4e9b..58e23aa84d 100644
--- a/src/course-unit/xblock-container-iframe/index.tsx
+++ b/src/course-unit/xblock-container-iframe/index.tsx
@@ -10,15 +10,13 @@ import { useNavigate } from 'react-router-dom';
import DeleteModal from '../../generic/delete-modal/DeleteModal';
import ConfigureModal from '../../generic/configure-modal/ConfigureModal';
import { copyToClipboard } from '../../generic/data/thunks';
-import { COURSE_BLOCK_NAMES } from '../../constants';
-import { IFRAME_FEATURE_POLICY, messageTypes } from '../constants';
+import { COURSE_BLOCK_NAMES, IFRAME_FEATURE_POLICY } from '../../constants';
+import { messageTypes } from '../constants';
import { fetchCourseUnitQuery } from '../data/thunk';
import { useIframe } from '../context/hooks';
import { useIFrameBehavior } from './hooks';
import messages from './messages';
-const IFRAME_BOTTOM_OFFSET = 220;
-
interface XBlockContainerIframeProps {
courseId: string;
blockId: string;
@@ -73,6 +71,7 @@ const XBlockContainerIframe: FC = ({
const [deleteXblockId, setDeleteXblockId] = useState(null);
const [isDeleteModalOpen, openDeleteModal, closeDeleteModal] = useToggle(false);
const [isConfigureModalOpen, openConfigureModal, closeConfigureModal] = useToggle(false);
+ const [dropdownHeight, setDropdownHeight] = useState(0);
const { setIframeRef, sendMessageToIframe } = useIframe();
const [editXblockId, setEditXblockId] = useState(null);
const [currentXblockData, setCurrentXblockData] = useState({});
@@ -141,10 +140,12 @@ const XBlockContainerIframe: FC = ({
[messageTypes.duplicateXBlock]: (payload) => handleDuplicateXBlock(payload.id),
[messageTypes.refreshPositions]: handleRefreshXBlocks,
[messageTypes.newXBlockEditor]: (payload) => navigateToNewXBlockEditor(payload.url),
+ [messageTypes.toggleDropdownMenu]: ({ subMenuHeight }) => setDropdownHeight(subMenuHeight),
};
const handleMessage = (event: MessageEvent) => {
const { type, payload } = event.data || {};
+
if (type && messageHandlers[type]) {
messageHandlers[type](payload);
}
@@ -209,7 +210,10 @@ const XBlockContainerIframe: FC = ({
allow={IFRAME_FEATURE_POLICY}
allowFullScreen
loading="lazy"
- style={{ width: '100%', height: iframeHeight + IFRAME_BOTTOM_OFFSET }}
+ style={{
+ width: '100%',
+ height: iframeHeight + dropdownHeight,
+ }}
scrolling="no"
referrerPolicy="origin"
aria-label={intl.formatMessage(messages.xblockIframeLabel, { xblockCount: xblocks.length })}