Skip to content

Commit

Permalink
Merge course popovers (#551)
Browse files Browse the repository at this point in the history
* feat: merge warning into course popover

* feat: replace info icon with warning icon if issue

* feat: make popover styles conform more to figma

* feat: increase popover arrow size

* fix: correct popover directions with arrows

* fix: popover sizing details

* feat: popover arrow shadow

* refactor: move course popover to new component

* fix: course popover line heights

* fix: course popover props interface

* fix: popover position on mobile

* refactor: remove separate popover position classes

* Adjust styles of tooltip

* fix tooltips in other directions

* fix: bottom popover arrow color

* fix: course popover position issue

---------

Co-authored-by: Cadecraft <[email protected]>
Co-authored-by: Awesome-E <[email protected]>
  • Loading branch information
3 people authored Jan 22, 2025
1 parent c4d9029 commit 9a92bd3
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 71 deletions.
74 changes: 74 additions & 0 deletions site/src/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,80 @@ button {
}
}

.ppc-popover {
border-radius: 8px;
padding: 0px;
box-shadow: none;
max-width: 375px;
top: -16px !important;

$filter: drop-shadow(0px 0px 16px rgba(0, 0, 0, 0.35));
filter: $filter;
-webkit-filter: $filter;
border: none;

.popover-body {
border-radius: 8px;
padding: 16px;
}

.arrow {
z-index: -1;
&::after {
display: none;
}
}
.arrow::before {
pointer-events: none;
position: absolute;
border: 8px solid transparent;
border-width: 12px 16px;
top: 8px;
left: unset;
}
&[data-popper-placement='bottom'] {
top: -24px !important;
.arrow::before {
left: 0;
bottom: 0;
top: 8px;
border-bottom-color: var(--overlay1);
transform: translate(-25%, -100%);
border-width: 16px 12px;
}
}
&[data-popper-placement='left-start'] {
.arrow::before {
left: -2px;
border-left-color: var(--overlay1);
}
}
&[data-popper-placement='right-start'] {
.arrow::before {
right: -2px;
border-right-color: var(--overlay1);
}
}
}

.bs-popover-left {
margin-right: 20px;

.arrow::after,
.arrow::before {
left: -1px;
}
}

.bs-popover-bottom {
margin-top: 48px;
.arrow::after,
.arrow::before {
top: -12px;
left: 7px;
}
}

.ppc-modal {
font-size: 18px;

Expand Down
62 changes: 62 additions & 0 deletions site/src/component/CoursePopover/CoursePopover.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
.course-popover {
line-height: normal;

.popover-name {
font-weight: bold;
color: var(--text-dark);
font-size: 16px;
height: 21px;
margin-top: -2px;
}

.popover-subtitle {
font-weight: bold;
}

.popover-units {
font-weight: normal;
}

.popover-description {
font-size: 14px;
padding-top: 12px;
line-height: 17px;
}

.popover-detail {
padding-top: 12px;
}

.popover-detail-prefix {
font-weight: bold;
}

.popover-detail-warning {
font-size: 14px;
color: #ce0000;
gap: 5px;

.popover-detail-warning-icon {
margin-bottom: 4px;
margin-right: 4px;
font-size: 16px;
}
}

.popover-detail-italics {
padding-top: 6px;
font-weight: 400;
font-size: 12px;
font-style: italic;
color: var(--petr-gray);
}
}

[data-theme='dark'] {
.popover-detail-warning {
color: red;
}
.popover-detail-italics {
color: var(--petr-gray);
}
}
68 changes: 68 additions & 0 deletions site/src/component/CoursePopover/CoursePopover.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { FC } from 'react';
import './CoursePopover.scss';
import { ExclamationTriangle } from 'react-bootstrap-icons';
import Popover from 'react-bootstrap/Popover';

interface CoursePopoverProps {
department: string;
courseNumber: string;
title: string;
minUnits: number;
maxUnits: number;
description: string;
prerequisiteText: string;
corequisites: string;
requiredCourses?: string[];
}

const CoursePopover: FC<CoursePopoverProps> = (props) => {
const {
department,
courseNumber,
title,
minUnits,
maxUnits,
description,
prerequisiteText,
corequisites,
requiredCourses,
} = props;

return (
<Popover.Content className="course-popover">
<div className="popover-name">
{department + ' ' + courseNumber + ' '}
<span className="popover-units">({minUnits === maxUnits ? minUnits : `${minUnits}-${maxUnits}`} units)</span>
</div>
<div className="popover-description">
<span className="popover-subtitle">{title + ':'}</span>
<br />
{description}
</div>
{prerequisiteText && (
<div className="popover-detail">
<span className="popover-detail-prefix">Prerequisites:</span> {prerequisiteText}
</div>
)}
{corequisites && (
<div className="popover-detail">
<span className="popover-detail-prefix">Corequisites:</span> {corequisites}
</div>
)}
{requiredCourses && (
<div className="popover-detail">
<div className="popover-detail-warning">
<ExclamationTriangle className="popover-detail-warning-icon" />
Prerequisite{requiredCourses?.length > 1 ? 's' : ''} Not Met: {requiredCourses?.join(', ')}
</div>
<div className="popover-detail-italics">
Already completed? Click "Transfer Credits" at the top of the roadmap viewer to add{' '}
{requiredCourses?.length > 1 ? 'these prerequisites' : 'this prerequisite'}.
</div>
</div>
)}
</Popover.Content>
);
};

export default CoursePopover;
29 changes: 0 additions & 29 deletions site/src/pages/RoadmapPage/Course.scss
Original file line number Diff line number Diff line change
Expand Up @@ -66,35 +66,6 @@
color: red;
}

