Skip to content

Commit

Permalink
Feat/textarea add clear button (#4172)
Browse files Browse the repository at this point in the history
* 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 <vincentiusrkuswara@gmail.com>

* 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 <jrgarciadev@gmail.com>

* 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: աӄա <wingkwong.code@gmail.com>
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>

* 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: աӄա <wingkwong.code@gmail.com>
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>

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

* feat(table): add isKeyboardNavigationDisabled prop to the table (#3735)

Co-authored-by: Maharshi Alpesh <maharshialpesh@Maharshi-Book.local>

* 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 <jrgarciadev@gmail.com>
Co-authored-by: WK Wong <wingkwong.code@gmail.com>

* docs: add forms guide (#4155)

Co-authored-by: Ryo Matsukawa <76232929+ryo-manba@users.noreply.github.com>

* 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 <wingkwong.code@gmail.com>

* 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 <wingkwong.code@gmail.com>
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>

* 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: աӄա <wingkwong.code@gmail.com>
Co-authored-by: Ryo Matsukawa <76232929+ryo-manba@users.noreply.github.com>

* 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 <maharshialpesh@Maharshi-Book.local>
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>

* 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- <1335902682@qq.com>
Co-authored-by: WK Wong <wingkwong.code@gmail.com>
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ı <19329346+mstfblci@users.noreply.github.com>
Co-authored-by: Maharshi Alpesh <maharshialpesh@gmail.com>
Co-authored-by: Vincentius Roger Kuswara <vincentiusrkuswara@gmail.com>
Co-authored-by: Ryo Matsukawa <76232929+ryo-manba@users.noreply.github.com>
Co-authored-by: winches <329487092@qq.com>
Co-authored-by: Tianen Pang <32772271+tianenpang@users.noreply.github.com>
Co-authored-by: Maharshi Alpesh <maharshialpesh@Maharshi-Book.local>
Co-authored-by: chirokas <157580465+chirokas@users.noreply.github.com>
  • Loading branch information
13 people authored Nov 29, 2024
1 parent 0b5ceb9 commit 004c4a4
Show file tree
Hide file tree
Showing 11 changed files with 182 additions and 10 deletions.
7 changes: 7 additions & 0 deletions .changeset/five-adults-protect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@nextui-org/input": patch
"@nextui-org/shared-icons": patch
"@nextui-org/theme": patch
---

introduce `isClearable` to Textarea component (#2348, #2112)
16 changes: 16 additions & 0 deletions apps/docs/content/components/textarea/clear-button.raw.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {Textarea} from "@nextui-org/react";

export default function App() {
return (
<Textarea
isClearable
className="max-w-xs"
defaultValue="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
label="Description"
placeholder="Description"
variant="bordered"
// eslint-disable-next-line no-console
onClear={() => console.log("textarea cleared")}
/>
);
}
9 changes: 9 additions & 0 deletions apps/docs/content/components/textarea/clear-button.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import App from "./clear-button.raw.jsx?raw";

const react = {
"/App.jsx": App,
};

export default {
...react,
};
2 changes: 2 additions & 0 deletions apps/docs/content/components/textarea/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import errorMessage from "./error-message";
import description from "./description";
import controlled from "./controlled";
import disableAutosize from "./disable-autosize";
import clearButton from "./clear-button";

export const textareaContent = {
usage,
Expand All @@ -20,4 +21,5 @@ export const textareaContent = {
description,
controlled,
disableAutosize,
clearButton,
};
10 changes: 10 additions & 0 deletions apps/docs/content/docs/components/textarea.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ the end of the label and the textarea will be required.

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

### Clear Button

If you pass the `isClearable` property to the textarea, it will have a clear button at the
end of the textarea, it will be visible when the textarea has a value.

<CodeDemo title="Clear Button" files={textareaContent.clearButton} />

### Autosize

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

## Slots

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

<Spacer y={4} />

Expand Down Expand Up @@ -163,6 +172,7 @@ You can use the `value` and `onValueChange` properties to control the input valu
| isRequired | `boolean` | Whether user input is required on the textarea before form submission. | `false` |
| isReadOnly | `boolean` | Whether the textarea can be selected but not changed by the user. | |
| isDisabled | `boolean` | Whether the textarea is disabled. | `false` |
| isClearable | `boolean` | Whether the textarea should have a clear button. | `false` |
| isInvalid | `boolean` | Whether the textarea is invalid. | `false` |
| validationState | `valid` \| `invalid` | Whether the textarea should display its "valid" or "invalid" visual styling. (**Deprecated**) use **isInvalid** instead. | - |
| disableAutosize | `boolean` | Whether the textarea auto vertically resize should be disabled. | `false` |
Expand Down
81 changes: 81 additions & 0 deletions packages/components/input/__tests__/textarea.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import * as React from "react";
import {render} from "@testing-library/react";
import userEvent from "@testing-library/user-event";

import {Textarea} from "../src";

describe("Textarea", () => {
it("should clear the value and onClear is triggered", async () => {
const onClear = jest.fn();

const ref = React.createRef<HTMLTextAreaElement>();

const {getByRole} = render(
<Textarea
ref={ref}
isClearable
defaultValue="junior@nextui.org"
label="test textarea"
onClear={onClear}
/>,
);

const clearButton = getByRole("button");

expect(clearButton).not.toBeNull();

const user = userEvent.setup();

await user.click(clearButton);

expect(ref.current?.value)?.toBe("");

expect(onClear).toHaveBeenCalledTimes(1);
});

it("should disable clear button when isReadOnly is true", async () => {
const onClear = jest.fn();

const ref = React.createRef<HTMLTextAreaElement>();

const {getByRole} = render(
<Textarea
ref={ref}
isClearable
isReadOnly
defaultValue="readOnly test for clear button"
label="test textarea"
onClear={onClear}
/>,
);

const clearButton = getByRole("button")!;

expect(clearButton).not.toBeNull();

const user = userEvent.setup();

await user.click(clearButton);

expect(onClear).toHaveBeenCalledTimes(0);
});

it("should appear clear button when just define onClear but not define isClearable", async () => {
const onClear = jest.fn();

const ref = React.createRef<HTMLTextAreaElement>();

const {getByRole} = render(
<Textarea
ref={ref}
defaultValue="junior@nextui.org"
label="test textarea"
onClear={onClear}
/>,
);

const clearButton = getByRole("button");

expect(clearButton).not.toBeNull();
});
});
18 changes: 13 additions & 5 deletions packages/components/input/src/textarea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {forwardRef} from "@nextui-org/system";
import {mergeProps} from "@react-aria/utils";
import {useMemo, useState} from "react";
import TextareaAutosize from "react-textarea-autosize";
import {CloseFilledIcon} from "@nextui-org/shared-icons";

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

Expand All @@ -14,11 +15,7 @@ type TextareaAutoSizeStyle = Omit<
height?: number;
};

type OmittedInputProps =
| "isClearButtonFocusVisible"
| "isLabelPlaceholder"
| "isClearable"
| "isTextarea";
type OmittedInputProps = "isClearButtonFocusVisible" | "isLabelPlaceholder" | "isTextarea";

export type TextareaHeightChangeMeta = {
rowHeight: number;
Expand Down Expand Up @@ -88,6 +85,8 @@ const Textarea = forwardRef<"textarea", TextAreaProps>(
getHelperWrapperProps,
getDescriptionProps,
getErrorMessageProps,
isClearable,
getClearButtonProps,
} = useInput<HTMLTextAreaElement>({...otherProps, ref, isMultiline: true});

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

const clearButtonContent = useMemo(() => {
return isClearable ? (
<button {...getClearButtonProps()}>
<CloseFilledIcon />
</button>
) : null;
}, [isClearable, getClearButtonProps]);

const innerWrapper = useMemo(() => {
if (startContent || endContent) {
return (
Expand All @@ -145,6 +152,7 @@ const Textarea = forwardRef<"textarea", TextAreaProps>(
<div {...getInputWrapperProps()} data-has-multiple-rows={dataAttr(hasMultipleRows)}>
{shouldLabelBeInside ? labelContent : null}
{innerWrapper}
{clearButtonContent}
</div>
{hasHelper && hasHelperContent ? (
<div {...getHelperWrapperProps()}>
Expand Down
6 changes: 4 additions & 2 deletions packages/components/input/src/use-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ export function useInput<T extends HTMLInputElement | HTMLTextAreaElement = HTML
"data-has-start-content": dataAttr(hasStartContent),
"data-has-end-content": dataAttr(!!endContent),
className: slots.input({
class: clsx(classNames?.input, isFilled ? "is-filled" : ""),
class: clsx(classNames?.input, isFilled ? "is-filled" : "", isMultiline ? "pe-0" : ""),
}),
...mergeProps(
focusProps,
Expand Down Expand Up @@ -518,7 +518,9 @@ export function useInput<T extends HTMLInputElement | HTMLTextAreaElement = HTML
"aria-label": "clear input",
"data-slot": "clear-button",
"data-focus-visible": dataAttr(isClearButtonFocusVisible),
className: slots.clearButton({class: clsx(classNames?.clearButton, props?.className)}),
className: slots.clearButton({
class: clsx(classNames?.clearButton, props?.className),
}),
...mergeProps(clearPressProps, clearFocusProps),
};
},
Expand Down
12 changes: 12 additions & 0 deletions packages/components/input/stories/textarea.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -334,3 +334,15 @@ export const IsInvalid = {
errorMessage: "Please enter a valid description",
},
};

export const Clearable = {
render: Template,

args: {
...defaultProps,
placeholder: "Enter your description",
defaultValue: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
// eslint-disable-next-line no-console
onClear: () => console.log("textarea cleared"),
},
};
30 changes: 27 additions & 3 deletions packages/core/theme/src/components/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ const input = tv({
"p-2",
"-m-2",
"z-10",
"hidden",
"absolute",
"end-3",
"start-auto",
"pointer-events-none",
"appearance-none",
"outline-none",
"select-none",
Expand Down Expand Up @@ -192,7 +192,11 @@ const input = tv({
isClearable: {
true: {
input: "peer pe-6 input-search-cancel-button-none",
clearButton: "peer-data-[filled=true]:opacity-70 peer-data-[filled=true]:block",
clearButton: [
"peer-data-[filled=true]:pointer-events-auto",
"peer-data-[filled=true]:opacity-70 peer-data-[filled=true]:block",
"peer-data-[filled=true]:scale-100",
],
},
},
isDisabled: {
Expand All @@ -219,6 +223,7 @@ const input = tv({
inputWrapper: "!h-auto",
innerWrapper: "items-start group-data-[has-label=true]:items-start",
input: "resize-none data-[hide-scroll=true]:scrollbar-hide",
clearButton: "absolute top-2 right-2 rtl:right-auto rtl:left-2 z-10",
},
},
disableAnimation: {
Expand All @@ -236,7 +241,14 @@ const input = tv({
"motion-reduce:transition-none",
"transition-[transform,color,left,opacity]",
],
clearButton: ["transition-opacity", "motion-reduce:transition-none"],
clearButton: [
"scale-90",
"ease-out",
"duration-150",
"transition-[opacity,transform]",
"motion-reduce:transition-none",
"motion-reduce:scale-100",
],
},
},
},
Expand Down Expand Up @@ -862,6 +874,18 @@ const input = tv({
inputWrapper: "data-[has-multiple-rows=true]:rounded-large",
},
},
// isClearable & isMultiline
{
isClearable: true,
isMultiline: true,
class: {
clearButton: [
"group-data-[has-value=true]:opacity-70 group-data-[has-value=true]:block",
"group-data-[has-value=true]:scale-100",
"group-data-[has-value=true]:pointer-events-auto",
],
},
},
],
});

Expand Down
1 change: 1 addition & 0 deletions packages/utilities/shared-icons/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export * from "./info-circle";
export * from "./warning";
export * from "./danger";
export * from "./success";

// sets
export * from "./bulk";
export * from "./bold";
Expand Down

0 comments on commit 004c4a4

Please sign in to comment.