1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Display hint to user on how to add items in an EditableList (#3475)

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2021-07-23 09:26:23 -04:00 committed by GitHub
parent 239bfec99c
commit 07532b1552
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 10 deletions

View File

@ -53,11 +53,9 @@ export class EditableList<T> extends React.Component<Props<T>> {
@boundMethod
onSubmit(val: string, evt: React.KeyboardEvent) {
const { add } = this.props;
if (val) {
evt.preventDefault();
add(val);
this.props.add(val);
}
}
@ -72,6 +70,7 @@ export class EditableList<T> extends React.Component<Props<T>> {
onSubmit={this.onSubmit}
validators={validators}
placeholder={placeholder}
iconRight={({ isDirty }) => isDirty ? <Icon material="keyboard_return" size={16} /> : null}
/>
</div>
<div className="el-contents">

View File

@ -27,7 +27,6 @@ import { Icon } from "../icon";
import { Tooltip, TooltipProps } from "../tooltip";
import * as Validators from "./input_validators";
import type { InputValidator } from "./input_validators";
import isString from "lodash/isString";
import isFunction from "lodash/isFunction";
import isBoolean from "lodash/isBoolean";
import uniqueId from "lodash/uniqueId";
@ -41,6 +40,18 @@ export type { InputValidator };
type InputElement = HTMLInputElement | HTMLTextAreaElement;
type InputElementProps = InputHTMLAttributes<InputElement> & TextareaHTMLAttributes<InputElement> & DOMAttributes<InputElement>;
export interface IconDataFnArg {
isDirty: boolean;
}
/**
* One of the folloing:
* - A material icon name
* - A react node
* - Or a function that produces a react node
*/
export type IconData = string | React.ReactNode | ((opt: IconDataFnArg) => React.ReactNode);
export type InputProps = Omit<InputElementProps, "onChange" | "onSubmit"> & {
theme?: "round-black" | "round";
className?: string;
@ -53,8 +64,8 @@ export type InputProps = Omit<InputElementProps, "onChange" | "onSubmit"> & {
dirty?: boolean; // show validation errors even if the field wasn't touched yet
showValidationLine?: boolean; // show animated validation line for async validators
showErrorsAsTooltip?: boolean | Omit<TooltipProps, "targetId">; // show validation errors as a tooltip :hover (instead of block below)
iconLeft?: string | React.ReactNode; // material-icon name in case of string-type
iconRight?: string | React.ReactNode;
iconLeft?: IconData;
iconRight?: IconData;
contentRight?: string | React.ReactNode; // Any component of string goes after iconRight
validators?: InputValidator | InputValidator[];
onChange?(value: string, evt: React.ChangeEvent<InputElement>): void;
@ -75,7 +86,6 @@ const defaultProps: Partial<InputProps> = {
maxRows: 10000,
showValidationLine: true,
validators: [],
defaultValue: "",
};
export class Input extends React.Component<InputProps, State> {
@ -105,7 +115,7 @@ export class Input extends React.Component<InputProps, State> {
}
getValue(): string {
const { trim, value, defaultValue } = this.props;
const { trim, value, defaultValue = "" } = this.props;
const rawValue = value ?? this.input?.value ?? defaultValue;
return trim ? rawValue.trim() : rawValue;
@ -262,6 +272,10 @@ export class Input extends React.Component<InputProps, State> {
this.props.onSubmit?.(this.getValue(), evt);
this.setDirtyOnChange.cancel();
this.setState({ submitted: true });
if (this.input && typeof this.props.value !== "string") {
this.input.value = "";
}
} else {
this.setDirty();
}
@ -323,6 +337,20 @@ export class Input extends React.Component<InputProps, State> {
this.input = elem;
}
private renderIcon(iconData: IconData) {
if (typeof iconData === "string") {
return <Icon material={iconData} />;
}
if (typeof iconData === "function") {
return iconData({
isDirty: Boolean(this.getValue()),
});
}
return iconData;
}
render() {
const {
multiLine, showValidationLine, validators, theme, maxRows, children, showErrorsAsTooltip,
@ -383,9 +411,9 @@ export class Input extends React.Component<InputProps, State> {
<div id={componentId} className={className}>
{tooltipError}
<label className="input-area flex gaps align-center" id="">
{isString(iconLeft) ? <Icon material={iconLeft}/> : iconLeft}
{this.renderIcon(iconLeft)}
{multiLine ? <textarea {...inputProps as any} /> : <input {...inputProps as any} />}
{isString(iconRight) ? <Icon material={iconRight}/> : iconRight}
{this.renderIcon(iconRight)}
{contentRight}
</label>
<div className="input-info flex gaps">