Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions codewit/client/src/components/typography.tsx
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking: should this file be renamed to typography.tsx before more imports depend on the typeography spelling?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I should probably fix my bad spelling

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { ComponentProps, forwardRef } from "react";

import { cn } from "../utils/styles";

/*
* since some of the header elements currently being used on the site seem
* somewhat arbitrary, the only consistent styling is just the highlight
* color.
*
* when we want more consistency we can use these to enforce specific
* styling.
*
* the current elements (2026/04/24) are 1:1 replacement for base html
* elements and only modify the styling and everything else is just passed
* through without changes.
*/

export const H1 = forwardRef<HTMLHeadingElement, ComponentProps<"h1">>(({className, ...props}, ref) => {
return <h1
ref={ref}
className={cn("text-highlight-500", className)}
{...props}
/>;
});
H1.displayName = "H1";
Comment on lines +18 to +25
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice abstraction overall.

One thing to maybe tweak: these heading wrappers pass children through {...props}, which still renders correctly, but eslint can’t detect the heading content and raises jsx-a11y/heading-has-content on each helper.

Could we destructure children explicitly and render it inside the heading element? That should keep the behavior the same and avoid the new lint noise.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was a similar process as to what I have done with a different project. the idea being that they only thing that needs to be extracted is and then everything else is just passed through without worrying about what it is.

if we are starting to use eslint then I can make the change otherwise I am inclined to leave it as me taking it out just to manually pass it in seems unnecessary.


export const H2 = forwardRef<HTMLHeadingElement, ComponentProps<"h2">>(({className, ...props}, ref) => {
return <h2
ref={ref}
className={cn("text-highlight-500", className)}
{...props}
/>;
});
H2.displayName = "H2";

export const H3 = forwardRef<HTMLHeadingElement, ComponentProps<"h3">>(({className, ...props}, ref) => {
return <h3
ref={ref}
className={cn("text-highlight-500", className)}
{...props}
/>;
});
H3.displayName = "H3";

export const H4 = forwardRef<HTMLHeadingElement, ComponentProps<"h4">>(({className, ...props}, ref) => {
return <h4
ref={ref}
className={cn("text-highlight-500", className)}
{...props}
/>;
});
H4.displayName = "H4";

export const H5 = forwardRef<HTMLHeadingElement, ComponentProps<"h5">>(({className, ...props}, ref) => {
return <h5
ref={ref}
className={cn("text-highlight-500", className)}
{...props}
/>;
});
H5.displayName = "H5";
5 changes: 3 additions & 2 deletions codewit/client/src/pages/ImportExercisesPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import axios from "axios";
import { toast } from "react-toastify";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { EXERCISES_KEY } from "../hooks/useExercises";
import { H3 } from "../components/typography";

type ImportResponse = { ok: boolean; created: number; updated: number };

