feat: Filter zurücksetzen button
This commit is contained in:
parent
ece5f17e2a
commit
5aacf17b13
6 changed files with 132 additions and 21 deletions
|
|
@ -0,0 +1,48 @@
|
|||
.wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 100%;
|
||||
padding: 3px 30px 3px 6px;
|
||||
font-size: 12px;
|
||||
border: 1px solid var(--border-color, #ccc);
|
||||
border-radius: 3px;
|
||||
outline: none;
|
||||
box-sizing: border-box;
|
||||
background: var(--color-bg, #fff);
|
||||
color: var(--color-text, #334155);
|
||||
}
|
||||
|
||||
.input:focus {
|
||||
border-color: var(--primary-color, #F25843);
|
||||
}
|
||||
|
||||
.input::placeholder {
|
||||
color: var(--color-text-muted, #94a3b8);
|
||||
}
|
||||
|
||||
.clearBtn {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 3px;
|
||||
bottom: 3px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 25px;
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
font-size: 25px;
|
||||
line-height: 1;
|
||||
color: var(--color-text-secondary, #94a3b8);
|
||||
}
|
||||
|
||||
.clearBtn:hover {
|
||||
background: none;
|
||||
color: var(--color-text-secondary, #94a3b8);
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
import React, { type Ref } from 'react';
|
||||
import styles from './FilterSearchInput.module.css';
|
||||
|
||||
export interface FilterSearchInputProps {
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
placeholder?: string;
|
||||
inputRef?: Ref<HTMLInputElement>;
|
||||
onInputClick?: (e: React.MouseEvent<HTMLInputElement>) => void;
|
||||
onFocus?: () => void;
|
||||
onBlur?: () => void;
|
||||
/** When set, only `inputClassName` styles the input (for floating-label toolbar search). */
|
||||
variant?: 'compact' | 'inherit';
|
||||
inputClassName?: string;
|
||||
wrapperClassName?: string;
|
||||
clearTitle?: string;
|
||||
}
|
||||
|
||||
export function FilterSearchInput({
|
||||
value,
|
||||
onChange,
|
||||
placeholder = 'Filter...',
|
||||
inputRef,
|
||||
onInputClick,
|
||||
onFocus,
|
||||
onBlur,
|
||||
variant = 'compact',
|
||||
inputClassName,
|
||||
wrapperClassName,
|
||||
clearTitle = 'Eingabe löschen',
|
||||
}: FilterSearchInputProps) {
|
||||
const inputClass = variant === 'inherit'
|
||||
? inputClassName
|
||||
: inputClassName
|
||||
? `${styles.input} ${inputClassName}`
|
||||
: styles.input;
|
||||
|
||||
return (
|
||||
<div className={wrapperClassName ? `${styles.wrapper} ${wrapperClassName}` : styles.wrapper}>
|
||||
<input
|
||||
ref={inputRef}
|
||||
type="text"
|
||||
value={value}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
placeholder={placeholder}
|
||||
className={inputClass}
|
||||
onClick={onInputClick}
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}
|
||||
/>
|
||||
{value && (
|
||||
<button
|
||||
type="button"
|
||||
className={styles.clearBtn}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onChange('');
|
||||
}}
|
||||
onMouseDown={(e) => e.preventDefault()}
|
||||
title={clearTitle}
|
||||
tabIndex={-1}
|
||||
aria-label={clearTitle}
|
||||
>
|
||||
×
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
2
src/components/FormGenerator/FilterSearchInput/index.ts
Normal file
2
src/components/FormGenerator/FilterSearchInput/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export { FilterSearchInput } from './FilterSearchInput';
|
||||
export type { FilterSearchInputProps } from './FilterSearchInput';
|
||||
|
|
@ -168,7 +168,7 @@
|
|||
.searchInput {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
padding: 8px 12px;
|
||||
padding: 8px 28px 8px 12px;
|
||||
border: 1px solid var(--color-border, #E2E8F0);
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||
import type { IconType } from 'react-icons';
|
||||
import { useLanguage } from '../../../providers/language/LanguageContext';
|
||||
import styles from './FormGeneratorControls.module.css';
|
||||
import { FilterSearchInput } from '../FilterSearchInput';
|
||||
import { Button } from '../../UiComponents/Button';
|
||||
import { IoIosRefresh } from "react-icons/io";
|
||||
import { FaTrash, FaDownload } from "react-icons/fa";
|
||||
|
|
@ -189,14 +190,15 @@ export function FormGeneratorControls({
|
|||
<div className={styles.searchContainer}>
|
||||
{searchable && (
|
||||
<div className={styles.floatingLabelInput}>
|
||||
<input
|
||||
type="text"
|
||||
placeholder=" "
|
||||
<FilterSearchInput
|
||||
variant="inherit"
|
||||
value={searchTerm}
|
||||
onChange={(e) => onSearchChange(e.target.value)}
|
||||
onChange={onSearchChange}
|
||||
placeholder=" "
|
||||
onFocus={() => onSearchFocus(true)}
|
||||
onBlur={() => onSearchFocus(false)}
|
||||
className={`${styles.searchInput} ${searchFocused || searchTerm ? styles.focused : ''}`}
|
||||
inputClassName={`${styles.searchInput} ${searchFocused || searchTerm ? styles.focused : ''}`}
|
||||
clearTitle={t('Suche löschen')}
|
||||
/>
|
||||
<label className={searchFocused || searchTerm ? styles.focusedLabel : styles.label}>
|
||||
{t('Suchen...')}
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ import {
|
|||
import { formatUnixTimestamp } from '../../../utils/time';
|
||||
import { applyFrontendFormat } from '../../../utils/applyFrontendFormat';
|
||||
import { FormGeneratorControls } from '../FormGeneratorControls';
|
||||
import { FilterSearchInput } from '../FilterSearchInput';
|
||||
import { CopyableTruncatedValue } from '../../UiComponents/CopyableTruncatedValue';
|
||||
import {
|
||||
isDateTimeType,
|
||||
|
|
@ -446,22 +447,11 @@ function FilterValuesList({
|
|||
<>
|
||||
{showSearch && (
|
||||
<div style={{ padding: '4px 6px', borderBottom: '1px solid var(--border-color, #ddd)' }}>
|
||||
<input
|
||||
ref={searchInputRef}
|
||||
type="text"
|
||||
<FilterSearchInput
|
||||
inputRef={searchInputRef}
|
||||
value={searchTerm}
|
||||
onChange={(e) => { setSearchTerm(e.target.value); setDisplayCount(_FILTER_PAGE_SIZE); }}
|
||||
placeholder="Filter..."
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '3px 6px',
|
||||
fontSize: '12px',
|
||||
border: '1px solid var(--border-color, #ccc)',
|
||||
borderRadius: '3px',
|
||||
outline: 'none',
|
||||
boxSizing: 'border-box',
|
||||
}}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onChange={(value) => { setSearchTerm(value); setDisplayCount(_FILTER_PAGE_SIZE); }}
|
||||
onInputClick={(e) => e.stopPropagation()}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
Loading…
Reference in a new issue