add legend component#27
Conversation
|
|
||
| export const YEAR_COLOUR_DEFAULT = 'border-gray-300'; | ||
|
|
||
| export const YEAR_COLOUR: Record<string, string> = { |
There was a problem hiding this comment.
This currently fails CI since constants are exported from a file that also exports components.
Extract YEAR_COLOUR_DEFAULT and YEAR_COLOUR into a module: src/lib/yearColour.ts. This should export YEAR_COLOUR (for the legend to enumerate), YEAR_COLOUR_DEFAULT, and a yearColour(code) helper, then import from both CourseNode and ExplorerLegend. Draft fix (confirm it works, may need slight changes if not):
// content for src/lib/yearColour.ts
export const YEAR_COLOUR_DEFAULT = 'border-gray-300';
export const YEAR_COLOUR: Record<string, string> = {
'1': 'border-green-500',
'2': 'border-blue-500',
'3': 'border-yellow-500',
'4': 'border-red-500',
};
export function yearColour(code: string): string {
const digit = code.match(/\d/)?.[0];
return (digit && YEAR_COLOUR[digit]) ?? YEAR_COLOUR_DEFAULT;
}
| const match = data.code.match(/\d/); | ||
| const borderColour = match ? YEAR_COLOUR[match[0]] : YEAR_COLOUR_DEFAULT; |
There was a problem hiding this comment.
This can be replaced with the yearColour helper mentioned in the comment above.
Also note about the borderColour line:
This ternary checks if there is a digit present, not whether it's a known (1-4) or unknown (0 / 5-9) digit. A course code that has an unknown digit (e.g. 5) still uses the truth case, tries to match it to the YEAR_COLOUR map, finds no match, and renders with no colour (this is a hypothetical since current data only has digits 1-4, but it may not always be the case)
The yearColour helper proposed in the comment above should fix this using the nullish coalescing operator
| <div className="flex gap-2"> | ||
| <button className="hover:text-red-600" onClick={() => setOpen(!open)}> | ||
| {open ? '▲' : '▼'} | ||
| </button> | ||
| <p className="flex-1 font-semibold">Legend</p> | ||
| </div> |
There was a problem hiding this comment.
Right now the legend is only toggled by clicking on the arrow. Making the whole legend bar clickable to toggle may be better for UX.
Also, instead of the raw triangles for the icon, we could use the ChevronUp / ChevronDown icons from lucide-react instead. I pushed a commit to main with the install, so you'd just have to import them in the file and use them like the code snippet below.
Make the full row a button instead and add an aria-expanded line. Roughly something like:
<button
type="button"
onClick={() => setOpen(!open)}
aria-expanded={open}
className="flex w-full items-center gap-2"
>
{open ? <ChevronUp size={16} /> : <ChevronDown size={16} />}
<span className="flex-1 text-left font-semibold">Legend</span>
</button>
| {open && ( | ||
| <div className="flex flex-col gap-1 border-t border-gray-300 pt-1 mt-2"> | ||
| {Object.entries(YEAR_COLOUR).map(([key, colour]) => ( | ||
| <div className={`${div}`}> |
There was a problem hiding this comment.
This Object.entries line returns a div with no key, add a key={key} here
| const div = 'flex flex-row gap-2'; | ||
| const colouredDiv = 'w-9 h-4 border-2 self-center rounded'; |
There was a problem hiding this comment.
Naming the class strings after a common HTML element (div) could be a bit confusing. Something like rowClass and boxClass (or similar) would be better
No description provided.