Skip to content

Commit

Permalink
Create new chip components to represent status and grade status
Browse files Browse the repository at this point in the history
  • Loading branch information
acelaya committed Sep 5, 2024
1 parent 1a4d5dd commit 9fdb91b
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 1 deletion.
33 changes: 33 additions & 0 deletions lms/static/scripts/frontend_apps/components/StatusChip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import classnames from 'classnames';
import type { ComponentChildren } from 'preact';

export type StatusChipProps = {
/**
* Determines the aspect of the status chip, being "top" the one representing
* the most successful status, and "bottom" the one representing a total
* failure.
*/
variant: 'top' | 'high' | 'medium' | 'low' | 'bottom';

children?: ComponentChildren;
};

/**
* A status chip (AKA label or tag) that visually represents the success level
* on a scale of 1 to 5
*/
export default function StatusChip({ variant, children }: StatusChipProps) {
return (
<div
className={classnames('rounded font-bold inline-block px-2 py-0.5', {
'bg-green-success text-white': variant === 'top',
'bg-green-200 text-green-900': variant === 'high',
'bg-amber-100 text-amber-900': variant === 'medium',
'bg-red-200 text-red-900': variant === 'low',
'bg-red-error text-white': variant === 'bottom',
})}
>
{children}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useMemo } from 'preact/hooks';

import type { StatusChipProps } from '../StatusChip';
import StatusChip from '../StatusChip';

export type GradeStatusChipProps = {
/**
* A grade, from 0 to 100, that will be used to render the corresponding
* StatusChip.
*
* 100 - top
* 80-99 - high
* 50-79 - medium
* 1-49 - low
* 0 - bottom
*/
grade: number;
};

/**
* A StatusChip where the corresponding variant is calculated from a grade
* from 0 to 100
*
* See {@link StatusChip}
*/
export default function GradeStatusChip({ grade }: GradeStatusChipProps) {
const variant = useMemo((): StatusChipProps['variant'] => {
if (grade === 100) {
return 'top';
} else if (grade >= 80 && grade < 100) {
return 'high';
} else if (grade >= 50 && grade < 80) {
return 'medium';
} else if (grade >= 1 && grade < 50) {
return 'low';
}

return 'bottom';
}, [grade]);

return <StatusChip variant={variant}>{grade}%</StatusChip>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Library from '@hypothesis/frontend-shared/lib/pattern-library/components/Library';

import StatusChip from '../../frontend_apps/components/StatusChip';
import GradeStatusChip from '../../frontend_apps/components/dashboard/GradeStatusChip';

export default function GradeStatusChipPage() {
return (
<Library.Page title="Grade status chip">
<Library.Section title="Standard StatusChip">
<p>
It can render any kind of content. The color can be customized via{' '}
<code>variant</code> prop.
</p>
<Library.Demo withSource>
<StatusChip variant="top">Top</StatusChip>
<StatusChip variant="high">High</StatusChip>
<StatusChip variant="medium">Medium</StatusChip>
<StatusChip variant="low">Low</StatusChip>
<StatusChip variant="bottom">Bottom</StatusChip>
</Library.Demo>
</Library.Section>
<Library.Section title="GradeStatusChip">
<p>
It renders a <code>StatusChip</code> by automatically calculating the
right variant, based on a grade from 0 to 100.
</p>
<Library.Demo withSource>
<GradeStatusChip grade={100} />
<GradeStatusChip grade={80} />
<GradeStatusChip grade={68} />
<GradeStatusChip grade={38} />
<GradeStatusChip grade={0} />
</Library.Demo>
</Library.Section>
</Library.Page>
);
}
10 changes: 9 additions & 1 deletion lms/static/scripts/ui-playground/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,16 @@
import { startApp } from '@hypothesis/frontend-shared/lib/pattern-library';
import type { CustomPlaygroundRoute } from '@hypothesis/frontend-shared/lib/pattern-library/routes';

import GradeStatusChipPage from './components/GradeStatusChipPage';

// LMS prototype pages should be defined here
const extraRoutes: CustomPlaygroundRoute[] = [];
const extraRoutes: CustomPlaygroundRoute[] = [
{
component: GradeStatusChipPage,
route: '/grade-status-chip',
title: 'Grade status chip',
},
];

startApp({
baseURL: '/ui-playground',
Expand Down

0 comments on commit 9fdb91b

Please sign in to comment.