diff --git a/src/courseware/course/Course.jsx b/src/courseware/course/Course.jsx
index 9f3e0994..294caa75 100644
--- a/src/courseware/course/Course.jsx
+++ b/src/courseware/course/Course.jsx
@@ -71,7 +71,7 @@ export default function Course({
/>
)}
-
+
+
+ {verifiedMode && }
- {verifiedMode &&
}
>
);
}
diff --git a/src/courseware/course/SequenceContainer.jsx b/src/courseware/course/SequenceContainer.jsx
index 6ab03dee..5b288e78 100644
--- a/src/courseware/course/SequenceContainer.jsx
+++ b/src/courseware/course/SequenceContainer.jsx
@@ -8,7 +8,6 @@ import { history } from '@edx/frontend-platform';
import messages from '../messages';
import PageLoading from '../../PageLoading';
import Sequence from '../sequence/Sequence';
-import AlertList from '../../user-messages/AlertList';
import { fetchSequenceMetadata, checkBlockCompletion, saveSequencePosition } from '../../data/course-blocks';
import { createSequenceIdList } from '../utils';
@@ -75,35 +74,32 @@ function SequenceContainer(props) {
const isLastUnit = sequenceIds.indexOf(sequenceId) === sequenceIds.length - 1
&& unitIds.indexOf(unitId) === unitIds.length - 1;
return (
- <>
-
-
- {isLoading ? (
-
- ) : (
-
- )}
-
- >
+
+ {isLoading ? (
+
+ ) : (
+
+ )}
+
);
}
diff --git a/src/courseware/sequence/Sequence.jsx b/src/courseware/sequence/Sequence.jsx
index 394775cb..6286364b 100644
--- a/src/courseware/sequence/Sequence.jsx
+++ b/src/courseware/sequence/Sequence.jsx
@@ -4,16 +4,14 @@ import React, {
} from 'react';
import PropTypes from 'prop-types';
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
-import { injectIntl, intlShape, FormattedMessage } from '@edx/frontend-platform/i18n';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';
-import { Button } from '@edx/paragon';
+import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import Unit from './Unit';
import SequenceNavigation from './SequenceNavigation';
import PageLoading from '../../PageLoading';
import messages from './messages';
import UserMessagesContext from '../../user-messages/UserMessagesContext';
+import UnitNavigation from './UnitNavigation';
const ContentLock = React.lazy(() => import('./content-lock'));
@@ -102,7 +100,7 @@ function Sequence({
}, [activeUnitId]);
return (
- <>
+
-
+
{isGated && (
)}
-
- {unitHasLoaded ? (
-
-
{
+ {unitHasLoaded && (
+ {
logEvent('edx.ui.lms.sequence.previous_selected', 'bottom');
handlePrevious();
}}
- >
-
-
-
- {isLastUnit ? (
-
- 🤗 {/* This is a hugging face emoji */}
- {' '}
- {intl.formatMessage(messages['learn.end.of.course'])}
-
- ) : (
-
{
- logEvent('edx.ui.lms.sequence.next_selected', 'bottom');
- handleNext();
- }}
- disabled={isLastUnit}
- >
-
-
-
- )}
-
- ) : null}
- >
+ onClickNext={() => {
+ logEvent('edx.ui.lms.sequence.next_selected', 'bottom');
+ handleNext();
+ }}
+ isLastUnit={isLastUnit}
+ />
+ )}
+
+
);
}
diff --git a/src/courseware/sequence/Unit.jsx b/src/courseware/sequence/Unit.jsx
index 55030272..07975e80 100644
--- a/src/courseware/sequence/Unit.jsx
+++ b/src/courseware/sequence/Unit.jsx
@@ -43,26 +43,26 @@ function Unit({
};
return (
- <>
-
-
{displayName}
-
+ {displayName}
+
+
+
-
- >
+
);
}
diff --git a/src/courseware/sequence/UnitNavigation.jsx b/src/courseware/sequence/UnitNavigation.jsx
new file mode 100644
index 00000000..988ca21f
--- /dev/null
+++ b/src/courseware/sequence/UnitNavigation.jsx
@@ -0,0 +1,68 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Button } from '@edx/paragon';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';
+import { FormattedMessage } from '@edx/frontend-platform/i18n';
+
+export default function UnitNavigation(props) {
+ const {
+ isFirstUnit,
+ isLastUnit,
+ onClickPrevious,
+ onClickNext,
+ } = props;
+
+ return (
+
+
+
+
+
+ {isLastUnit ? (
+
+ 🤗 {/* This is a hugging face emoji */}
+ {' '}
+
+
+ ) : (
+
+
+
+
+ )}
+
+ );
+}
+
+UnitNavigation.propTypes = {
+ isFirstUnit: PropTypes.bool,
+ isLastUnit: PropTypes.bool,
+ onClickPrevious: PropTypes.func.isRequired,
+ onClickNext: PropTypes.func.isRequired,
+};
+
+UnitNavigation.defaultProps = {
+ isFirstUnit: false,
+ isLastUnit: false,
+};
diff --git a/src/courseware/sequence/messages.js b/src/courseware/sequence/messages.js
index 9c04cc9b..fc3007bd 100644
--- a/src/courseware/sequence/messages.js
+++ b/src/courseware/sequence/messages.js
@@ -6,11 +6,6 @@ const messages = defineMessages({
defaultMessage: 'Loading locked content messaging...',
description: 'Message shown when an interface about locked content is being loaded',
},
- 'learn.end.of.course': {
- id: 'learn.end.of.course',
- defaultMessage: "You've reached the end of this course!",
- description: "Message shown to students in place of a 'Next' button when they're at the end of a course.",
- },
});
export default messages;
diff --git a/src/index.scss b/src/index.scss
index 995bd2d6..3954a6ef 100755
--- a/src/index.scss
+++ b/src/index.scss
@@ -48,6 +48,7 @@ $primary: #1176B2;
.course-tabs-navigation {
border-bottom: solid 1px #EAEAEA;
}
+
.nav-underline-tabs {
margin: 0 0 -1px;
.nav-link {
@@ -70,19 +71,35 @@ $primary: #1176B2;
}
}
-.course-content-container {
- border: solid 1px #EAEAEA;
- border-radius: 4px;
- margin-bottom: 4rem;
+.sequence-container {
display: flex;
flex-direction: column;
flex-grow: 1;
+ margin-bottom: 4rem;
+ // On mobile, the unit container will be responsible
+ // for container padding.
+ @media (min-width: map-get($grid-breakpoints, 'sm')) {
+ max-width: 1440px;
+ width: 100%;
+ padding: 0 $grid-gutter-width;
+ margin-right: auto;
+ margin-left: auto;
+ }
}
+.sequence {
+ @media (min-width: map-get($grid-breakpoints, 'sm')) {
+ border: solid 1px #EAEAEA;
+ border-radius: 4px;
+ }
+}
.sequence-navigation {
display: flex;
- margin: -1px -1px 0;
+ @media (min-width: map-get($grid-breakpoints, 'sm')) {
+ margin: -1px -1px 0;
+ }
+
.btn {
flex-grow: 1;
display: block;
@@ -92,7 +109,7 @@ $primary: #1176B2;
position: relative;
font-weight: 400;
flex-basis: 80%;
- padding: .5rem;
+ padding: .625rem .375rem;
color: theme-color('gray', 400);
&:hover,
@@ -100,7 +117,6 @@ $primary: #1176B2;
&.active {
color: theme-color('gray', 700);
}
-
&:focus {
z-index: 1;
}
@@ -123,6 +139,7 @@ $primary: #1176B2;
margin-left: 0;
}
}
+
.previous-btn, .next-btn {
flex-basis: 10em;
min-width: 9em;
@@ -131,47 +148,65 @@ $primary: #1176B2;
justify-content: center;
align-items: center;
}
+
.previous-btn {
- border-top-left-radius: 4px;
+ border-left-width: 0;
+ @media (min-width: map-get($grid-breakpoints, 'sm')) {
+ border-left-width: 1px;
+ border-top-left-radius: 4px;
+ }
}
+
.next-btn {
- border-top-right-radius: 4px;
+ border-right-width: 0;
+ @media (min-width: map-get($grid-breakpoints, 'sm')) {
+ border-top-right-radius: 4px;
+ border-right-width: 1px;
+ }
}
}
-.unit-content-container {
- padding-left: 20px;
- padding-right: 20px;
+.unit-container {
+ padding: 0 $grid-gutter-width 2rem;
max-width: 1024px;
margin-left: auto;
margin-right: auto;
- width: 100%;
@media (min-width: 830px) {
padding-left: 40px;
padding-right: 40px;
}
}
-.below-unit-navigation {
+.unit-iframe-wrapper {
+ margin: 0 -20px 2rem;
+ @media (min-width: 830px) {
+ margin: 0 -40px 2rem;
+ }
+}
+
+#unit-iframe {
+ width: 100%;
+ border: none;
+ display: block;
+}
+
+.unit-navigation {
display: flex;
justify-content: center;
- margin-top: 2rem;
- margin-bottom: 2rem;
- padding-left: 6rem;
- padding-right: 6rem;
+ max-width: 640px;
+ margin: 0 auto;
.previous-button,
.next-button {
+ white-space: nowrap;
border-radius: 4px;
&:focus:before {
border-radius: 6px;
}
}
+ .next-button {
+ flex-basis: 75%;
+ }
+ .previous-button {
+ flex-basis: 25%;
+ }
}
-
-#unit-iframe {
- max-width: 1024px;
- width: 100%;
- margin: 0 auto;
- border: none;
- display: block;
-}
\ No newline at end of file
diff --git a/src/tabs/Tabs.jsx b/src/tabs/Tabs.jsx
index 32e7a58d..56308888 100644
--- a/src/tabs/Tabs.jsx
+++ b/src/tabs/Tabs.jsx
@@ -65,7 +65,7 @@ export default function Tabs({ children, className, ...attrs }) {
// All tabs will be rendered. Those that would overflow are set to invisible.
const wrappedChildren = childrenArray.map((child, index) => (
-
+
{React.cloneElement(child)}
));
@@ -78,7 +78,7 @@ export default function Tabs({ children, className, ...attrs }) {
// it so it can be part of measurements)
wrappedChildren.splice(cutOffIndex, 0, (
= React.Children.count(children) ? invisibleStyle : null}
ref={overflowEl}
>