feat: add tooltip for Other in grade distribution (#709)
* feat: add tooltip * refactor: lint happy * chore: lint --------- Co-authored-by: Derek Chen <derex1987@gmail.com>
This commit is contained in:
44
src/views/components/common/Tooltip.tsx
Normal file
44
src/views/components/common/Tooltip.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import clsx from 'clsx';
|
||||
import type { PropsWithChildren, ReactNode } from 'react';
|
||||
import React from 'react';
|
||||
|
||||
interface TooltipProps {
|
||||
className?: string;
|
||||
contentClassName?: string;
|
||||
content: ReactNode;
|
||||
offsetX: number;
|
||||
offsetY: number;
|
||||
maxWidth?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tooltip that displays content on hover
|
||||
*/
|
||||
export default function Tooltip({
|
||||
className,
|
||||
contentClassName,
|
||||
content,
|
||||
offsetX,
|
||||
offsetY,
|
||||
maxWidth,
|
||||
children,
|
||||
}: PropsWithChildren<TooltipProps>): JSX.Element {
|
||||
return (
|
||||
<span className={clsx('relative inline-flex group', className)}>
|
||||
{children}
|
||||
<span
|
||||
className={clsx(
|
||||
'pointer-events-none absolute rounded-md bg-white px-3 py-2 text-xs invisible opacity-0 transition-opacity group-hover:visible group-hover:opacity-100 whitespace-normal break-words',
|
||||
contentClassName
|
||||
)}
|
||||
style={{
|
||||
marginTop: offsetY,
|
||||
marginLeft: offsetX,
|
||||
maxWidth,
|
||||
}}
|
||||
>
|
||||
{content}
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import type { Distribution, LetterGrade } from '@shared/types/Distribution';
|
||||
import { extendedColors } from '@shared/types/ThemeColors';
|
||||
import Link from '@views/components/common/Link';
|
||||
import Text from '@views/components/common/Text/Text';
|
||||
import Tooltip from '@views/components/common/Tooltip';
|
||||
import {
|
||||
NoDataError,
|
||||
queryAggregateDistribution,
|
||||
@@ -12,10 +13,12 @@ import Highcharts from 'highcharts';
|
||||
import HighchartsReact from 'highcharts-react-official';
|
||||
import type { ChangeEvent } from 'react';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { renderToStaticMarkup } from 'react-dom/server';
|
||||
import Skeleton from 'react-loading-skeleton';
|
||||
|
||||
const UT_GRADE_DISTRIBUTION_URL = 'https://reports.utexas.edu/spotlight-data/ut-course-grade-distributions';
|
||||
|
||||
const TOOLTIP_CONTENT =
|
||||
"The 'Other' grade category includes all non-standard letter grades, including: In Progress, Incomplete, Permanent Incomplete, Oblit, Q-Drop, Withdrawn, Credit, No Credit, Satisfactory, Unsatisfactory, and Registered on CR/F or CR/NC basis.";
|
||||
interface GradeDistributionProps {
|
||||
course: Course;
|
||||
}
|
||||
@@ -126,6 +129,25 @@ export default function GradeDistribution({ course }: GradeDistributionProps): J
|
||||
lineHeight: 'normal',
|
||||
fontStyle: 'normal',
|
||||
},
|
||||
useHTML: true,
|
||||
formatter() {
|
||||
// eslint-disable-next-line react/no-this-in-sfc
|
||||
const val = `${this.value}`;
|
||||
|
||||
return val === 'Other'
|
||||
? renderToStaticMarkup(
|
||||
<Tooltip
|
||||
content={TOOLTIP_CONTENT}
|
||||
className='underline'
|
||||
offsetX={-425}
|
||||
offsetY={-175}
|
||||
maxWidth={500}
|
||||
>
|
||||
Other
|
||||
</Tooltip>
|
||||
)
|
||||
: val;
|
||||
},
|
||||
},
|
||||
title: {
|
||||
text: 'Grades',
|
||||
@@ -135,6 +157,7 @@ export default function GradeDistribution({ course }: GradeDistributionProps): J
|
||||
fontWeight: '400',
|
||||
},
|
||||
},
|
||||
|
||||
categories: ['A', 'A-', 'B+', 'B', 'B-', 'C+', 'C', 'C-', 'D+', 'D', 'D-', 'F', 'Other'],
|
||||
tickInterval: 1,
|
||||
tickWidth: 1,
|
||||
|
||||
@@ -4,10 +4,10 @@ import React from 'react';
|
||||
* Lightweight skeleton placeholder for contributor cards while data loads
|
||||
*/
|
||||
export const ContributorCardSkeleton: React.FC = () => (
|
||||
<div className='border border-gray-300 rounded bg-ut-gray/10 p-4 animate-pulse'>
|
||||
<div className='h-4 w-3/4 bg-gray-300 rounded mb-2' />
|
||||
<div className='h-3 w-1/2 bg-gray-300 rounded mb-1' />
|
||||
<div className='h-3 w-1/4 bg-gray-300 rounded' />
|
||||
<div className='animate-pulse border border-gray-300 rounded bg-ut-gray/10 p-4'>
|
||||
<div className='mb-2 h-4 w-3/4 rounded bg-gray-300' />
|
||||
<div className='mb-1 h-3 w-1/2 rounded bg-gray-300' />
|
||||
<div className='h-3 w-1/4 rounded bg-gray-300' />
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user