Skip to content

Commit 004c4a4

Browse files
jrgarciadevIsDyh01wingkwonggithub-actions[bot]mstfblci
authored
Feat/textarea add clear button (#4172)
* feat(components): add clear button to the textarea component * docs(textarea): add test and changeset * feat(textarea): modify the changeset file * feat(textarea): add clear button to textarea * feat(textarea): add isClearable prop to textarea * docs(textarea): add documentation to textarea * docs(textarea): add documentation to textarea * feat(textarea): replace the textarea component clear icon and modify its location * feat(textarea): revise the clear button position * feat(textarea): revise the clear button structure * feat(textarea): revise the styles of clear button and textarea * feat(textarea): revise the styles of RTL case * feat(textarea): change the rtl to pe * feat(textarea): delete the px classname * chore(changeset): update package and message * test(textarea): add test case * feat(textarea): change the clear button structure * feat(textarea): optimized code * chore(textarea): update the changeset file * docs(textarea): add slots doc to textarea * chore(textarea): update peerDevpeerDependencies version * chore(textarea): add usecallback dep * Update .changeset/five-adults-protect.md * chore(pre-release): enter pre-release mode * feat(textarea): modify the clear button icon * fix(theme): apply tw nested group (#3909) * chore(changset): add changeset * fix(theme): apply nested group to table * chore(docs): update table bottomContent code * fix: changeset * fix: changeset * fix: changeset * fix: changeset * fix: changeset * fix: pkg versions * fix: changeset * fix: drawer peer dep * chore: update plop components tempalte * ci(changesets): version packages (beta) (#3988) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * fix: pre-release workflow * chore: debug log added * chore: force pre-release * ci(changesets): version packages (beta) * ci(changesets): version packages (beta) * ci(changesets): version packages (beta) * ci(changesets): version packages (beta) * ci(changesets): version packages (beta) * chore: beta1 (#3990) * ci(changesets): version packages (beta) (#3991) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * fix(use-image): image ReferenceError in SSR (#3993) * fix(input): fixed a sliding issue caused by the helper wrapper (#3966) * If it is false and there is an error message or description it will create a div * Update packages/components/input/src/input.tsx * Update packages/components/select/src/select.tsx * Update packages/components/input/src/textarea.tsx * add changeset * changeset update * ci(changesets): version packages (beta) (#3995) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * fix: image loading in the server (#3996) * fix: lock file * chore: force release * chore: force release 2 * ci(changesets): version packages (beta) (#3997) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * fix: image load on next.js (#3998) * ci(changesets): version packages (beta) (#3999) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * fix: element.ref was removed in React 19 warning (#4003) * ci(changesets): version packages (beta) (#4004) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * fix: react 19 as peer dep (#4008) * ci(changesets): version packages (beta) (#4009) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Beta/react 19 support (#4010) * fix: react 19 as peer dep * fix: react 19 as peer dep * chore: support framer-motion alpha version * ci(changesets): version packages (beta) (#4011) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * fix(theme): making select and input themes consistent (#3881) * ci(changesets): version packages (beta) (#4012) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * fix(textarea): fix clearButton display * fix: support inert value with boolean type for react 19 (#4039) * ci(changesets): version packages (beta) (#4041) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * feat: alert design improved (#4054) * ci(changesets): version packages (beta) (#4056) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * feat: drawer improvements (#4057) * ci(changesets): version packages (beta) (#4058) * feat: alert styles improved (#4071) * ci(changesets): version packages (beta) (#4072) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * feat: alert styles improved (#4073) * ci(changesets): version packages (beta) (#4074) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * feat: add number of stars and credits * chore: fix build * chore: improve navabr colors * chore: new changeset (#4083) * ci(changesets): version packages (beta) (#4084) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * chore: pnpm cleaned (#4086) * ci(changesets): version packages (beta) (#4087) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * chore: custom runnner added * chore: custom runner test (#4091) * Beta/custom runner (#4092) * chore: custom runner test * chore: custom runner test * chore: remove 2 from older changeset * ci(changesets): version packages (beta) (#4093) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * feat: new demo added to alert * Feat/virtualization for autocomplete (#4094) * feat: add react-window virtualization for autocomplete * fix: wrong imports and wrong sizing * fix: update pnpm lock * chore: add test cases for large dataset (1000 and 10000 items) * chore: move virtualized-listbox to listbox components folder, implement isVirtualized conditional * feat: implement dynamic listboxheight n item height, add story * chore: rename props, remove unnecessary line changes * fix: maxHeight style 256px for default, conditional usage of virtualizer * feat: migrate to tan-stack virtual. (todo: fix scroll shadow) * feat: virtualization support --------- Co-authored-by: Vincentius Roger Kuswara <[email protected]> * ci(changesets): version packages (beta) (#4095) * feat: small fixes * feat: add reducedMotion setting to Provider (#3470) * feat: add reducedMotion setting to Provider * chore: refactor reducedMotion story * Update .changeset/pretty-parrots-guess.md --------- Co-authored-by: Junior Garcia <[email protected]> * ci(changesets): version packages (beta) (#4106) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * fix: move circular-progress tv to progress (#3321) * fix: remove circular-progress tv to progress * docs: changeset * chore(changeset): update changeset message * Update .changeset/angry-maps-serve.md --------- Co-authored-by: աӄա <[email protected]> Co-authored-by: Junior Garcia <[email protected]> * fix: label placement when the select has a placeholder or description (#4126) * ci(changesets): version packages (beta) (#4107) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * fix(deps): add missing `framer-motion` in `peerDependencies` (#4140) * fix(theme): add truncate class to the list item to avoid overflow the wrapper (#4105) * fix(docs): invalid canary storybook link (#4030) * fix: menu item hidden overflow text * feat: changeset * Merge branch 'beta/release-next' into fix/menu-item-hidden * fix: truncate list item * feat: update changeset * fix(menu): omit internal props --------- Co-authored-by: աӄա <[email protected]> Co-authored-by: Junior Garcia <[email protected]> * Update apps/docs/content/docs/components/textarea.mdx * feat(table): add isKeyboardNavigationDisabled prop to the table (#3735) Co-authored-by: Maharshi Alpesh <[email protected]> * feat: add form component (#3036) * chore: add support validationBehavior aria * chore: add validationBehavior to Provider * chore: add autocomplete validation test * chore: add checkbox validation test * fix(input): require condition * docs: add description of validationBehavior props * chore: add support validationBehavior props for date components * docs(dates): add description of validationBehavior props * chore: add changeset * chore: format * chore: fix test * fix: select validationBehavior is not support yet * fix: select validationBehavior not supported yet * feat: add form component with input support * feat: add support form context * chore: wip add support for form server errors * chore: add support checkbox server validation * chore: add support radio server validation * chore: update pnpm-lock.yaml * chore: add support input server validation * chore: add support autocomplete server validation * chore(form): add server validation stories * chore: fix test * chore: add date-picker validation test * chore: update form stories * chore: add changeset * chore: update react-aria version * chore: add pnpm-lock.yaml * chore: update react-aria version * chore: add comment * chore: update react-aria version * chore: fix change set * chore: export form component in the main package * chore: upgrade react-aria * chore: fixed internationalized/date version * fix: build error * chore: upgrade docs react-aria version * fix: remove comment * fix: debug setting * chore(docs): update sponsor (#3904) * chore(docs): remove Scrumbuiss * chore(docs): remove Scrumbuiss logo * chore(docs): replace va by posthog (#4123) * chore(changeset): change to patch * refactor: react-aria-components remove to decrease package size, logic moved to the form package --------- Co-authored-by: Junior Garcia <[email protected]> Co-authored-by: WK Wong <[email protected]> * docs: add forms guide (#4155) Co-authored-by: Ryo Matsukawa <[email protected]> * chore: routes updated * ci(changesets): version packages (beta) (#4151) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * chore: fix indentation * fix(changeset): package not be found * ci(changesets): version packages (beta) (#4158) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * fix(select): controlled isInvalid prop (#4082) * fix(select): controlled isInvalid prop * chore: add changeset * Merge branch 'beta/release-next' into pr/4082 --------- Co-authored-by: WK Wong <[email protected]> * ci(changesets): version packages (beta) (#4159) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * chore(changeset): bump all versions * ci(changesets): version packages (beta) (#4160) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * fix(deps): missing peer / dev dependency for framer-motion (#4161) * fix(system): align `navigate` function parameters with `@react-aria` (#4163) * fix: menu item classNames not work (#4156) * fix: menu item classNames not work * feat: changeset * docs: update * feat: merge classes utility added * Update .changeset/brave-trains-wave.md --------- Co-authored-by: WK Wong <[email protected]> Co-authored-by: Junior Garcia <[email protected]> * chore(docs): remove incorrect info * ci(changesets): version packages (beta) (#4162) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * refactor(docs): overall dx (#4055) * refactor(docs): revise code block (#3922) * refactor(docs): revise code block * chore(docs): resolve pr comments * refactor(docs): autocomplete dx (#3934) * feat(docs): add *.js?raw module * feat(docs): change to react-jsx and add **/*.js * chore(root): include js and jsx * refactor(docs): autocomplete dx * chore(docs): rollback overrides * chore(autocomplete): lint * fix(autocomplete): incorrect import path * fix(docs): autocomplete dx * chore(docs): remove highlightedLines * refactor(docs): breadcrumbs dx (#3968) * refactor(docs): breadcrumbs dx * fix(docs): export issue * chore(docs): use preserve for jsx * fix(docs): support multiline import * fix(docs): support multiple export * chore(docs): add back export * refactor(docs): avatar dx (#3951) * refactor(docs): badge dx (#3960) * refactor(docs): badge dx * chore(docs): incorrect import path * refactor(docs): button dx (#3981) * refactor(docs): calendar dx (#4022) * refactor(docs): calendar dx * fix(docs): incorrect import path * refactor(docs): switch dx (#4037) * refactor(docs): switch dx * chore(docs): remove highlightedLines * refactor(docs): tooltip (#4035) * refactor(docs): usage dx (#4036) * refactor(docs): circular-progress dx (#4029) * refactor(docs): chip-dx (#4028) * refactor(docs): checkbox-group dx (#4027) * refactor(docs): checkbox dx (#4024) * refactor(docs): checkbox dx * fix(docs): incorrect import path * refactor(docs): card dx (#4023) * refactor(docs): skeleton dx (#4042) * refactor(docs): spacer dx (#4043) * refactor(docs): snippet dx (#4044) * refactor(docs): scroll-shadow dx (#4045) * refactor(docs): code dx (#4046) * refactor(docs): kbd dx (#4047) * refactor(docs): link dx (#4048) * refactor(docs): progress dx (#4049) * refactor(docs): divider dx (#4050) * refactor(docs): listbox dx (#4051) * refactor(docs): listbox dx * fix(docs): import path * fix(docs): import path * chore(docs): remove highlightedLines * fix(docs): indentation * chore(docs): replace the props of autocomplete from value to key (#4129) * refactor(docs): alert dx (#4108) * refactor(docs): alert dx * refactor(docs): alert dx * refactor(docs): image dx (#4061) * refactor(docs): textarea dx (#4063) * refactor(docs): spinner dx (#4088) * refactor(docs): radio-group dx (#4064) * refactor(docs): pagination dx (#4062) * refactor(docs): pagination dx * refactor(docs): pagination dx * refactor(docs): time-input dx (#4065) * refactor(docs): time-input dx * refactor(docs): time-input dx * refactor(docs): slider dx (#4066) * refactor(docs): slider dx * refactor(docs): slider dx * refactor(docs): move SliderValue to type * refactor(docs): slider dx * refactor(docs): make icon code collapsible * refactor(docs): specify versions for date packages (#4138) * refactor(docs): specify versions for date packages * fix(docs): correct RA i18n version * chore(deps): sync version from package * refactor(docs): tabs dx (#4067) * refactor(docs): tab dx * refactor(docs): tabs dx * refactor(docs): input dx (#4102) * refactor(docs): input dx * refactor(docs): input dx * refactor(docs): navbar dx (#4076) * refactor(docs): navbar dx * refactor(docs): navbar dx * refactor(docs): navbar dx * refactor(docs): modal dx (#4077) * refactor(docs): modal dx * refactor(docs): modal dx * refactor(docs): select dx (#4078) * refactor(docs): select dx * refactor(docs): select dx * refactor(docs): select dx * refactor(docs): select dx * refactor(docs): select dx * refactor(docs): table dx (#4079) * refactor(docs): table dx * fix(docs): import path * refactor(docs): table dx * refactor(docs): table dx * refactor(docs): popover dx (#4090) * refactor(docs): range-calendar dx (#4089) * refactor(docs): range-calendar dx * fix(docs): import path * refactor(docs): date input dx (#4100) * refactor(docs): dropdown dx (#4101) * refactor(docs): dropdown dx * refactor(docs): remove highlightedLines * refactor(docs): dropdown dx * refactor(docs): dropdown dx * refactor(docs): date-picker dx (#4103) * refactor(docs): date-picker dx * fix(docs): import paths * refactor(docs): date-range-picker dx (#4104) * refactor(docs): date-range-picker dx * fix(docs): date-range-picker dx * refactor(docs): drawer dx (#4109) * refactor(docs): drawer dx * fix(docs): indentation * refactor(docs): make icon collapsible --------- Co-authored-by: աӄա <[email protected]> Co-authored-by: Ryo Matsukawa <[email protected]> * Merge branch 'beta/release-next' into pr/3477 * refactor(docs): apply new structure to doc * feat(input-otp): introduce input OTP component (#4052) * feat(input-otp): adding the functionality * fix(input-otp): making the use of input-otp library * Update .changeset/spotty-flies-jump.md * chore(input-otp): nits * feat: improvements and fixes added * refactor: input-otp docs improvements * fix: changeset * fix: build --------- Co-authored-by: Maharshi Alpesh <[email protected]> Co-authored-by: Junior Garcia <[email protected]> * ci(changesets): version packages (beta) (#4169) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * refactor(theme): revise label font size for lg (#4141) * refactor(theme): revise label font size for lg * chore(changeset): add changeset * refactor(theme): revise label font size for lg * fix(docs): typecheck errors (#4171) * fix(docs): remove duplicate import * fix(docs): update type for onChange in range-calendar page * fix(docs): add missing `@react-types/calendar` * fix(docs): broken syntax * fix(docs): typecheck issues * fix(docs): add missing `@react-types/datepicker` * fix(docs): typecheck issues * fix: missing li tag when href is specified (#4168) * fix(items): items in list should wrapped in li in case of a * chore: adding the tests * fix: textarea issues with the clear button * chore: adjust clear button position --------- Co-authored-by: doki- <[email protected]> Co-authored-by: WK Wong <[email protected]> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Mustafa Balcı <[email protected]> Co-authored-by: Maharshi Alpesh <[email protected]> Co-authored-by: Vincentius Roger Kuswara <[email protected]> Co-authored-by: Ryo Matsukawa <[email protected]> Co-authored-by: winches <[email protected]> Co-authored-by: Tianen Pang <[email protected]> Co-authored-by: Maharshi Alpesh <[email protected]> Co-authored-by: chirokas <[email protected]>
1 parent 0b5ceb9 commit 004c4a4

File tree

11 files changed

+182
-10
lines changed

11 files changed

+182
-10
lines changed

.changeset/five-adults-protect.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@nextui-org/input": patch
3+
"@nextui-org/shared-icons": patch
4+
"@nextui-org/theme": patch
5+
---
6+
7+
introduce `isClearable` to Textarea component (#2348, #2112)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import {Textarea} from "@nextui-org/react";
2+
3+
export default function App() {
4+
return (
5+
<Textarea
6+
isClearable
7+
className="max-w-xs"
8+
defaultValue="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
9+
label="Description"
10+
placeholder="Description"
11+
variant="bordered"
12+
// eslint-disable-next-line no-console
13+
onClear={() => console.log("textarea cleared")}
14+
/>
15+
);
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import App from "./clear-button.raw.jsx?raw";
2+
3+
const react = {
4+
"/App.jsx": App,
5+
};
6+
7+
export default {
8+
...react,
9+
};

apps/docs/content/components/textarea/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import errorMessage from "./error-message";
88
import description from "./description";
99
import controlled from "./controlled";
1010
import disableAutosize from "./disable-autosize";
11+
import clearButton from "./clear-button";
1112

1213
export const textareaContent = {
1314
usage,
@@ -20,4 +21,5 @@ export const textareaContent = {
2021
description,
2122
controlled,
2223
disableAutosize,
24+
clearButton,
2325
};

apps/docs/content/docs/components/textarea.mdx

+10
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ the end of the label and the textarea will be required.
5656

5757
<CodeDemo title="Required" files={textareaContent.required} />
5858

59+
### Clear Button
60+
61+
If you pass the `isClearable` property to the textarea, it will have a clear button at the
62+
end of the textarea, it will be visible when the textarea has a value.
63+
64+
<CodeDemo title="Clear Button" files={textareaContent.clearButton} />
65+
5966
### Autosize
6067

6168
Textarea grows automatically based on the content, but you can also set a min and max height to
@@ -92,6 +99,7 @@ You can use the `value` and `onValueChange` properties to control the input valu
9299
> **Note**: NextUI `Textarea` also supports native events like `onChange`, useful for form libraries
93100
> such as [Formik](https://formik.org/) and [React Hook Form](https://react-hook-form.com/).
94101
102+
95103
## Slots
96104

97105
- **base**: Input wrapper, it handles alignment, placement, and general appearance.
@@ -100,6 +108,7 @@ You can use the `value` and `onValueChange` properties to control the input valu
100108
- **input**: The textarea input element.
101109
- **description**: The description of the textarea.
102110
- **errorMessage**: The error message of the textarea.
111+
- **headerWrapper**: Wraps the `label` and the `clearButton`.
103112

104113
<Spacer y={4} />
105114

@@ -163,6 +172,7 @@ You can use the `value` and `onValueChange` properties to control the input valu
163172
| isRequired | `boolean` | Whether user input is required on the textarea before form submission. | `false` |
164173
| isReadOnly | `boolean` | Whether the textarea can be selected but not changed by the user. | |
165174
| isDisabled | `boolean` | Whether the textarea is disabled. | `false` |
175+
| isClearable | `boolean` | Whether the textarea should have a clear button. | `false` |
166176
| isInvalid | `boolean` | Whether the textarea is invalid. | `false` |
167177
| validationState | `valid` \| `invalid` | Whether the textarea should display its "valid" or "invalid" visual styling. (**Deprecated**) use **isInvalid** instead. | - |
168178
| disableAutosize | `boolean` | Whether the textarea auto vertically resize should be disabled. | `false` |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import * as React from "react";
2+
import {render} from "@testing-library/react";
3+
import userEvent from "@testing-library/user-event";
4+
5+
import {Textarea} from "../src";
6+
7+
describe("Textarea", () => {
8+
it("should clear the value and onClear is triggered", async () => {
9+
const onClear = jest.fn();
10+
11+
const ref = React.createRef<HTMLTextAreaElement>();
12+
13+
const {getByRole} = render(
14+
<Textarea
15+
ref={ref}
16+
isClearable
17+
defaultValue="[email protected]"
18+
label="test textarea"
19+
onClear={onClear}
20+
/>,
21+
);
22+
23+
const clearButton = getByRole("button");
24+
25+
expect(clearButton).not.toBeNull();
26+
27+
const user = userEvent.setup();
28+
29+
await user.click(clearButton);
30+
31+
expect(ref.current?.value)?.toBe("");
32+
33+
expect(onClear).toHaveBeenCalledTimes(1);
34+
});
35+
36+
it("should disable clear button when isReadOnly is true", async () => {
37+
const onClear = jest.fn();
38+
39+
const ref = React.createRef<HTMLTextAreaElement>();
40+
41+
const {getByRole} = render(
42+
<Textarea
43+
ref={ref}
44+
isClearable
45+
isReadOnly
46+
defaultValue="readOnly test for clear button"
47+
label="test textarea"
48+
onClear={onClear}
49+
/>,
50+
);
51+
52+
const clearButton = getByRole("button")!;
53+
54+
expect(clearButton).not.toBeNull();
55+
56+
const user = userEvent.setup();
57+
58+
await user.click(clearButton);
59+
60+
expect(onClear).toHaveBeenCalledTimes(0);
61+
});
62+
63+
it("should appear clear button when just define onClear but not define isClearable", async () => {
64+
const onClear = jest.fn();
65+
66+
const ref = React.createRef<HTMLTextAreaElement>();
67+
68+
const {getByRole} = render(
69+
<Textarea
70+
ref={ref}
71+
defaultValue="[email protected]"
72+
label="test textarea"
73+
onClear={onClear}
74+
/>,
75+
);
76+
77+
const clearButton = getByRole("button");
78+
79+
expect(clearButton).not.toBeNull();
80+
});
81+
});

packages/components/input/src/textarea.tsx

+13-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {forwardRef} from "@nextui-org/system";
33
import {mergeProps} from "@react-aria/utils";
44
import {useMemo, useState} from "react";
55
import TextareaAutosize from "react-textarea-autosize";
6+
import {CloseFilledIcon} from "@nextui-org/shared-icons";
67

78
import {UseInputProps, useInput} from "./use-input";
89

@@ -14,11 +15,7 @@ type TextareaAutoSizeStyle = Omit<
1415
height?: number;
1516
};
1617

17-
type OmittedInputProps =
18-
| "isClearButtonFocusVisible"
19-
| "isLabelPlaceholder"
20-
| "isClearable"
21-
| "isTextarea";
18+
type OmittedInputProps = "isClearButtonFocusVisible" | "isLabelPlaceholder" | "isTextarea";
2219

2320
export type TextareaHeightChangeMeta = {
2421
rowHeight: number;
@@ -88,6 +85,8 @@ const Textarea = forwardRef<"textarea", TextAreaProps>(
8885
getHelperWrapperProps,
8986
getDescriptionProps,
9087
getErrorMessageProps,
88+
isClearable,
89+
getClearButtonProps,
9190
} = useInput<HTMLTextAreaElement>({...otherProps, ref, isMultiline: true});
9291

9392
const [hasMultipleRows, setIsHasMultipleRows] = useState(minRows > 1);
@@ -122,6 +121,14 @@ const Textarea = forwardRef<"textarea", TextAreaProps>(
122121
/>
123122
);
124123

124+
const clearButtonContent = useMemo(() => {
125+
return isClearable ? (
126+
<button {...getClearButtonProps()}>
127+
<CloseFilledIcon />
128+
</button>
129+
) : null;
130+
}, [isClearable, getClearButtonProps]);
131+
125132
const innerWrapper = useMemo(() => {
126133
if (startContent || endContent) {
127134
return (
@@ -145,6 +152,7 @@ const Textarea = forwardRef<"textarea", TextAreaProps>(
145152
<div {...getInputWrapperProps()} data-has-multiple-rows={dataAttr(hasMultipleRows)}>
146153
{shouldLabelBeInside ? labelContent : null}
147154
{innerWrapper}
155+
{clearButtonContent}
148156
</div>
149157
{hasHelper && hasHelperContent ? (
150158
<div {...getHelperWrapperProps()}>

packages/components/input/src/use-input.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ export function useInput<T extends HTMLInputElement | HTMLTextAreaElement = HTML
371371
"data-has-start-content": dataAttr(hasStartContent),
372372
"data-has-end-content": dataAttr(!!endContent),
373373
className: slots.input({
374-
class: clsx(classNames?.input, isFilled ? "is-filled" : ""),
374+
class: clsx(classNames?.input, isFilled ? "is-filled" : "", isMultiline ? "pe-0" : ""),
375375
}),
376376
...mergeProps(
377377
focusProps,
@@ -518,7 +518,9 @@ export function useInput<T extends HTMLInputElement | HTMLTextAreaElement = HTML
518518
"aria-label": "clear input",
519519
"data-slot": "clear-button",
520520
"data-focus-visible": dataAttr(isClearButtonFocusVisible),
521-
className: slots.clearButton({class: clsx(classNames?.clearButton, props?.className)}),
521+
className: slots.clearButton({
522+
class: clsx(classNames?.clearButton, props?.className),
523+
}),
522524
...mergeProps(clearPressProps, clearFocusProps),
523525
};
524526
},

packages/components/input/stories/textarea.stories.tsx

+12
Original file line numberDiff line numberDiff line change
@@ -334,3 +334,15 @@ export const IsInvalid = {
334334
errorMessage: "Please enter a valid description",
335335
},
336336
};
337+
338+
export const Clearable = {
339+
render: Template,
340+
341+
args: {
342+
...defaultProps,
343+
placeholder: "Enter your description",
344+
defaultValue: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
345+
// eslint-disable-next-line no-console
346+
onClear: () => console.log("textarea cleared"),
347+
},
348+
};

packages/core/theme/src/components/input.ts

+27-3
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@ const input = tv({
5151
"p-2",
5252
"-m-2",
5353
"z-10",
54-
"hidden",
5554
"absolute",
5655
"end-3",
5756
"start-auto",
57+
"pointer-events-none",
5858
"appearance-none",
5959
"outline-none",
6060
"select-none",
@@ -192,7 +192,11 @@ const input = tv({
192192
isClearable: {
193193
true: {
194194
input: "peer pe-6 input-search-cancel-button-none",
195-
clearButton: "peer-data-[filled=true]:opacity-70 peer-data-[filled=true]:block",
195+
clearButton: [
196+
"peer-data-[filled=true]:pointer-events-auto",
197+
"peer-data-[filled=true]:opacity-70 peer-data-[filled=true]:block",
198+
"peer-data-[filled=true]:scale-100",
199+
],
196200
},
197201
},
198202
isDisabled: {
@@ -219,6 +223,7 @@ const input = tv({
219223
inputWrapper: "!h-auto",
220224
innerWrapper: "items-start group-data-[has-label=true]:items-start",
221225
input: "resize-none data-[hide-scroll=true]:scrollbar-hide",
226+
clearButton: "absolute top-2 right-2 rtl:right-auto rtl:left-2 z-10",
222227
},
223228
},
224229
disableAnimation: {
@@ -236,7 +241,14 @@ const input = tv({
236241
"motion-reduce:transition-none",
237242
"transition-[transform,color,left,opacity]",
238243
],
239-
clearButton: ["transition-opacity", "motion-reduce:transition-none"],
244+
clearButton: [
245+
"scale-90",
246+
"ease-out",
247+
"duration-150",
248+
"transition-[opacity,transform]",
249+
"motion-reduce:transition-none",
250+
"motion-reduce:scale-100",
251+
],
240252
},
241253
},
242254
},
@@ -862,6 +874,18 @@ const input = tv({
862874
inputWrapper: "data-[has-multiple-rows=true]:rounded-large",
863875
},
864876
},
877+
// isClearable & isMultiline
878+
{
879+
isClearable: true,
880+
isMultiline: true,
881+
class: {
882+
clearButton: [
883+
"group-data-[has-value=true]:opacity-70 group-data-[has-value=true]:block",
884+
"group-data-[has-value=true]:scale-100",
885+
"group-data-[has-value=true]:pointer-events-auto",
886+
],
887+
},
888+
},
865889
],
866890
});
867891

packages/utilities/shared-icons/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export * from "./info-circle";
3737
export * from "./warning";
3838
export * from "./danger";
3939
export * from "./success";
40+
4041
// sets
4142
export * from "./bulk";
4243
export * from "./bold";

0 commit comments

Comments
 (0)