.course-popover {
padding: 5%;

.popover-name {
font-weight: bold;
color: var(--text-dark);
font-size: 16px;
}

.popover-units {
color: #c4c4c4;

.popover-units-value {
font-weight: bold;
}
}

.popover-description {
padding-top: 5%;
}

.popover-detail {
padding-top: 5%;
}
.popover-detail-prefix {
font-weight: bold;
}
}

.course-footer {
height: auto;
display: flex;
Expand Down
67 changes: 26 additions & 41 deletions site/src/pages/RoadmapPage/Course.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import './Course.scss';
import { Button } from 'react-bootstrap';
import { InfoCircle, ExclamationTriangle, Trash, BagPlus, BagFill } from 'react-bootstrap-icons';
import CourseQuarterIndicator from '../../component/QuarterTooltip/CourseQuarterIndicator';
import CoursePopover from '../../component/CoursePopover/CoursePopover';
import OverlayTrigger from 'react-bootstrap/OverlayTrigger';
import Popover from 'react-bootstrap/Popover';
import { useIsMobile } from '../../helpers/util';

import { CourseGQLData } from '../../types/types';
import ThemeContext from '../../style/theme-context';
Expand All @@ -27,6 +29,7 @@ interface CourseProps extends CourseGQLData {
onAddToBag?: () => void;
isInBag?: boolean;
removeFromBag?: () => void;
openPopoverLeft?: boolean;
addMode?: 'tap' | 'drag';
}

Expand All @@ -47,45 +50,13 @@ const Course: FC<CourseProps> = (props) => {
onAddToBag,
isInBag,
removeFromBag,
openPopoverLeft,
} = props;
const CoursePopover = (
<Popover id={'course-popover-' + id}>
<Popover.Content>
<div className="course-popover">
<div className="popover-name">
{department + ' ' + courseNumber} {title}
</div>
<div className="popover-units">
<span className="popover-units-value">{minUnits === maxUnits ? minUnits : `${minUnits}-${maxUnits}`}</span>{' '}
units
</div>
<div className="popover-description">{description}</div>
{prerequisiteText && (
<div className="popover-detail">
<span className="popover-detail-prefix">Prerequisites:</span> {prerequisiteText}
</div>
)}
{corequisites && (
<div className="popover-detail">
<span className="popover-detail-prefix">Corequisites:</span> {corequisites}
</div>
)}
</div>
</Popover.Content>
</Popover>
);

const dispatch = useAppDispatch();

const warningPopover = (
<Popover id={'warning-popover-' + id}>
<Popover.Content>
<UnmetPrerequisiteText requiredCourses={requiredCourses} />
</Popover.Content>
</Popover>
);

const courseRoute = '/course/' + props.department.replace(/\s+/g, '') + props.courseNumber.replace(/\s+/g, '');
const isMobile = useIsMobile();

const insertCourseOnClick = () => {
dispatch(setActiveCourse(props));
Expand All @@ -105,14 +76,28 @@ const Course: FC<CourseProps> = (props) => {
<span className="units">
{minUnits === maxUnits ? minUnits : `${minUnits}-${maxUnits}`} unit{maxUnits === 1 ? '' : 's'}
</span>
<OverlayTrigger trigger={['hover', 'focus']} placement="auto" overlay={CoursePopover} delay={100}>
<InfoCircle />
<OverlayTrigger
trigger={['hover', 'focus']}
placement={isMobile ? 'bottom' : openPopoverLeft ? 'left-start' : 'right-start'}
overlay={
<Popover className="ppc-popover" id={'course-popover-' + id}>
<CoursePopover
department={department}
courseNumber={courseNumber}
title={title}
minUnits={minUnits}
maxUnits={maxUnits}
description={description}
prerequisiteText={prerequisiteText}
corequisites={corequisites}
requiredCourses={requiredCourses}
/>
</Popover>
}
delay={100}
>
<div style={{ display: 'flex' }}>{requiredCourses ? <ExclamationTriangle /> : <InfoCircle />}</div>
</OverlayTrigger>
{requiredCourses && (
<OverlayTrigger trigger={['hover', 'focus']} placement="right" overlay={warningPopover} delay={100}>
<ExclamationTriangle />
</OverlayTrigger>
)}
</div>
<div className="spacer"></div>
{onDelete ? (
Expand Down
2 changes: 1 addition & 1 deletion site/src/pages/RoadmapPage/SearchSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ const SearchSidebar = () => {
className={'search-body' + (isMobile ? ' disabled' : '')}
>
{shownCourses.map((course, i) => (
<Course {...course} key={i} addMode={isMobile ? 'tap' : 'drag'} />
<Course {...course} key={i} addMode={isMobile ? 'tap' : 'drag'} openPopoverLeft={true} />
))}
</ReactSortable>
) : (
Expand Down
3 changes: 3 additions & 0 deletions site/src/style/theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@
}
}

.popover {
background-color: var(--overlay1);
}
.popover-body {
background-color: var(--overlay1);
color: var(--text);
Expand Down

0 comments on commit 9a92bd3

Please sign in to comment.