mirror of
https://github.com/Sonny93/my-links.git
synced 2025-12-11 08:43:04 +00:00
feat: first form field auto focused
This commit is contained in:
@@ -1,57 +1,59 @@
|
||||
import { MutableRefObject, useState } from 'react';
|
||||
import { MutableRefObject, useState } from "react";
|
||||
|
||||
interface SelectorProps {
|
||||
name: string;
|
||||
label?: string;
|
||||
labelComponent?: JSX.Element;
|
||||
disabled?: boolean;
|
||||
innerRef?: MutableRefObject<any>;
|
||||
placeholder?: string;
|
||||
fieldClass?: string;
|
||||
isChecked?: boolean;
|
||||
onChangeCallback?: (value, { target }) => void;
|
||||
name: string;
|
||||
label?: string;
|
||||
labelComponent?: JSX.Element;
|
||||
disabled?: boolean;
|
||||
innerRef?: MutableRefObject<any>;
|
||||
placeholder?: string;
|
||||
fieldClass?: string;
|
||||
isChecked?: boolean;
|
||||
onChangeCallback?: (value, { target }) => void;
|
||||
}
|
||||
|
||||
export default function Selector({
|
||||
name,
|
||||
label,
|
||||
labelComponent,
|
||||
disabled = false,
|
||||
innerRef = null,
|
||||
fieldClass = '',
|
||||
placeholder = 'Type something...',
|
||||
isChecked,
|
||||
onChangeCallback
|
||||
export default function Checkbox({
|
||||
name,
|
||||
label,
|
||||
labelComponent,
|
||||
disabled = false,
|
||||
innerRef = null,
|
||||
fieldClass = "",
|
||||
placeholder = "Type something...",
|
||||
isChecked,
|
||||
onChangeCallback,
|
||||
}: SelectorProps): JSX.Element {
|
||||
const [checkboxValue, setCheckboxValue] = useState<boolean>(isChecked);
|
||||
const [checkboxValue, setCheckboxValue] = useState<boolean>(isChecked);
|
||||
|
||||
function onChange({ target }) {
|
||||
setCheckboxValue(!checkboxValue);
|
||||
if (onChangeCallback) {
|
||||
onChangeCallback(!checkboxValue, { target });
|
||||
}
|
||||
function onChange({ target }) {
|
||||
setCheckboxValue(!checkboxValue);
|
||||
if (onChangeCallback) {
|
||||
onChangeCallback(!checkboxValue, { target });
|
||||
}
|
||||
}
|
||||
|
||||
return (<div className={`checkbox-field ${fieldClass}`}>
|
||||
{label && (
|
||||
<label htmlFor={name} title={`${name} field`}>
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
{labelComponent && (
|
||||
<label htmlFor={name} title={`${name} field`}>
|
||||
{labelComponent}
|
||||
</label>
|
||||
)}
|
||||
<input
|
||||
type='checkbox'
|
||||
id={name}
|
||||
name={name}
|
||||
onChange={onChange}
|
||||
checked={checkboxValue}
|
||||
placeholder={placeholder}
|
||||
ref={innerRef}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</div>);
|
||||
}
|
||||
return (
|
||||
<div className={`checkbox-field ${fieldClass}`}>
|
||||
{label && (
|
||||
<label htmlFor={name} title={`${name} field`}>
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
{labelComponent && (
|
||||
<label htmlFor={name} title={`${name} field`}>
|
||||
{labelComponent}
|
||||
</label>
|
||||
)}
|
||||
<input
|
||||
type="checkbox"
|
||||
id={name}
|
||||
name={name}
|
||||
onChange={onChange}
|
||||
checked={checkboxValue}
|
||||
placeholder={placeholder}
|
||||
ref={innerRef}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@ import styles from "../styles/create.module.scss";
|
||||
|
||||
interface FormProps {
|
||||
title: string;
|
||||
|
||||
categoryId?: string;
|
||||
|
||||
errorMessage?: string;
|
||||
successMessage?: string;
|
||||
infoMessage?: string;
|
||||
@@ -21,6 +24,7 @@ interface FormProps {
|
||||
}
|
||||
export default function Form({
|
||||
title,
|
||||
categoryId = undefined,
|
||||
errorMessage,
|
||||
successMessage,
|
||||
infoMessage,
|
||||
@@ -45,7 +49,9 @@ export default function Form({
|
||||
{textBtnConfirm}
|
||||
</button>
|
||||
</form>
|
||||
<Link href="/">← Revenir à l'accueil</Link>
|
||||
<Link href={categoryId ? `/?categoryId=${categoryId}` : "/"}>
|
||||
← Revenir à l'accueil
|
||||
</Link>
|
||||
<MessageManager
|
||||
info={infoMessage}
|
||||
error={errorMessage}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { AiFillDelete, AiFillEdit } from "react-icons/ai";
|
||||
|
||||
import { Category } from "../../../types";
|
||||
|
||||
import { useEffect, useRef } from "react";
|
||||
import styles from "./categories.module.scss";
|
||||
|
||||
interface CategoryItemProps {
|
||||
@@ -11,19 +12,28 @@ interface CategoryItemProps {
|
||||
handleSelectCategory: (category: Category) => void;
|
||||
}
|
||||
|
||||
let rendered = false;
|
||||
export default function CategoryItem({
|
||||
category,
|
||||
categoryActive,
|
||||
handleSelectCategory,
|
||||
}: CategoryItemProps): JSX.Element {
|
||||
const ref = useRef<HTMLLIElement>();
|
||||
const className = `${styles["item"]} ${
|
||||
category.id === categoryActive.id ? styles["active"] : ""
|
||||
}`;
|
||||
const onClick = () => handleSelectCategory(category);
|
||||
|
||||
useEffect(() => {
|
||||
if (category.id === categoryActive.id && !rendered) {
|
||||
rendered = true;
|
||||
ref.current.scrollIntoView({ behavior: "smooth" });
|
||||
}
|
||||
}, [category.id, categoryActive.id]);
|
||||
|
||||
return (
|
||||
<li className={className} onClick={onClick}>
|
||||
<div className={styles["content"]}>
|
||||
<li className={className} ref={ref}>
|
||||
<div className={styles["content"]} onClick={onClick}>
|
||||
<span className={styles["name"]}>{category.name}</span>
|
||||
<span className={styles["links-count"]}>— {category.links.length}</span>
|
||||
</div>
|
||||
@@ -35,12 +45,17 @@ export default function CategoryItem({
|
||||
function MenuOptions({ id }: { id: number }): JSX.Element {
|
||||
return (
|
||||
<div className={styles["menu-item"]}>
|
||||
<LinkTag href={`/category/edit/${id}`} className={styles["option-edit"]}>
|
||||
<LinkTag
|
||||
href={`/category/edit/${id}`}
|
||||
className={styles["option-edit"]}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
>
|
||||
<AiFillEdit />
|
||||
</LinkTag>
|
||||
<LinkTag
|
||||
href={`/category/remove/${id}`}
|
||||
className={styles["option-remove"]}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
>
|
||||
<AiFillDelete color="red" />
|
||||
</LinkTag>
|
||||
|
||||
@@ -29,7 +29,7 @@ export default function SideMenu({
|
||||
<BlockWrapper>
|
||||
<Favorites favorites={favorites} />
|
||||
</BlockWrapper>
|
||||
<BlockWrapper style={{ minHeight: "0" }}>
|
||||
<BlockWrapper style={{ minHeight: "0", flex: "1" }}>
|
||||
<Categories
|
||||
categories={categories}
|
||||
categoryActive={categoryActive}
|
||||
|
||||
@@ -1,62 +1,64 @@
|
||||
import { MutableRefObject, useState } from 'react';
|
||||
import { MutableRefObject, useState } from "react";
|
||||
|
||||
interface InputProps {
|
||||
name: string;
|
||||
label?: string;
|
||||
labelComponent?: JSX.Element;
|
||||
disabled?: boolean;
|
||||
type?: string;
|
||||
multiple?: boolean;
|
||||
innerRef?: MutableRefObject<any>;
|
||||
placeholder?: string;
|
||||
fieldClass?: string;
|
||||
value?: string;
|
||||
onChangeCallback?: (value) => void;
|
||||
name: string;
|
||||
label?: string;
|
||||
labelComponent?: JSX.Element;
|
||||
disabled?: boolean;
|
||||
type?: string;
|
||||
multiple?: boolean;
|
||||
innerRef?: MutableRefObject<any> | ((ref: any) => void);
|
||||
placeholder?: string;
|
||||
fieldClass?: string;
|
||||
value?: string;
|
||||
onChangeCallback?: (value) => void;
|
||||
}
|
||||
|
||||
export default function TextBox({
|
||||
name,
|
||||
label,
|
||||
labelComponent,
|
||||
disabled = false,
|
||||
type = 'text',
|
||||
multiple = false,
|
||||
innerRef = null,
|
||||
placeholder = 'Type something...',
|
||||
fieldClass = '',
|
||||
value,
|
||||
onChangeCallback
|
||||
name,
|
||||
label,
|
||||
labelComponent,
|
||||
disabled = false,
|
||||
type = "text",
|
||||
multiple = false,
|
||||
innerRef = null,
|
||||
placeholder = "Type something...",
|
||||
fieldClass = "",
|
||||
value,
|
||||
onChangeCallback,
|
||||
}: InputProps): JSX.Element {
|
||||
const [inputValue, setInputValue] = useState<string>(value);
|
||||
const [inputValue, setInputValue] = useState<string>(value);
|
||||
|
||||
function onChange({ target }) {
|
||||
setInputValue(target.value);
|
||||
if (onChangeCallback) {
|
||||
onChangeCallback(target.value);
|
||||
}
|
||||
function onChange({ target }) {
|
||||
setInputValue(target.value);
|
||||
if (onChangeCallback) {
|
||||
onChangeCallback(target.value);
|
||||
}
|
||||
}
|
||||
|
||||
return (<div className={`input-field ${fieldClass}`}>
|
||||
{label && (
|
||||
<label htmlFor={name} title={`${name} field`}>
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
{labelComponent && (
|
||||
<label htmlFor={name} title={`${name} field`}>
|
||||
{labelComponent}
|
||||
</label>
|
||||
)}
|
||||
<input
|
||||
id={name}
|
||||
name={name}
|
||||
type={type}
|
||||
onChange={onChange}
|
||||
value={inputValue}
|
||||
multiple={multiple}
|
||||
placeholder={placeholder}
|
||||
ref={innerRef}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</div>);
|
||||
}
|
||||
return (
|
||||
<div className={`input-field ${fieldClass}`}>
|
||||
{label && (
|
||||
<label htmlFor={name} title={`${name} field`}>
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
{labelComponent && (
|
||||
<label htmlFor={name} title={`${name} field`}>
|
||||
{labelComponent}
|
||||
</label>
|
||||
)}
|
||||
<input
|
||||
id={name}
|
||||
name={name}
|
||||
type={type}
|
||||
onChange={onChange}
|
||||
value={inputValue}
|
||||
multiple={multiple}
|
||||
placeholder={placeholder}
|
||||
ref={innerRef}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user