autobrr/web/src/components/inputs/input.tsx
stacksmash76 279d4ff7a3
feat: add filter dropdown #26 (#142)
feat(FilterItemDropdown): added a filter dropdown component from #26 

* fix(react-multi-select-component): adjusted the component to fit in with other components when comparing across multiple browsers. (where firefox consistently handles pixels and rem's, chromium doesn't agree).

refactor(input): removed shadow from input components to match react-multi-select-component look where needed.

refactor(SwitchGroup): added a small top margin for a less dense look. cleaned up surrounding code.

refactor(DeleteModal): adjusted the background color to fit more nicely across dark/light themes. made the exclamation icon bigger and removed the circle container.

refactor(Logs): adjusted text color on the light theme. cleaned up the code.

refactor(FilterAddForm): adapted to conform with the changes.

feat(FilterItemDropdown): added a dropdown component to the filter list as proposed in #26. could use a better look, though. also, cleaned up surrounding code and got rid of pesky negative margins.

refactor(FilterListItem): made the table striped when using the dark theme. adapter for the dropdown component.

refactor(filters/details):
- removed needless border properties from remove button, which left artifacts after de-focusing the button. also, removed the shadow from the cancel button.
- added invalidation of the filter list on a delete mutation before redirecting to /filters.
- modified certain group descriptions a bit in order to make them a bit more concise.
- overall, cleaned up the surrounding code further.
2022-02-17 20:59:06 +01:00

165 lines
5.5 KiB
TypeScript

import { Field } from "formik";
import { classNames } from "../../utils";
import { EyeIcon, EyeOffIcon } from "@heroicons/react/solid";
import { useToggle } from "../../hooks/hooks";
type COL_WIDTHS = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
interface TextFieldProps {
name: string;
label?: string;
placeholder?: string;
columns?: COL_WIDTHS;
autoComplete?: string;
}
export const TextField = ({
name,
label,
placeholder,
columns,
autoComplete
}: TextFieldProps) => (
<div
className={classNames(
columns ? `col-span-${columns}` : "col-span-12"
)}
>
{label && (
<label htmlFor={name} className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
{label}
</label>
)}
<Field name={name}>
{({
field,
meta,
}: any) => (
<div>
<input
{...field}
id={name}
type="text"
autoComplete={autoComplete}
className="mt-2 block w-full dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-md py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:text-gray-100"
placeholder={placeholder}
/>
{meta.touched && meta.error && (
<div className="error">{meta.error}</div>
)}
</div>
)}
</Field>
</div>
)
interface PasswordFieldProps {
name: string;
label?: string;
placeholder?: string;
columns?: COL_WIDTHS;
autoComplete?: string;
defaultValue?: string;
help?: string;
required?: boolean;
}
export const PasswordField = ({
name,
label,
placeholder,
defaultValue,
columns,
autoComplete,
help,
required
}: PasswordFieldProps) => {
const [isVisible, toggleVisibility] = useToggle(false)
return (
<div
className={classNames(
columns ? `col-span-${columns}` : "col-span-12"
)}
>
{label && (
<label htmlFor={name} className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
{label} {required && <span className="text-gray-500">*</span>}
</label>
)}
<Field name={name} defaultValue={defaultValue}>
{({
field,
meta,
}: any) => (
<div className="sm:col-span-2 relative">
<input
{...field}
id={name}
type={isVisible ? "text" : "password"}
autoComplete={autoComplete}
className={classNames(meta.touched && meta.error ? "focus:ring-red-500 focus:border-red-500 border-red-500" : "focus:ring-indigo-500 dark:focus:ring-blue-500 focus:border-indigo-500 dark:focus:border-blue-500 border-gray-300 dark:border-gray-700", "mt-2 block w-full dark:bg-gray-800 dark:text-gray-100 rounded-md")}
placeholder={placeholder}
/>
<div className="absolute inset-y-0 right-0 px-3 flex items-center" onClick={toggleVisibility}>
{!isVisible ? <EyeIcon className="h-5 w-5 text-gray-400 hover:text-gray-500" aria-hidden="true" /> : <EyeOffIcon className="h-5 w-5 text-gray-400 hover:text-gray-500" aria-hidden="true" />}
</div>
{help && (
<p className="mt-2 text-sm text-gray-500" id="email-description">{help}</p>
)}
{meta.touched && meta.error && (
<div className="error">{meta.error}</div>
)}
</div>
)}
</Field>
</div>
)
}
interface NumberFieldProps {
name: string;
label?: string;
placeholder?: string;
}
export const NumberField = ({
name,
label,
placeholder
}: NumberFieldProps) => (
<div className="col-span-12 sm:col-span-6">
<label htmlFor={name} className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
{label}
</label>
<Field name={name} type="number">
{({
field,
meta,
}: any) => (
<div className="sm:col-span-2">
<input
type="number"
{...field}
className={classNames(
meta.touched && meta.error
? "focus:ring-red-500 focus:border-red-500 border-red-500"
: "focus:ring-indigo-500 dark:focus:ring-blue-500 focus:border-indigo-500 dark:focus:border-blue-500 border-gray-300",
"mt-2 block w-full dark:bg-gray-800 border border-gray-300 dark:border-gray-700 dark:text-gray-100 rounded-md"
)}
placeholder={placeholder}
/>
{meta.touched && meta.error && (
<div className="error">{meta.error}</div>
)}
</div>
)}
</Field>
</div>
);