Skip to content

Commit 7049445

Browse files
committed
chore: update to paragon 19.0.0
Adapt to the big <Card> redesign. Also, as part of 19.0.0, the shadow variables in paragon got marked as !default, letting the theme override them. This would normally be fine and good. But the edx.org theme has a dramatically larger shadow set. And a lot of our cards and card-like components were designed with a smaller shadow in mind. So I added a new raised-card custom css class to keep as many cards looking the same. Notably, I cannot fix the data tables on the Progress tab. So those might have a larger shadow with this change, but that's unavoidable and presumably the intent of the edx.org theme authors.
1 parent f17a635 commit 7049445

File tree

12 files changed

+102
-109
lines changed

12 files changed

+102
-109
lines changed

package-lock.json

+32-15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"@edx/frontend-enterprise-utils": "1.1.1",
3737
"@edx/frontend-lib-special-exams": "1.15.5",
3838
"@edx/frontend-platform": "1.14.3",
39-
"@edx/paragon": "17.1.2",
39+
"@edx/paragon": "19.0.0",
4040
"@edx/frontend-component-header": "^2.4.2",
4141
"@fortawesome/fontawesome-svg-core": "1.2.36",
4242
"@fortawesome/free-brands-svg-icons": "5.15.4",

src/course-home/outline-tab/widgets/StartOrResumeCourseCard.jsx

+16-18
Original file line numberDiff line numberDiff line change
@@ -41,24 +41,22 @@ function StartOrResumeCourseCard({ intl }) {
4141
};
4242

4343
return (
44-
<Card className="mb-3 shadow-sm border-0" data-testid="start-resume-card">
45-
<Card.Body>
46-
<div className="row w-100 m-0 justify-content-between align-items-center">
47-
<div className="col-12 col-md-7 p-0 mb-3 mb-md-0">
48-
<h2 className="h3 m-0">{hasVisitedCourse ? intl.formatMessage(messages.resumeBlurb) : intl.formatMessage(messages.startBlurb)}</h2>
49-
</div>
50-
<div className="col-12 col-md-auto p-0">
51-
<Button
52-
variant="brand"
53-
block
54-
href={resumeCourseUrl}
55-
onClick={() => logResumeCourseClick()}
56-
>
57-
{hasVisitedCourse ? intl.formatMessage(messages.resume) : intl.formatMessage(messages.start)}
58-
</Button>
59-
</div>
60-
</div>
61-
</Card.Body>
44+
<Card className="mb-3 raised-card" data-testid="start-resume-card">
45+
<Card.Header
46+
title={hasVisitedCourse ? intl.formatMessage(messages.resumeBlurb) : intl.formatMessage(messages.startBlurb)}
47+
actions={(
48+
<Button
49+
variant="brand"
50+
block
51+
href={resumeCourseUrl}
52+
onClick={() => logResumeCourseClick()}
53+
>
54+
{hasVisitedCourse ? intl.formatMessage(messages.resume) : intl.formatMessage(messages.start)}
55+
</Button>
56+
)}
57+
/>
58+
{/* Footer is needed for internal vertical spacing to work out. If you can remove, be my guest */}
59+
<Card.Footer />
6260
</Card>
6361
);
6462
}

src/course-home/outline-tab/widgets/WeeklyLearningGoalCard.jsx

