Skip to content

Commit

Permalink
chore(Textarea): migrate to Tailwind
Browse files Browse the repository at this point in the history
chore(tailwind): add boxShadow formElement tokens

test: update snapshots

chore(tokens): fix small typo

chore(tokens): add formElementBorderColorErrorHover

chore(tailwind): add form-element-error-hover box-shadow classname
  • Loading branch information
mainframev committed Oct 9, 2023
1 parent 58ba32c commit 6599337
Show file tree
Hide file tree
Showing 12 changed files with 451 additions and 38 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import * as React from "react";
import { action } from "@storybook/addon-actions";
import { text, boolean, select, number } from "@storybook/addon-knobs";

import { SIZE_OPTIONS, RESIZE_OPTIONS } from "../../Textarea/consts";
import RenderInRtl from "../../utils/rtl/RenderInRtl";
import SPACINGS_AFTER from "../../common/getSpacingToken/consts";

import Textarea from ".";

export default {
title: "Tailwind/Textarea",
};

export const Default = () => {
const label = text("Label", "Label");
const value = text("Value", "");
const placeholder = text("Placeholder", "Placeholder");

return (
<Textarea label={label} placeholder={placeholder} onChange={action("change")} value={value} />
);
};

Default.story = {
parameters: {
info: "Some description about this type of textarea in general.",
},
};

export const SmallSize = () => {
const value = text("Value", "");
const placeholder = text("Placeholder", "Placeholder");

return (
<Textarea size="small" placeholder={placeholder} onChange={action("change")} value={value} />
);
};

SmallSize.story = {
name: "Small size",

parameters: {
info: "Some description about this type of textarea in general.",
},
};

export const WithLabel = () => {
const label = text("Label", "Label");
const value = text("Value", "");
const placeholder = text("Placeholder", "Placeholder");

return (
<Textarea label={label} placeholder={placeholder} onChange={action("change")} value={value} />
);
};

WithLabel.story = {
name: "With label",

parameters: {
info: "Some description about this type of textarea in general.",
},
};

export const WithHelp = () => {
const value = text("Value", "Something");
const placeholder = text("Placeholder", "Placeholder");
const help = text("Help", "Everything is fine.");

return (
<Textarea placeholder={placeholder} help={help} onChange={action("change")} value={value} />
);
};

WithHelp.story = {
name: "With help",

parameters: {
info: "Some description about this type of textarea in general.",
},
};

export const WithError = () => {
const value = text("Value", "Something");
const placeholder = text("Placeholder", "Placeholder");
const error = text("Error", "Something went wrong.");

return (
<Textarea placeholder={placeholder} error={error} onChange={action("change")} value={value} />
);
};

WithError.story = {
name: "With error",

parameters: {
info: "Some description about this type of textarea in general.",
},
};

export const Playground = () => {
const size = select("Size", Object.values(SIZE_OPTIONS), SIZE_OPTIONS.SMALL);
const label = text("Label", "Label");
const value = text("Value", "");
const fullHeight = boolean("fullHeight", true);
const placeholder = text("Placeholder", "Placeholder");
const help = text("Help", "");
const error = text("Error", "Something went wrong.");
const disabled = boolean("Disabled", false);
const readOnly = boolean("Read-only", false);
const resize = select("resize", Object.values(RESIZE_OPTIONS), RESIZE_OPTIONS.VERTICAL);
const maxLength = number("maxLength", Infinity);
const dataTest = text("dataTest", "test");
const rows = number("rows", 3);
const required = boolean("required", false);
const spaceAfter = select("spaceAfter", Object.values(SPACINGS_AFTER), SPACINGS_AFTER.MEDIUM);

return (
<Textarea
size={size}
label={label}
value={value}
fullHeight={fullHeight}
placeholder={placeholder}
help={help}
error={error}
rows={rows}
required={required}
disabled={disabled}
readOnly={readOnly}
maxLength={maxLength}
resize={resize}
onChange={action("change")}
onFocus={action("focus")}
onBlur={action("blur")}
dataTest={dataTest}
spaceAfter={spaceAfter}
/>
);
};

Playground.story = {
parameters: {
info: "Some description about this type of textarea in general.",
},
};

export const Rtl = () => {
const label = text("Label", "Label");
const help = text("Help", "");
const error = text("Error", "Something went wrong.");
return (
<RenderInRtl>
<Textarea
label={label}
help={help}
error={error}
placeholder="My placeholder"
value="Content of the Textarea"
/>
</RenderInRtl>
);
};

Rtl.story = {
name: "RTL",

parameters: {
info: "This is a preview of this component in RTL setup.",
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import * as React from "react";
import userEvent from "@testing-library/user-event";

import { render, screen, act } from "../../../test-utils";
import Textarea from "..";
import SPACINGS_AFTER from "../../../common/getSpacingToken/consts";

describe("Textarea", () => {
const user = userEvent.setup();

it("should have expected DOM output", async () => {
const name = "name";
const label = "Label";
const placeholder = "placeholder";
const dataTest = "test";
const maxLength = 200;
const fullHeight = true;
const spaceAfter = SPACINGS_AFTER.NORMAL;
const dataAttrs = {
"data-sample": "Sample",
};

render(
<Textarea
name={name}
label={label}
defaultValue="value"
rows={4}
fullHeight={fullHeight}
placeholder={placeholder}
maxLength={maxLength}
help={<div>Something useful.</div>}
dataTest={dataTest}
spaceAfter={spaceAfter}
dataAttrs={dataAttrs}
/>,
);

const textarea = screen.getByRole("textbox");

expect(screen.getByTestId(dataTest)).toBeInTheDocument();
expect(screen.getByDisplayValue("value")).toBeInTheDocument();
expect(screen.getByPlaceholderText(placeholder)).toBeInTheDocument();

await act(() => user.tab());
expect(screen.getByText("Something useful.")).toBeInTheDocument();
expect(textarea).toHaveAttribute("maxlength", maxLength.toString());
expect(textarea).toHaveAttribute("rows", "4");
expect(textarea).toHaveAttribute("name", name);
expect(textarea).toHaveAttribute("data-sample", "Sample");
expect(textarea).not.toBeInvalid();
expect(textarea.parentElement).toHaveStyle({ marginBottom: "12px" });
expect(textarea).toHaveStyle({ padding: "12px" });
});

it("should trigger event handlers", async () => {
const onFocus = jest.fn();
const onBlur = jest.fn();
const onChange = jest.fn();

render(<Textarea onFocus={onFocus} onBlur={onBlur} onChange={onChange} />);

const textarea = screen.getByRole("textbox");

await user.tab();
expect(onFocus).toHaveBeenCalled();
await user.tab();
expect(onBlur).toHaveBeenCalled();
await act(() => user.type(textarea, "kek"));
expect(onChange).toHaveBeenCalled();
});

it("should have error", async () => {
render(<Textarea error="error" size="small" />);
const textarea = screen.getByRole("textbox");

await act(() => user.tab());
expect(screen.getByText("error")).toBeInTheDocument();
expect(textarea).toHaveStyle({ padding: "8px 12px 8px 12px" });
expect(textarea).toBeInvalid();
expect(textarea).toHaveAccessibleDescription("error");
// Needs to flush async `floating-ui` hooks
// https://github.com/floating-ui/floating-ui/issues/1520
await act(async () => {});
});
});
Loading

0 comments on commit 6599337

Please sign in to comment.