diff --git a/src/controls/TextControl.test.tsx b/src/controls/TextControl.test.tsx index aed71b1..5b4e195 100644 --- a/src/controls/TextControl.test.tsx +++ b/src/controls/TextControl.test.tsx @@ -1,10 +1,10 @@ -import { test, expect } from "vitest" +import { test, expect, describe } from "vitest" import { screen, waitFor } from "@testing-library/react" import { userEvent } from "@testing-library/user-event" import type { JSONSchema } from "json-schema-to-ts" import { render } from "../common/test-render" -import type { UISchema } from "../ui-schema" +import type { TextControlOptions, UISchema } from "../ui-schema" import type { JSONFormData } from "../common/schema-derived-types" const textInputSchema = { @@ -130,3 +130,63 @@ test("renders error messages from rule validation", async () => { await screen.findByText("Only letters are allowed") }) + +describe("tooltips", () => { + const getUiSchema = (options?: TextControlOptions) => ({ + type: "VerticalLayout", + elements: [ + { + type: "Control", + scope: "#/properties/name", + label: "Name", + formItemProps: { + tooltip: { + title: ( +

+ Choose{" "} + + a random name + + . +

+ ), + placement: "right", + }, + }, + options, + }, + ], + }) + + const schema = { + type: "object", + properties: { name: { type: "string", title: "Name" } }, + } satisfies JSONSchema + + test("renders tooltip", async () => { + render({ schema, uischema: getUiSchema() }) + await screen.findByPlaceholderText(schema.properties.name.title, { + exact: false, + }) + const svgEl = screen.getByRole("img", { name: /question-circle/i }) + await userEvent.hover(svgEl) + + await screen.findByText("a random name", { exact: false }) + }) + + test("renders right tooltip in case both are passed", async () => { + const options = { tooltip: "You should see this tooltip" } + render({ schema, uischema: getUiSchema(options) }) + await screen.findByPlaceholderText(schema.properties.name.title, { + exact: false, + }) + const svgEl = screen.getByRole("img", { name: /question-circle/i }) + await userEvent.hover(svgEl) + + await screen.findByText("You should see this tooltip") + }) +}) diff --git a/src/controls/TextControl.tsx b/src/controls/TextControl.tsx index bdaa41c..5c85ca7 100644 --- a/src/controls/TextControl.tsx +++ b/src/controls/TextControl.tsx @@ -11,6 +11,7 @@ import type { ControlUISchema, TextControlOptions } from "../ui-schema" import { assertNever } from "../common/assert-never" import { withJsonFormsControlProps } from "@jsonforms/react" import { TextAreaProps } from "antd/es/input/TextArea" + type ControlProps = Omit & { data: string handleChange(path: string, value: string): void @@ -44,7 +45,10 @@ export function TextControl({ (uischema.options as TextControlOptions) ?? {} const formItemProps = "formItemProps" in uischema ? uischema.formItemProps : {} - const tooltip = options.tooltip ? options.tooltip : formItemProps?.tooltip + const { tooltip: formItemTooltip, ...formItemPropsWOTooltip } = + formItemProps ?? {} + const tooltip = options.tooltip ? options.tooltip : formItemTooltip ?? "" + const placeholderText = options.placeholderText const form = Form.useFormInstance() const rules: Rule[] = [ @@ -64,10 +68,10 @@ export function TextControl({ label={label} id={id} name={path} - rules={rules} validateTrigger={["onBlur"]} + rules={rules} tooltip={tooltip} - {...formItemProps} + {...formItemPropsWOTooltip} > + Choose{" "} + + a random name + + . +

+ ), + placement: "right", + }, + }, }, ], } satisfies UISchema, diff --git a/src/ui-schema.ts b/src/ui-schema.ts index 8667ad3..4b6f997 100644 --- a/src/ui-schema.ts +++ b/src/ui-schema.ts @@ -155,6 +155,9 @@ export type AnyOfControlOptions = OneOfControlOptions export type TextControlType = "multiline" | "password" | "singleline" export type TextControlOptions = { + /** + * @deprecated Please use formItemProps.tooltip instead + */ tooltip?: string placeholderText?: string required?: boolean