dbeaver/pro#5800 refactor: InputFieldBase (#3492)

* dbeaver/pro#5800 refactor: InputFieldBase

update InputField by swapping native input by Input from ui-kit, replace inner action icons to IconButton components, and replace Loader with Spinner component

* dbeaver/pro#5800 fix: enforce border and min-height styles in InlineEditor

* dbeaver/pro#5800 feat: add size prop to Filter component for responsive input sizing

* dbeaver/pro#5800 feat: add UiInput tokens for input component

removes hover effect on inputs by using the same token as for default border

---------

Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
This commit is contained in:
Sychev Andrey
2025-06-12 17:21:29 +08:00
committed by GitHub
co-authored by mr-anton-t
parent c920f84e13
commit fbdb5cd49a
6 changed files with 41 additions and 26 deletions
@@ -119,6 +119,7 @@ export const Filter = observer<ControlledProps | ObjectsProps<any, any>>(functio
readOnly={disabled}
name={name}
value={value}
size={smallSize ? 'small' : 'medium'}
onChange={handleChange}
onKeyDown={handleKeyDown}
/>
@@ -5,9 +5,6 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
.icon {
composes: theme-text-on-secondary from global;
}
.fieldLabel {
display: block;
composes: theme-typography--body1 from global;
@@ -18,23 +15,19 @@
}
.inputContainer {
position: relative;
--dbv-kit-control-outline-offset: -2px;
}
.loaderContainer,
.iconContainer {
position: absolute;
right: 8px;
right: 4px;
top: 50%;
transform: translateY(-50%);
width: 16px;
height: 16px;
display: flex;
}
.iconContainer {
cursor: pointer;
& .icon {
width: 100%;
height: 100%;
}
width: 24px;
height: 24px;
--dbv-kit-icon-btn-outline-offset: -2px;
}
.customIconContainer {
@@ -13,7 +13,6 @@ import { isNotNullDefined } from '@dbeaver/js-helpers';
import { filterLayoutFakeProps, getLayoutProps } from '../../Containers/filterLayoutFakeProps.js';
import type { ILayoutSizeProps } from '../../Containers/ILayoutSizeProps.js';
import { Icon } from '../../Icon.js';
import { Loader } from '../../Loader/Loader.js';
import { useTranslate } from '../../localization/useTranslate.js';
import { s } from '../../s.js';
import { useCombinedHandler } from '../../useCombinedHandler.js';
@@ -25,9 +24,11 @@ import { FieldDescription } from '../FieldDescription.js';
import { FieldLabel } from '../FieldLabel.js';
import { useCapsLockTracker } from '../useCapsLockTracker.js';
import inputFieldStyle from './InputField.module.css';
import { IconButton, Input, Spinner, type InputProps } from '@dbeaver/ui-kit';
export type InputFieldBaseProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'style' | 'ref'> &
export type InputFieldBaseProps = Omit<InputProps, 'onChange'> &
ILayoutSizeProps & {
size?: 'small' | 'medium' | 'large';
value?: string;
error?: boolean;
loading?: boolean;
@@ -119,7 +120,7 @@ export const InputFieldBase = observer<InputFieldBaseProps, HTMLInputElement>(
{children}
</FieldLabel>
<div className={s(styles, { inputContainer: true })}>
<input
<Input
ref={mergedRef}
{...rest}
type={passwordRevealed ? 'text' : rest.type}
@@ -134,18 +135,31 @@ export const InputFieldBase = observer<InputFieldBaseProps, HTMLInputElement>(
/>
{loading && (
<div title={translate('ui_processing_loading')} className={s(styles, { loaderContainer: true })}>
<Loader small />
<Spinner size="small" />
</div>
)}
{passwordType && canShowPassword && (
<div title={translate('ui_reveal_password')} className={styles['iconContainer']} onClick={revealPassword}>
<Icon name={passwordRevealed ? 'password-hide' : 'password-show'} viewBox="0 0 16 16" className={styles['icon']} />
</div>
<IconButton
variant="secondary"
size="small"
aria-label={translate('ui_reveal_password')}
title={translate('ui_reveal_password')}
className={styles['iconContainer']}
onClick={revealPassword}
>
<Icon width={16} height={16} name={passwordRevealed ? 'password-hide' : 'password-show'} viewBox="0 0 16 16" />
</IconButton>
)}
{onCustomCopy && (
<div title={translate('ui_copy_to_clipboard')} className={styles['iconContainer']} onClick={onCustomCopy}>
<Icon name="copy" viewBox="0 0 32 32" className={styles['icon']} />
</div>
<IconButton
size="small"
aria-label={translate('ui_copy_to_clipboard')}
title={translate('ui_copy_to_clipboard')}
className={styles['iconContainer']}
onClick={onCustomCopy}
>
<Icon width={16} height={16} name="copy" viewBox="0 0 32 32" />
</IconButton>
)}
{icon && <div className={s(styles, { customIconContainer: true })}>{icon}</div>}
</div>
@@ -22,6 +22,7 @@ import './styles/main/typography.pure.scss';
import './styles/UiCheckbox.css';
import './styles/UiIconButton.css';
import './styles/UiSpinner.css';
import './styles/UiInput.css';
import { DEFAULT_THEME_ID, themes } from './themes.js';
import { ThemeSettingsService } from './ThemeSettingsService.js';
import type { ClassCollection } from './themeUtils.js';
@@ -0,0 +1,6 @@
@layer components {
.dbv-kit-input {
--dbv-kit-input-radius: 3px;
--dbv-kit-color-control-hover: var(--theme-background);
}
}
@@ -47,11 +47,11 @@
& .input,
& .input[disabled],
& .input[readonly] {
border: none;
border: none !important;
border-radius: unset;
width: 100%;
height: 100%;
min-height: unset;
min-height: unset !important;
padding: 0 8px;
}
}