+11-12
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,18 @@ function WeeklyLearningGoalCard({
6868
return (
6969
<Card
7070
id="courseHome-weeklyLearningGoal"
71-
className="row w-100 m-0 mb-3 shadow-sm border-0"
71+
className="row w-100 m-0 mb-3 raised-card"
7272
data-testid="weekly-learning-goal-card"
7373
>
74-
<Card.Body className="p-3 p-lg-3.5">
75-
<h2 id="set-weekly-goal-h2" className="h4 mb-1 text-primary-500">{intl.formatMessage(messages.setWeeklyGoal)}</h2>
76-
<Card.Text
77-
className="text-gray-700 small mb-2.5"
78-
>
79-
{intl.formatMessage(messages.setWeeklyGoalDetail)}
80-
</Card.Text>
74+
<Card.Header
75+
size="sm"
76+
title={(<div id="set-weekly-goal-header">{intl.formatMessage(messages.setWeeklyGoal)}</div>)}
77+
subtitle={intl.formatMessage(messages.setWeeklyGoalDetail)}
78+
/>
79+
<Card.Section className="text-gray-700 small">
8180
<div
8281
role="radiogroup"
83-
aria-labelledby="set-weekly-goal-h2"
82+
aria-labelledby="set-weekly-goal-header"
8483
className="flag-button-container m-0 p-0"
8584
>
8685
<LearningGoalButton
@@ -108,9 +107,9 @@ function WeeklyLearningGoalCard({
108107
<small>{intl.formatMessage(messages.setGoalReminder)}</small>
109108
</Form.Switch>
110109
</div>
111-
</Card.Body>
110+
</Card.Section>
112111
{isGetReminderSelected && (
113-
<Card.Footer className="border-0 px-2.5 bg-light-200">
112+
<Card.Section muted>
114113
<div className="row w-100 m-0 small align-center">
115114
<div className="d-flex align-items-center pr-1">
116115
<Icon
@@ -122,7 +121,7 @@ function WeeklyLearningGoalCard({
122121
{intl.formatMessage(messages.goalReminderDetail)}
123122
</div>
124123
</div>
125-
</Card.Footer>
124+
</Card.Section>
126125
)}
127126
</Card>
128127
);

src/course-home/outline-tab/widgets/WelcomeMessage.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ function WelcomeMessage({ courseId, intl }) {
3737
setDisplay(false);
3838
dispatch(dismissWelcomeMessage(courseId));
3939
}}
40-
className="shadow-sm border-0"
40+
className="raised-card"
4141
actions={messageCanBeShortened ? [
4242
<Button
4343
onClick={() => setShowShortMessage(!showShortMessage)}

src/course-home/progress-tab/ProgressTab.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ function ProgressTab() {
4141
<CourseCompletion />
4242
{!wideScreen && <CertificateStatus />}
4343
<CourseGrade />
44-
<div className={`grades my-4 p-4 rounded shadow-sm ${applyLockedOverlay}`} aria-hidden={gradesFeatureIsFullyLocked}>
44+
<div className={`grades my-4 p-4 rounded raised-card ${applyLockedOverlay}`} aria-hidden={gradesFeatureIsFullyLocked}>
4545
<GradeSummary />
4646
<DetailedGrades />
4747
</div>

src/course-home/progress-tab/certificate-status/CertificateStatus.jsx

+7-9
Original file line numberDiff line numberDiff line change
@@ -224,14 +224,12 @@ function CertificateStatus({ intl }) {
224224

225225
return (
226226
<section data-testid="certificate-status-component" className="text-dark-700 mb-4">
227-
<Card className="bg-light-200 shadow-sm border-0">
228-
<Card.Body>
229-
<Card.Title>
230-
<h3>{header}</h3>
231-
</Card.Title>
232-
<Card.Text className="small text-gray-700">
233-
{body}
234-
</Card.Text>
227+
<Card className="bg-light-200 raised-card">
228+
<Card.Header title={header} />
229+
<Card.Section className="small text-gray-700">
230+
{body}
231+
</Card.Section>
232+
<Card.Footer>
235233
{buttonText && (buttonLocation || buttonAction) && (
236234
<Button
237235
variant="outline-brand"
@@ -245,7 +243,7 @@ function CertificateStatus({ intl }) {
245243
{buttonText}
246244
</Button>
247245
)}
248-
</Card.Body>
246+
</Card.Footer>
249247
</Card>
250248
</section>
251249
);

src/course-home/progress-tab/course-completion/CourseCompletion.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import messages from './messages';
66

77
function CourseCompletion({ intl }) {
88
return (
9-
<section className="text-dark-700 mb-4 rounded shadow-sm p-4">
9+
<section className="text-dark-700 mb-4 rounded raised-card p-4">
1010
<div className="row w-100 m-0">
1111
<div className="col-12 col-sm-6 col-md-7 p-0">
1212
<h2>{intl.formatMessage(messages.courseCompletion)}</h2>

src/course-home/progress-tab/grades/course-grade/CourseGrade.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ function CourseGrade({ intl }) {
3030
const applyLockedOverlay = gradesFeatureIsFullyLocked ? 'locked-overlay' : '';
3131

3232
return (
33-
<section className="text-dark-700 my-4 rounded shadow-sm">
33+
<section className="text-dark-700 my-4 rounded raised-card">
3434
{(gradesFeatureIsFullyLocked || gradesFeatureIsPartiallyLocked) && <CourseGradeHeader />}
3535
<div className={applyLockedOverlay} aria-hidden={gradesFeatureIsFullyLocked}>
3636
<div className="row w-100 m-0 p-4">

src/courseware/course/course-exit/CourseRecommendations.jsx

+26-31
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ const messages = defineMessages({
2424
description: 'Header for recommendations section of course celebration',
2525
defaultMessage: 'Keep building your skills with these courses!',
2626
},
27+
recommendationsCourseFooter: {
28+
id: 'courseCelebration.recommendations.label', // not very descriptive, but is historical
29+
description: 'Label on a discovery-card that lets a user know that it is a course card',
30+
defaultMessage: 'Course',
31+
},
2732
listJoin: {
2833
id: 'courseCelebration.recommendations.formatting.list_join',
2934
description: 'Joining mark or word for a list of items, use the {sp} placeholder to include space before the joining word',
@@ -73,6 +78,20 @@ function CourseCard({
7378
intl,
7479
);
7580

81+
const subtitle = (
82+
<FormattedMessage
83+
id="courseCelebration.recommendations.card.schools.label"
84+
description="Screenreader label for the Schools and Partners running the course."
85+
defaultMessage="Schools and Partners"
86+
>{text => (
87+
<>
88+
<span className="sr-only">{text}: </span>
89+
{truncate(formattedOwners, 40, { reserveLastWord: -1 })}
90+
</>
91+
)}
92+
</FormattedMessage>
93+
);
94+
7695
return (
7796
<div
7897
role="group"
@@ -83,36 +102,12 @@ function CourseCard({
83102
className="text-decoration-none"
84103
onClick={onClick}
85104
>
86-
<Card style={{ width: '270px', height: '270px' }} className="discovery-card">
87-
<Card.Img variant="top" src={image.src} bsPrefix="d-card-hero" />
88-
<Card.Body>
89-
<Card.Title>
90-
<h3 className="h4 text-gray-700 font-weight-normal">
91-
{truncate(title, 70, { reserveLastWord: -1 })}
92-
</h3>
93-
</Card.Title>
94-
<div className="text-gray-500 small">
95-
<FormattedMessage
96-
id="courseCelebration.recommendations.card.schools.label"
97-
description="Screenreader label for the Schools and Partners running the course."
98-
defaultMessage="Schools and Partners"
99-
>{text => (
100-
<>
101-
<span className="sr-only">{text}: </span>
102-
{truncate(formattedOwners, 40, { reserveLastWord: -1 })}
103-
</>
104-
)}
105-
</FormattedMessage>
106-
</div>
107-
</Card.Body>
108-
<footer className="pl-4 pb-2 x-small text-gray-500">
109-
<FormattedMessage
110-
id="courseCelebration.recommendations.label"
111-
description="Label on a discovery-card that lets a user know that it is a course card"
112-
defaultMessage="Course"
113-
/>
114-
</footer>
115-
105+
<Card isClickable style={{ width: '21rem', height: '100%' }}>
106+
<Card.ImageCap src={image.src} />
107+
<Card.Header title={truncate(title, 70, { reserveLastWord: -1 })} subtitle={subtitle} size="sm" />
108+
{/* Section is needed for internal vertical spacing to work out. If you can remove, be my guest */}
109+
<Card.Section />
110+
<Card.Footer textElement={intl.formatMessage(messages.recommendationsCourseFooter)} />
116111
</Card>
117112
</Hyperlink>
118113
</div>
@@ -161,7 +156,7 @@ function CourseRecommendations({ intl, variant }) {
161156
}
162157

163158
if (recommendationsStatus === LOADING) {
164-
return <PageLoading srMessage={`${intl.formatMessage(messages.loadingRecommendations)}`} />;
159+
return <PageLoading srMessage={intl.formatMessage(messages.loadingRecommendations)} />;
165160
}
166161

167162
const onCardClick = (url) => (e) => {

src/courseware/course/course-exit/CourseRecommendations.scss

-19
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,4 @@
88
}
99
}
1010
}
11-
12-
.discovery-card {
13-
&:hover,
14-
&:focus {
15-
box-shadow: 0 2px 4px 2px $gray-500
16-
}
17-
}
18-
19-
.d-card-hero-top {
20-
height: 102px;
21-
min-height: 102px;
22-
background-color: $gray-200;
23-
overflow: hidden;
24-
border: {
25-
radius: 3px 3px 0 0;
26-
bottom: 1px solid $success-100;
27-
}
28-
}
29-
3011
}

src/index.scss

+5
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,11 @@
356356
}
357357
}
358358

359+
.raised-card {
360+
border: 0 !important;
361+
box-shadow: 0 .0625rem .125rem rgba(0, 0, 0, .2) !important;
362+
}
363+
359364
// Import component-specific sass files
360365
@import "courseware/course/celebration/CelebrationModal.scss";
361366
@import "courseware/course/NotificationTray.scss";

0 commit comments

Comments
 (0)