diff --git a/packages/smarthr-ui/src/components/Textarea/Textarea.stories.tsx b/packages/smarthr-ui/src/components/Textarea/Textarea.stories.tsx
index 676a061c4a..dc2fc14f24 100644
--- a/packages/smarthr-ui/src/components/Textarea/Textarea.stories.tsx
+++ b/packages/smarthr-ui/src/components/Textarea/Textarea.stories.tsx
@@ -46,14 +46,18 @@ const Template: StoryFn = () => {
-
+
@@ -63,7 +67,7 @@ const Template: StoryFn = () => {
@@ -73,12 +77,12 @@ const Template: StoryFn = () => {
diff --git a/packages/smarthr-ui/src/components/Textarea/Textarea.tsx b/packages/smarthr-ui/src/components/Textarea/Textarea.tsx
index e4c4a83d05..63b93e2058 100644
--- a/packages/smarthr-ui/src/components/Textarea/Textarea.tsx
+++ b/packages/smarthr-ui/src/components/Textarea/Textarea.tsx
@@ -10,6 +10,7 @@ import React, {
} from 'react'
import { tv } from 'tailwind-variants'
+import { useId } from '../../hooks/useId'
import { useTheme } from '../../hooks/useTailwindTheme'
import { defaultHtmlFontSize } from '../../themes/createFontSize'
@@ -28,8 +29,10 @@ type Props = {
maxRows?: number
/** 行数の初期値。省略した場合は2 */
rows?: number
+ /** 入力可能な最大文字数。あと何文字入力できるかの表示が追加される。html的なvalidateは発生しない */
+ maxLetters?: number
/** コンポーネント内の文言を変更するための関数を設定 */
- decorators?: DecoratorsType<'beforeMaxLengthCount' | 'afterMaxLengthCount'>
+ decorators?: DecoratorsType<'beforeMaxLettersCount' | 'afterMaxLettersCount'>
/**
* @deprecated placeholder属性は非推奨です。別途ヒント用要素の設置を検討してください。
*/
@@ -50,8 +53,8 @@ const getStringLength = (value: string | number | readonly string[]) => {
return formattedValue.length - (formattedValue.match(surrogatePairs) || []).length
}
-const TEXT_BEFORE_MAXlENGTH_COUNT = 'あと'
-const TEXT_AFTER_MAXlENGTH_COUNT = '文字'
+const TEXT_BEFORE_MAXLETTERS_COUNT = 'あと'
+const TEXT_AFTER_MAXLETTERS_COUNT = '文字'
const textarea = tv({
slots: {
@@ -87,7 +90,7 @@ export const Textarea = forwardRef(
(
{
autoFocus,
- maxLength,
+ maxLetters,
width,
className,
autoResize = false,
@@ -100,20 +103,24 @@ export const Textarea = forwardRef(
},
ref,
) => {
+ const maxLettersId = useId()
+ const actuaMaxLettersId = maxLetters ? maxLettersId : undefined
+
const { lineHeight } = useTheme()
const textareaRef = useRef(null)
const currentValue = props.defaultValue || props.value
const [interimRows, setInterimRows] = useState(rows)
const [count, setCount] = useState(currentValue ? getStringLength(currentValue) : 0)
- const beforeMaxLengthCount = useMemo(
+ const beforeMaxLettersCount = useMemo(
() =>
- decorators?.beforeMaxLengthCount?.(TEXT_BEFORE_MAXlENGTH_COUNT) ||
- TEXT_BEFORE_MAXlENGTH_COUNT,
+ decorators?.beforeMaxLettersCount?.(TEXT_BEFORE_MAXLETTERS_COUNT) ||
+ TEXT_BEFORE_MAXLETTERS_COUNT,
[decorators],
)
- const afterMaxLengthCount = useMemo(
+ const afterMaxLettersCount = useMemo(
() =>
- decorators?.afterMaxLengthCount?.(TEXT_AFTER_MAXlENGTH_COUNT) || TEXT_AFTER_MAXlENGTH_COUNT,
+ decorators?.afterMaxLettersCount?.(TEXT_AFTER_MAXLETTERS_COUNT) ||
+ TEXT_AFTER_MAXLETTERS_COUNT,
[decorators],
)
@@ -128,9 +135,15 @@ export const Textarea = forwardRef(
}
}, [autoFocus])
- const handleKeyup = useCallback((event: React.KeyboardEvent) => {
- setCount(getStringLength(event.currentTarget.value))
- }, [])
+ const onKeyUp = useMemo(
+ () =>
+ maxLetters
+ ? (event: React.KeyboardEvent) => {
+ setCount(getStringLength(event.currentTarget.value))
+ }
+ : undefined,
+ [maxLetters],
+ )
const handleInput = useCallback(
(e: React.ChangeEvent) => {
if (!autoResize) {
@@ -165,30 +178,37 @@ export const Textarea = forwardRef(
style: { width: typeof width === 'number' ? `${width}px` : width },
},
counterStyle: counter(),
- counterTextStyle: counterText({ error: !!(maxLength && maxLength - count <= 0) }),
+ counterTextStyle: counterText({ error: !!(maxLetters && maxLetters - count <= 0) }),
}
- }, [className, count, error, maxLength, width])
-
- return (
- <>
- {/* eslint-disable-next-line smarthr/a11y-input-has-name-attribute */}
-
- {maxLength && (
-
- {beforeMaxLengthCount}
- {maxLength - count}
- {afterMaxLengthCount}
+ }, [className, count, error, maxLetters, width])
+
+ const body = (
+ // eslint-disable-next-line smarthr/a11y-input-has-name-attribute
+
+ )
+
+ return maxLetters ? (
+
+ {body}
+
+ {beforeMaxLettersCount}
+
+ {maxLetters - count}/{maxLetters}
- )}
- >
+ {afterMaxLettersCount}
+
+
+ ) : (
+ body
)
},
)