Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/core/src/common/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ export type HTMLDivProps = React.HTMLAttributes<HTMLDivElement>;
*/
export type HTMLInputProps = React.InputHTMLAttributes<HTMLInputElement>;

/**
* Alias for all valid HTML props for `<textarea>` element.
* Does not include React's `ref` or `key`.
*/
export type HTMLTextAreaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;

/**
* Alias for a `React.JSX.Element` or a value that renders nothing.
*
Expand Down
20 changes: 16 additions & 4 deletions packages/core/src/components/editable-text/editableText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,22 @@ import classNames from "classnames";
import * as React from "react";

import { AbstractPureComponent, Classes } from "../../common";
import { DISPLAYNAME_PREFIX, type IntentProps, type Props } from "../../common/props";
import {
DISPLAYNAME_PREFIX,
type HTMLInputProps,
type HTMLTextAreaProps,
type IntentProps,
type Props,
} from "../../common/props";
import { clamp } from "../../common/utils";

export interface EditableTextProps extends IntentProps, Props {
/**
* Custom attributes that will be passed to the underlying input (or textarea) element.
* This allows you to specify additional attributes like
* `aria-` attributes, `data-` attributes, etc.
*/
customInputAttributes?: HTMLInputProps & HTMLTextAreaProps;
/**
* EXPERIMENTAL FEATURE.
*
Expand Down Expand Up @@ -383,7 +395,7 @@ export class EditableText extends AbstractPureComponent<EditableTextProps, Edita
};

private renderInput(value: string | undefined) {
const { disabled, maxLength, multiline, type, placeholder } = this.props;
const { disabled, maxLength, multiline, type, placeholder, customInputAttributes } = this.props;
const props: React.InputHTMLAttributes<HTMLInputElement | HTMLTextAreaElement> = {
className: Classes.EDITABLE_TEXT_INPUT,
disabled,
Expand All @@ -405,9 +417,9 @@ export class EditableText extends AbstractPureComponent<EditableTextProps, Edita
}

return multiline ? (
<textarea ref={this.refHandlers.input} {...props} />
<textarea ref={this.refHandlers.input} {...props} {...customInputAttributes} />
) : (
<input ref={this.refHandlers.input} type={type} {...props} />
<input ref={this.refHandlers.input} type={type} {...props} {...customInputAttributes} />
);
}

Expand Down
26 changes: 26 additions & 0 deletions packages/core/test/editable-text/editableTextTests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -310,4 +310,30 @@ describe("<EditableText>", () => {
wrapper.find("textarea").simulate("change", { target: { value } }).simulate("keydown", e);
}
});

describe("custom attributes", () => {
const customProps = {
"aria-label": "Edit description",
"data-gramm": "false",
spellcheck: "false",
};

it("passes custom attributes to textarea when multiline is true", () => {
const wrapper = mount(
<EditableText isEditing={true} multiline={true} customInputAttributes={customProps} />,
).find("textarea");
assert.strictEqual(wrapper.prop("data-gramm"), "false");
assert.strictEqual(wrapper.prop("spellcheck"), "false");
assert.strictEqual(wrapper.prop("aria-label"), "Edit description");
});

it("passes custom attributes to input when multiline is false", () => {
const wrapper = mount(
<EditableText isEditing={true} multiline={false} customInputAttributes={customProps} />,
).find("input");
assert.strictEqual(wrapper.prop("data-gramm"), "false");
assert.strictEqual(wrapper.prop("spellcheck"), "false");
assert.strictEqual(wrapper.prop("aria-label"), "Edit description");
});
});
});