mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2024-09-20 23:36:37 +08:00
impr(animated modal): add option to automatically focus and select on show
This commit is contained in:
parent
9c73697b37
commit
b6b22b3cf5
|
@ -6,7 +6,7 @@ import AnimatedModal from "../utils/animated-modal";
|
|||
|
||||
export function show(): void {
|
||||
void modal.show({
|
||||
focusFirstInput: true,
|
||||
focusFirstInput: "focusAndSelect",
|
||||
beforeAnimation: async (modalEl) => {
|
||||
(
|
||||
modalEl.querySelector("input") as HTMLInputElement
|
||||
|
|
|
@ -17,6 +17,7 @@ export function show(mode: "import" | "export", config?: string): void {
|
|||
state.value = config ?? "";
|
||||
|
||||
void modal.show({
|
||||
focusFirstInput: "focusAndSelect",
|
||||
beforeAnimation: async (modal) => {
|
||||
(modal.querySelector("input") as HTMLInputElement).value = state.value;
|
||||
if (state.mode === "export") {
|
||||
|
@ -27,14 +28,6 @@ export function show(mode: "import" | "export", config?: string): void {
|
|||
modal.querySelector("input")?.removeAttribute("readonly");
|
||||
}
|
||||
},
|
||||
afterAnimation: async (modal) => {
|
||||
const inputEl = modal.querySelector("input");
|
||||
if (state.mode === "import") {
|
||||
inputEl?.focus();
|
||||
} else if (state.mode === "export") {
|
||||
inputEl?.select();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -62,26 +62,11 @@ async function copy(): Promise<void> {
|
|||
duration: 5,
|
||||
}
|
||||
);
|
||||
await modal.hide({
|
||||
animationMode: "modalOnly",
|
||||
animationDurationMs: 62.5,
|
||||
});
|
||||
void urlModal.show({
|
||||
animationMode: "modalOnly",
|
||||
animationDurationMs: 62.5,
|
||||
beforeAnimation: async (modal) => {
|
||||
const input = modal.querySelector("input") as HTMLInputElement;
|
||||
input.value = url;
|
||||
//focus and select input
|
||||
setTimeout(() => {
|
||||
input.focus();
|
||||
input.select();
|
||||
}, 0);
|
||||
},
|
||||
afterAnimation: async (modal) => {
|
||||
const input = modal.querySelector("input") as HTMLInputElement;
|
||||
input.focus();
|
||||
input.select();
|
||||
modalChain: modal,
|
||||
focusFirstInput: "focusAndSelect",
|
||||
beforeAnimation: async (m) => {
|
||||
(m.querySelector("input") as HTMLInputElement).value = url;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -98,4 +83,20 @@ const modal = new AnimatedModal("shareCustomThemeModal", "popups", undefined, {
|
|||
},
|
||||
});
|
||||
|
||||
const urlModal = new AnimatedModal("shareCustomThemeUrlModal", "popups");
|
||||
const urlModal = new AnimatedModal(
|
||||
"shareCustomThemeUrlModal",
|
||||
"popups",
|
||||
undefined,
|
||||
{
|
||||
customEscapeHandler: async (): Promise<void> => {
|
||||
await urlModal.hide({
|
||||
clearModalChain: true,
|
||||
});
|
||||
},
|
||||
customWrapperClickHandler: async (): Promise<void> => {
|
||||
await urlModal.hide({
|
||||
clearModalChain: true,
|
||||
});
|
||||
},
|
||||
}
|
||||
);
|
||||
|
|
|
@ -27,7 +27,7 @@ type ShowHideOptions = {
|
|||
};
|
||||
|
||||
export type ShowOptions = ShowHideOptions & {
|
||||
focusFirstInput?: boolean;
|
||||
focusFirstInput?: true | "focusAndSelect";
|
||||
modalChain?: AnimatedModal;
|
||||
};
|
||||
|
||||
|
@ -146,6 +146,19 @@ export default class AnimatedModal {
|
|||
isOpen(): boolean {
|
||||
return this.open;
|
||||
}
|
||||
|
||||
focusFirstInput(setting: true | "focusAndSelect" | undefined): void {
|
||||
if (setting === true) {
|
||||
this.modalEl.querySelector("input")?.focus();
|
||||
} else if (setting === "focusAndSelect") {
|
||||
const input = this.modalEl.querySelector("input") as HTMLInputElement;
|
||||
input.focus();
|
||||
input.select();
|
||||
} else {
|
||||
this.wrapperEl.focus();
|
||||
}
|
||||
}
|
||||
|
||||
async show(options?: ShowOptions): Promise<void> {
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
return new Promise(async (resolve) => {
|
||||
|
@ -181,13 +194,9 @@ export default class AnimatedModal {
|
|||
|
||||
//wait until the next event loop to allow the dialog to start animating
|
||||
setTimeout(async () => {
|
||||
if (options?.focusFirstInput) {
|
||||
this.modalEl.querySelector("input")?.focus();
|
||||
} else {
|
||||
this.wrapperEl.focus();
|
||||
}
|
||||
this.focusFirstInput(options?.focusFirstInput);
|
||||
await options?.beforeAnimation?.(this.modalEl);
|
||||
}, 0);
|
||||
}, 1);
|
||||
|
||||
const modalAnimation =
|
||||
options?.customAnimation?.modal ?? this.customShowAnimations?.modal;
|
||||
|
@ -231,6 +240,7 @@ export default class AnimatedModal {
|
|||
animationMode === "none" ? 0 : wrapperAnimationDuration,
|
||||
wrapperAnimation.easing ?? "swing",
|
||||
async () => {
|
||||
this.focusFirstInput(options?.focusFirstInput);
|
||||
await options?.afterAnimation?.(this.modalEl);
|
||||
resolve();
|
||||
}
|
||||
|
@ -248,7 +258,7 @@ export default class AnimatedModal {
|
|||
modalAnimationDuration,
|
||||
modalAnimation?.easing ?? "swing",
|
||||
async () => {
|
||||
this.wrapperEl.focus();
|
||||
this.focusFirstInput(options?.focusFirstInput);
|
||||
await options?.afterAnimation?.(this.modalEl);
|
||||
resolve();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue