fix: add input scroll into view
All checks were successful
Deploy to VPS (dist) / deploy (push) Successful in 1m31s

This commit is contained in:
Hewston Fox
2026-03-22 17:48:35 +02:00
parent a9ed3dea5f
commit 8a11ee4c29
3 changed files with 39 additions and 3 deletions

View File

@@ -1,6 +1,6 @@
import { motion, type HTMLMotionProps } from "motion/react";
import clsx, { type ClassValue } from "clsx";
import { type ReactNode, useRef, useState, type ChangeEvent, useId } from "react";
import { type ReactNode, useRef, useState, type ChangeEvent, type FocusEvent, useId } from "react";
import KeyboardIcon from "@components/icons/KeyboardIcon";
import classes from "./NumberInput.module.css";
@@ -29,6 +29,7 @@ export default function NumberInput({
prefix,
value,
onChange,
onFocus,
...props
}: Props) {
const play = useAudioStore((s) => s.play);
@@ -44,6 +45,16 @@ export default function NumberInput({
setStrValue(value?.toString() ?? "");
}
const handleFocus = (e: FocusEvent<HTMLInputElement>) => {
onFocus?.(e);
const target = e.target;
setTimeout(() => {
if (target.isConnected) {
target.scrollIntoView({ block: "center", behavior: "smooth" });
}
}, 100);
};
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const normalized = filterNumericInput(e.target.value);
setStrValue(normalized);
@@ -65,6 +76,7 @@ export default function NumberInput({
className={classes.input}
value={strValue}
onChange={handleChange}
onFocus={handleFocus}
/>
</label>
<motion.button

View File

@@ -1,5 +1,6 @@
import { motion, type HTMLMotionProps } from "motion/react";
import clsx, { type ClassValue } from "clsx";
import type { FocusEvent } from "react";
import classes from "./TextAreaInput.module.css";
@@ -8,10 +9,21 @@ type Props = Omit<HTMLMotionProps<"textarea">, "className"> & {
error?: boolean;
};
export default function TextAreaInput({ className, error, ...props }: Props) {
export default function TextAreaInput({ className, error, onFocus, ...props }: Props) {
const handleFocus = (e: FocusEvent<HTMLTextAreaElement>) => {
onFocus?.(e);
const target = e.target;
setTimeout(() => {
if (target.isConnected) {
target.scrollIntoView({ block: "center", behavior: "smooth" });
}
}, 100);
};
return (
<motion.textarea
{...props}
onFocus={handleFocus}
className={clsx(classes.input, error && classes.error, className)}
/>
);

View File

@@ -1,5 +1,6 @@
import { motion, type HTMLMotionProps } from "motion/react";
import clsx, { type ClassValue } from "clsx";
import type { FocusEvent } from "react";
import classes from "./TextInput.module.css";
@@ -8,11 +9,22 @@ type Props = Omit<HTMLMotionProps<"input">, "className"> & {
error?: boolean;
};
export default function TextInput({ className, error, ...props }: Props) {
export default function TextInput({ className, error, onFocus, ...props }: Props) {
const handleFocus = (e: FocusEvent<HTMLInputElement>) => {
onFocus?.(e);
const target = e.target;
setTimeout(() => {
if (target.isConnected) {
target.scrollIntoView({ block: "center", behavior: "smooth" });
}
}, 100);
};
return (
<motion.input
{...props}
type="text"
onFocus={handleFocus}
className={clsx(classes.input, error && classes.error, className)}
/>
);