From 3674fd12f3e8a23caba8eed0cf4f0372d8bd261d Mon Sep 17 00:00:00 2001 From: Huuyii-sleeping <3134846106@qq.com> Date: Mon, 6 Jul 2026 23:07:56 +0800 Subject: [PATCH 1/2] feat(textarea): support clearable --- packages/components/textarea/Textarea.tsx | 29 +++++++++- .../textarea/__tests__/textarea.test.tsx | 39 +++++++++++-- .../textarea/_example/clearable.tsx | 20 +++++++ .../components/textarea/_usage/props.json | 8 ++- packages/components/textarea/defaultProps.ts | 1 + .../components/textarea/textarea.en-US.md | 50 ++++++++-------- packages/components/textarea/textarea.md | 50 ++++++++-------- packages/components/textarea/type.ts | 57 +++++++++++++++---- 8 files changed, 189 insertions(+), 65 deletions(-) create mode 100644 packages/components/textarea/_example/clearable.tsx diff --git a/packages/components/textarea/Textarea.tsx b/packages/components/textarea/Textarea.tsx index a78dc72db0..4613f3cd97 100644 --- a/packages/components/textarea/Textarea.tsx +++ b/packages/components/textarea/Textarea.tsx @@ -1,5 +1,6 @@ import React, { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'; import classNames from 'classnames'; +import { CloseCircleFilledIcon as TdCloseCircleFilledIcon } from 'tdesign-icons-react'; import calcTextareaHeight from '@tdesign/common-js/utils/calcTextareaHeight'; import { getCharacterLength, getUnicodeLength, limitUnicodeMaxLength } from '@tdesign/common-js/utils/helper'; @@ -9,6 +10,7 @@ import useConfig from '../hooks/useConfig'; import useControlled from '../hooks/useControlled'; import useDefaultProps from '../hooks/useDefaultProps'; import useEventCallback from '../hooks/useEventCallback'; +import useGlobalIcon from '../hooks/useGlobalIcon'; import useIsomorphicLayoutEffect from '../hooks/useLayoutEffect'; import { textareaDefaultProps } from './defaultProps'; @@ -49,9 +51,12 @@ const Textarea = forwardRef((originalProps, tips, allowInputOverMax, rows, + clearable, + onClear, ...otherProps } = props; const hasMaxcharacter = typeof maxcharacter !== 'undefined'; + const readOnlyProp = props.readOnly || props.readonly; const [value = '', setValue] = useControlled(props, 'value', props.onChange); @@ -72,6 +77,10 @@ const Textarea = forwardRef((originalProps, }, [value, allowInputOverMax, maxcharacter]); const { classPrefix } = useConfig(); + const { CloseCircleFilledIcon } = useGlobalIcon({ + CloseCircleFilledIcon: TdCloseCircleFilledIcon, + }); + const isShowClearIcon = clearable && value && !disabled && !readOnlyProp; const textareaPropsNames = Object.keys(otherProps).filter( (key) => !/^on[A-Z]/.test(key) && !OMIT_PROPS.includes(key), @@ -140,6 +149,13 @@ const Textarea = forwardRef((originalProps, } } + function handleClear(e: React.MouseEvent) { + composingRef.current = false; + setComposingValue(''); + setValue('', { e, trigger: 'clear' }); + onClear?.({ e }); + } + function handleCompositionStart() { composingRef.current = true; } @@ -216,7 +232,13 @@ const Textarea = forwardRef((originalProps, ); return ( -
+