• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

alma-oss / spirit-design-system / 25500013980

07 May 2026 01:50PM UTC coverage: 84.089% (-0.3%) from 84.395%
25500013980

Pull #2631

github

adamkudrna
feat(web,web-react)!: drop `Tag` appearance feature flag #DS-2456

BREAKING CHANGE: The new `Tag` appearance (`inline-flex` layout with explicit
height and inside spacing) is now default. Delete the `$enable-v5-tag-appearance`
Sass variable and the `spirit-feature-enable-v5-tag-appearance` CSS class from
your project — they have no effect. See the Tag: Appearance Feature Flag Removed
sections in the web and web-react package Migration Guides to version 5.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pull Request #2631: feat(web,web-react)!: drop `Tag` appearance feature flag #DS-2456

2274 of 3120 branches covered (72.88%)

Branch coverage included in aggregate %.

7149 of 8086 relevant lines covered (88.41%)

197.08 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.47
/packages/web-react/src/components/TextArea/TextArea.tsx
1
'use client';
2

3
import React, { type ForwardedRef, type RefObject, forwardRef, useEffect, useRef } from 'react';
188✔
4
import { warning } from '../../common/utilities';
188✔
5
import { type ForwardRefComponent, type SpiritTextAreaProps } from '../../types';
6
import { normalizeStringValue } from '../../utils';
188✔
7
import { useCharacterCounterState } from '../CharacterCounter';
188✔
8
import { TextFieldBase } from '../TextFieldBase';
188✔
9
import { TEXTAREA_MAX_SAFE_LENGTH } from './constants';
188✔
10
import { useAdjustHeight } from './useAdjustHeight';
188✔
11

12
const isCounterActive = (hasCounter: boolean | undefined, counterThreshold: number | undefined): boolean =>
188✔
13
  hasCounter === true || counterThreshold !== undefined;
35✔
14

15
const resolveCounterNativeMaxLength = (consumerMaxLength: number | undefined): number =>
188✔
16
  consumerMaxLength === undefined ? TEXTAREA_MAX_SAFE_LENGTH : consumerMaxLength;
×
17

18
const _TextArea = (props: SpiritTextAreaProps, ref: ForwardedRef<HTMLTextAreaElement>): JSX.Element => {
188✔
19
  const {
20
    onInput,
21
    isAutoResizing,
22
    autoResizingMaxHeight = 400,
35✔
23
    counterThreshold,
24
    hasCounter,
25
    onChange,
26
    value,
27
    defaultValue,
28
    helperText,
29
    isDisabled,
30
    id,
31
    ...restProps
32
  } = props;
35✔
33

34
  const elementReference = useRef(ref);
35✔
35
  const { adjustHeightOnAutoresize, onInput: onInputHandler } = useAdjustHeight({
35✔
36
    elementReference,
37
    onInput,
38
    isAutoResizing,
39
    maxHeight: autoResizingMaxHeight,
40
  });
41

42
  const normalizedValue = normalizeStringValue(value);
35✔
43
  const normalizedDefaultValue = normalizeStringValue(defaultValue);
35✔
44

45
  const { counterProps, handleChange } = useCharacterCounterState({
35✔
46
    value: normalizedValue,
47
    defaultValue: normalizedDefaultValue,
48
    counterThreshold,
49
    hasCounter,
50
    onChange,
51
  });
52

53
  const counterOn = isCounterActive(hasCounter, counterThreshold);
35✔
54
  const nativeMaxLength = counterOn ? resolveCounterNativeMaxLength(restProps.maxLength) : undefined;
35!
55
  const changeHandler = counterOn ? handleChange : onChange;
35!
56

57
  const didWarnMaxLengthLowerThanThresholdRef = useRef(false);
35✔
58
  useEffect(() => {
35✔
59
    if (
35!
60
      counterThreshold !== undefined &&
35!
61
      restProps.maxLength !== undefined &&
62
      restProps.maxLength < counterThreshold &&
63
      !didWarnMaxLengthLowerThanThresholdRef.current
64
    ) {
65
      didWarnMaxLengthLowerThanThresholdRef.current = true;
×
66
      warning(
×
67
        false,
68
        'TextArea: `maxLength` should be greater than or equal to `counterThreshold` to keep visible counter and hard input limit aligned.',
69
      );
70
    }
71
  }, [counterThreshold, restProps.maxLength]);
72

73
  return (
74
    <TextFieldBase
75
      id={id}
76
      isMultiline
77
      ref={elementReference as RefObject<HTMLTextAreaElement>}
78
      onInput={onInputHandler}
79
      onFocus={adjustHeightOnAutoresize}
80
      onChange={changeHandler}
81
      value={value}
82
      defaultValue={defaultValue}
83
      helperText={helperText}
84
      isDisabled={isDisabled}
85
      counterProps={counterProps}
86
      {...restProps}
87
      {...(nativeMaxLength !== undefined && { maxLength: nativeMaxLength })}
35!
88
    />
89
  );
90
};
91

92
const TextArea = forwardRef<HTMLTextAreaElement, SpiritTextAreaProps>(_TextArea) as ForwardRefComponent<
188✔
93
  HTMLTextAreaElement,
94
  SpiritTextAreaProps
95
>;
96

97
TextArea.spiritComponent = 'TextArea';
188✔
98
TextArea.displayName = 'TextArea';
188✔
99

100
export default TextArea;
188✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc