Skip to content
Draft
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
39 changes: 0 additions & 39 deletions frontend/src/html/popups.html
Original file line number Diff line number Diff line change
Expand Up @@ -87,45 +87,6 @@
</div>
</dialog>

<dialog id="practiseWordsModal" class="modalWrapper hidden">
<div class="modal" actions="">
<div class="title">Practice words</div>
<!-- <div class="inputs"> -->
<div class="group" data-id="missed">
<div class="title">
<i class="fas fa-times"></i>
missed
</div>
<div class="sub">
Include missed words or biwords (which include the previous word).
</div>
<div class="groupInputs">
<div class="buttonGroup">
<button class="missedOff" value="off">off</button>
<button class="missedWords" value="words">words</button>
<button class="missedBiwords" value="biwords">biwords</button>
</div>
</div>
</div>
<div class="group" data-id="slow">
<div class="title">
<i class="fas fa-tachometer-alt"></i>
slow
</div>
<div class="sub">Include words which you typed slower than others.</div>
<div class="groupInputs">
<div class="buttonGroup">
<button class="slowOff" value="false">off</button>
<button class="slowOn" value="true">on</button>
</div>
</div>
</div>
<div></div>
<!-- </div> -->
<button class="start">start</button>
</div>
</dialog>

<dialog id="shareCustomThemeUrlModal" class="modalWrapper hidden">
<div class="modal">
<input type="text" title="custom theme" />
Expand Down
33 changes: 0 additions & 33 deletions frontend/src/styles/popups.scss
Original file line number Diff line number Diff line change
Expand Up @@ -81,39 +81,6 @@ body.darkMode {
}
}

#practiseWordsModal {
.modal {
max-width: 400px;

.group {
width: 100%;
display: grid;
.title {
color: var(--sub-color);
text-transform: lowercase;
}
.sub {
color: var(--text-color);
margin-top: 0.25rem;
margin-bottom: 0.5rem;
}
.buttonGroup {
display: flex;
gap: 0.5rem;
width: 100%;
button {
flex-grow: 1;
}
}
}

.text {
font-size: 1rem;
color: var(--text-color);
}
}
}

#simpleModal {
.modal {
max-width: 500px;
Expand Down
9 changes: 3 additions & 6 deletions frontend/src/ts/commandline/lists/result-screen.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as TestLogic from "../../test/test-logic";
import * as TestUI from "../../test/test-ui";
import * as PractiseWordsModal from "../../modals/practise-words";
import { showModal } from "../../states/modals";
import {
showErrorNotification,
showSuccessNotification,
Expand Down Expand Up @@ -50,11 +50,8 @@ const practiceSubgroup: CommandsSubgroup = {
id: "practiseWordsCustom",
display: "custom...",
opensModal: true,
exec: (options): void => {
PractiseWordsModal.show({
animationMode: "modalOnly",
modalChain: options.commandlineModal,
});
exec: (): void => {
showModal("PractiseWords");
},
Comment thread
d1rshan marked this conversation as resolved.
},
],
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/ts/components/modals/Modals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { CustomTestDurationModal } from "./CustomTestDurationModal";
import { CustomTextModal } from "./CustomTextModal";
import { CustomWordAmountModal } from "./CustomWordAmountModal";
import { MobileTestConfigModal } from "./MobileTestConfigModal";
import { PractiseWordsModal } from "./PractiseWordsModal";
import { AddPresetModal } from "./preset/AddPresetModal";
import { EditPresetModal } from "./preset/EditPresetModal";
import { QuoteRateModal } from "./QuoteRateModal";
Expand Down Expand Up @@ -33,6 +34,7 @@ export function Modals(): JSXElement {
<CustomWordAmountModal />
<ShareTestSettings />
<MobileTestConfigModal />
<PractiseWordsModal />
<CookiesModal />
<AddPresetModal />
<EditPresetModal />
Expand Down
114 changes: 114 additions & 0 deletions frontend/src/ts/components/modals/PractiseWordsModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { AnyFieldApi, createForm } from "@tanstack/solid-form";
import { For, JSXElement } from "solid-js";

import { hideModalAndClearChain } from "../../states/modals";
import * as PractiseWords from "../../test/practise-words";
import * as TestLogic from "../../test/test-logic";
import { cn } from "../../utils/cn";
import { AnimatedModal } from "../common/AnimatedModal";
import { Button } from "../common/Button";
import { Fa } from "../common/Fa";

export function PractiseWordsModal(): JSXElement {
const form = createForm(() => ({
defaultValues: {
missed: "words" as "off" | "words" | "biwords",
slow: false,
},
onSubmit: ({ value }) => {
PractiseWords.init(value.missed, value.slow);
hideModalAndClearChain("PractiseWords");
TestLogic.restart({ practiseMissed: true });
},
}));

const canStart = form.useStore(
(state) => state.values.missed !== "off" || state.values.slow,
);

return (
<AnimatedModal
id="PractiseWords"
title="Practice words"
modalClass="max-w-[400px]"
animationMode="modalOnly"
>
<form
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I wonder if we could use ts/forms and create a ButtonGroup component. Part of it is already done in AutoSettings component.

This way we don't need to maintain the signals

Copy link
Copy Markdown
Contributor Author

@d1rshan d1rshan May 30, 2026

Choose a reason for hiding this comment

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

da99797,@fehmer like this?

onSubmit={(e) => {
e.preventDefault();
void form.handleSubmit();
}}
>
<div class="grid gap-6">
<div class="grid gap-2">
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This style is identical to the settings page. Could we extract a component for it and use it here and on the settings page

<div class="text-sub lowercase">
<Fa icon="fa-times" /> missed
</div>
<div>
Include missed words or biwords (which include the previous word).
</div>
<form.Field name="missed">
{(field) => (
<ButtonGroup
field={field}
options={[
{ value: "off", label: "off" },
{ value: "words", label: "words" },
{ value: "biwords", label: "biwords" },
]}
class="grid-cols-3"
/>
)}
</form.Field>
</div>

<div class="grid gap-2">
<div class="text-sub lowercase">
<Fa icon="fa-tachometer-alt" /> slow
</div>
<div>Include words which you typed slower than others.</div>
<form.Field name="slow">
{(field) => (
<ButtonGroup
field={field}
options={[
{ value: false, label: "off" },
{ value: true, label: "on" },
]}
class="grid-cols-2"
/>
)}
</form.Field>
</div>

<Button type="submit" disabled={!canStart()}>
start
</Button>
</div>
</form>
</AnimatedModal>
);
}

type ButtonGroupOption<T> = { value: T; label: string };

function ButtonGroup<T>(props: {
field: () => AnyFieldApi;
options: readonly ButtonGroupOption<T>[];
class?: string;
}): JSXElement {
return (
<div class={cn("grid gap-2", props.class)}>
<For each={props.options}>
{(opt) => (
<Button
active={props.field().state.value === opt.value}
onClick={() => props.field().handleChange(opt.value)}
>
{opt.label}
</Button>
)}
</For>
</div>
);
}
4 changes: 2 additions & 2 deletions frontend/src/ts/event-handlers/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from "../states/notifications";
import { showQuoteRateModal } from "../states/quote-rate";
import { showQuoteReportModal } from "../states/quote-report";
import * as PractiseWordsModal from "../modals/practise-words";
import { showModal } from "../states/modals";
import { navigate } from "../controllers/route-controller";
import { getMode2 } from "../utils/misc";
import { ConfigKey } from "@monkeytype/schemas/configs";
Expand Down Expand Up @@ -67,7 +67,7 @@ testPage?.onChild("click", "#practiseWordsButton", () => {
showNoticeNotification("Practice words is unsupported in zen mode");
return;
}
PractiseWordsModal.show();
showModal("PractiseWords");
});

qs(".pageTest #dailyLeaderboardRank")?.on("click", async () => {
Expand Down
82 changes: 0 additions & 82 deletions frontend/src/ts/modals/practise-words.ts

This file was deleted.

1 change: 1 addition & 0 deletions frontend/src/ts/states/modals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export type ModalId =
| "CustomWordAmount"
| "MobileTestConfig"
| "MiniResultChartModal"
| "PractiseWords"
| "Cookies"
| "AddPresetModal"
| "EditPresetModal"
Expand Down
Loading