Skip to content

Commit

Permalink
feat: TextareaをspanでラップすることでStackコンポーネントなどでラップした場合、意図しない余白が設定されないように変更
Browse files Browse the repository at this point in the history
  • Loading branch information
AtsushiM committed Apr 26, 2024
1 parent 4bec5a4 commit ee5a6b9
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 33 deletions.
4 changes: 2 additions & 2 deletions src/components/Textarea/Textarea.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ const Template: StoryFn = () => {
value={value}
onChange={onChangeValue}
decorators={{
beforeMaxLengthCount: (txt) => `entry maxLetters(${txt})`,
afterMaxLengthCount: (txt) => ` characters(${txt})`,
beforeMaxLettersCount: (txt) => `entry limit(${txt})`,
afterMaxLettersCount: (txt) => ` characters(${txt})`,
}}
/>
</FormControl>
Expand Down
73 changes: 42 additions & 31 deletions src/components/Textarea/Textarea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type Props = {
/** 入力可能な最大文字数。あと何文字入力できるかの表示が追加される。html的なvalidateは発生しない */
maxLetters?: number
/** コンポーネント内の文言を変更するための関数を設定 */
decorators?: DecoratorsType<'beforeMaxLengthCount' | 'afterMaxLengthCount'>
decorators?: DecoratorsType<'beforeMaxLettersCount' | 'afterMaxLettersCount'>
/**
* @deprecated placeholder属性は非推奨です。別途ヒント用要素の設置を検討してください。
*/
Expand All @@ -52,8 +52,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: {
Expand Down Expand Up @@ -107,15 +107,16 @@ export const Textarea = forwardRef<HTMLTextAreaElement, Props & ElementProps>(
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],
)

Expand All @@ -130,9 +131,15 @@ export const Textarea = forwardRef<HTMLTextAreaElement, Props & ElementProps>(
}
}, [autoFocus])

const handleKeyup = useCallback((event: React.KeyboardEvent<HTMLTextAreaElement>) => {
setCount(getStringLength(event.currentTarget.value))
}, [])
const onKeyUp = useMemo(
() =>
maxLetters
? (event: React.KeyboardEvent<HTMLTextAreaElement>) => {
setCount(getStringLength(event.currentTarget.value))
}
: undefined,
[maxLetters],
)
const handleInput = useCallback(
(e: React.ChangeEvent<HTMLTextAreaElement>) => {
if (!autoResize) {
Expand Down Expand Up @@ -171,26 +178,30 @@ export const Textarea = forwardRef<HTMLTextAreaElement, Props & ElementProps>(
}
}, [className, count, error, maxLetters, width])

return (
<>
{/* eslint-disable-next-line smarthr/a11y-input-has-name-attribute */}
<textarea
{...props}
{...textareaStyleProps}
{...(maxLetters ? { onKeyUp: handleKeyup } : {})}
ref={textareaRef}
aria-invalid={error || undefined}
rows={interimRows}
onInput={handleInput}
/>
{maxLetters && (
<span className={counterStyle}>
{beforeMaxLengthCount}
<span className={counterTextStyle}>{maxLetters - count}</span>
{afterMaxLengthCount}
</span>
)}
</>
const body = (
// eslint-disable-next-line smarthr/a11y-input-has-name-attribute
<textarea
{...props}
{...textareaStyleProps}
onKeyUp={onKeyUp}
ref={textareaRef}
aria-invalid={error || undefined}
rows={interimRows}
onInput={handleInput}
/>
)

return maxLetters ? (
<span>
{body}
<span className={counterStyle}>
{beforeMaxLettersCount}
<span className={counterTextStyle}>{maxLetters - count}</span>
{afterMaxLettersCount}
</span>
</span>
) : (
body
)
},
)

0 comments on commit ee5a6b9

Please sign in to comment.