Expand Down Expand Up @@ -46,7 +47,7 @@ export default function ImportExercisesPanel({

return (
<div className="bg-foreground-600 rounded-md p-4 space-y-3">
<h3 className="text-foreground-200 font-semibold">Import Exercises (CSV)</h3>
<H3 className="font-semibold">Import Exercises (CSV)</H3>

<div className="flex flex-wrap gap-3 items-center">
<label className="bg-background-500 text-foreground-200 border border-foreground-500 rounded px-2 py-1 cursor-pointer">
Expand All @@ -73,4 +74,4 @@ export default function ImportExercisesPanel({
</div>
</div>
);
}
}
3 changes: 2 additions & 1 deletion codewit/client/src/pages/Read.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { cn } from '../utils/styles';
import { ErrorView } from '../components/error/Error';
import { toast } from 'react-toastify';
import { DefaultMarkdown } from '../components/markdown';
import { H3 } from "../components/typography";

function demo_query_key(demo_uid: string, module_id: string | null): ["demo_attempt", string, string | null] {
return ["demo_attempt", demo_uid, module_id];
Expand Down Expand Up @@ -102,7 +103,7 @@ export default function Read() {
<LeftPanel info={data} module_id={module_id} course_id={course_id}/>
{data.demo.exercises.length === 0 ?
<div className="flex flex-col items-center justify-center w-full">
<h3 className="text-xl">No Exercises</h3>
<H3 className="text-xl">No Exercises</H3>
<p>There are no exercises attached to this demo</p>
</div>
:
Expand Down
19 changes: 10 additions & 9 deletions codewit/client/src/pages/course/TeacherView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import bulbLit from '/bulb(lit).svg';

import { useCourseProgress } from '../../hooks/useCourse';
import Loading from '../../components/loading/LoadingPage';
import { H1, H2 } from "../../components/typography";
import { ErrorPage } from '../../components/error/Error';
import { useAxiosFetch } from "../../hooks/fetching";
import { useEffect, useState } from "react";
Expand Down Expand Up @@ -71,7 +72,7 @@ export default function TeacherView({ onCourseChange }: TeacherViewProps) {
if (loading || course_loading) {
return <Loading />;
}

if (error || course_error || course == null || !students) {
return <ErrorPage message="Failed to load course information"/>;
}
Expand Down Expand Up @@ -105,7 +106,7 @@ export default function TeacherView({ onCourseChange }: TeacherViewProps) {
}

async function toggleAutoEnroll() {
if (!enrolling) return;
if (!enrolling) return;
const next = !autoEnroll;
await persistFlags(enrolling, next);
}
Expand Down Expand Up @@ -188,9 +189,9 @@ export default function TeacherView({ onCourseChange }: TeacherViewProps) {
<div className="w-full flex flex-col items-center bg-black gap-8 py-8">
{/* ───────── header + invite link ───────── */}
<div className="bg-foreground-600 w-3/4 rounded-md p-4">
<span className="text-[16px] font-bold text-foreground-200">
<H1 className="text-[16px] font-bold">
Teacher Dashboard
</span>
</H1>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed this changes Teacher Dashboard from a span to an h1 via the new helper.

I assume that was intentional, but wanted to confirm the goal here was also to make it a semantic page heading, not just to pick up the shared heading styling.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that was the idea, since it had the exact same heading style I figured I would just make it a heading.


{/* invite link */}
<div className="mt-4 flex items-center gap-2">
Expand Down Expand Up @@ -284,9 +285,9 @@ export default function TeacherView({ onCourseChange }: TeacherViewProps) {
{/* ───────── progress table ───────── */}
<div className="bg-foreground-600 w-3/4 rounded-md p-4">
<div className="flex items-center justify-between mb-4">
<h1 className="font-bold text-foreground-200 text-[16px]">
<H1 className="font-bold text-[16px]">
Student Progress
</h1>
</H1>
<button
onClick={handleExportCsv}
disabled={exporting || students.length === 0}
Expand Down Expand Up @@ -396,12 +397,12 @@ export default function TeacherView({ onCourseChange }: TeacherViewProps) {
{/* ─── pending enrollment requests ─── */}
{pending.length > 0 && (
<div className="bg-foreground-600 w-3/4 rounded-md p-4">
<h2 className="font-bold text-foreground-200 text-[16px] mb-4">
<H2 className="font-bold text-[16px] mb-4">
Pending Enrollment Requests ({pending.length})
</h2>
</H2>
<PendingRequestsCard courseId={courseId} pending={pending} />
</div>
)}
</div>
);
}
}
11 changes: 6 additions & 5 deletions codewit/client/src/pages/create/exercise/exercise_id.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import TagSelect, { topic_options } from "../../../components/form/TagSelect";
import LanguageSelect from "../../../components/form/LanguageSelect";
import ReusableModal from "../../../components/form/ReusableModal";
import InputLabel from "../../../components/form/InputLabel";
import { H2, H3, H4 } from "../../../components/typography";
import { isFormValid } from "../../../utils/formValidationUtils";
import { cn, SelectStyles } from "../../../utils/styles";
import { use_single_exercise_query, single_exercise_query_key } from "../../../hooks/useExercise";
Expand Down Expand Up @@ -304,9 +305,9 @@ function ExerciseEdit({
}}>
<div className="flex flex-row flex-nowrap items-center gap-x-2 pb-2">
<form.ConfirmAway on_away={() => on_cancel()}/>
<h2 className="text-4xl font-bold text-heading">
<H2 className="text-4xl font-bold">
{exercise != null ? "Edit Exercise" : "Create Exercise"}
</h2>
</H2>
<div className="flex-1"/>
<form.SubmitButton/>
<form.ConfirmReset on_reset={() => form.reset()}/>
Expand Down Expand Up @@ -537,8 +538,8 @@ function ExerciseTest({

return <div className="space-y-2">
<div>
<h3 className="text-3xl font-bold text-heading">Test Exercise</h3>
<p className="text-body">Run a small test with the current exercise inputs to validate it will run as expected</p>
<H3 className="text-3xl font-bold">Test Exercise</H3>
<p className="text-white">Run a small test with the current exercise inputs to validate it will run as expected</p>
</div>
<div className="flex flex-col gap-2">
<Editor
Expand All @@ -556,7 +557,7 @@ function ExerciseTest({
Reset
</Button>
</div>
<h4 className="text-2xl font-bold text-heading">Results</h4>
<H4 className="text-2xl font-bold">Results</H4>
<div className="px-4 w-full min-h-64 overflow-auto">
{data != null ?
<>
Expand Down
Loading