@kaizen/components 1.67.3 → 1.67.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,10 @@ import { OverrideClassName } from "../types/OverrideClassName";
3
3
  export type TextAreaProps = {
4
4
  textAreaRef?: React.RefObject<HTMLTextAreaElement>;
5
5
  status?: "default" | "error" | "caution";
6
+ /**
7
+ * Grows the input height as more content is added
8
+ * Replace with CSS field-sizing once it's supported by all major browsers
9
+ */
6
10
  autogrow?: boolean;
7
11
  reversed?: boolean;
8
12
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaizen/components",
3
- "version": "1.67.3",
3
+ "version": "1.67.4",
4
4
  "description": "Kaizen component library",
5
5
  "author": "Geoffrey Chong <geoff.chong@cultureamp.com>",
6
6
  "homepage": "https://cultureamp.design",
@@ -0,0 +1,142 @@
1
+ .wrapper {
2
+ font-family: var(--typography-paragraph-body-font-family);
3
+ font-size: var(--typography-paragraph-body-font-size);
4
+ font-weight: var(--typography-paragraph-body-font-weight);
5
+ line-height: var(--typography-paragraph-body-line-height);
6
+ letter-spacing: var(--typography-paragraph-body-letter-spacing);
7
+ color: var(--color-purple-800-rgb);
8
+ }
9
+
10
+ .wrapperAutogrow {
11
+ display: grid;
12
+ }
13
+
14
+ .wrapperAutogrow::after {
15
+ content: attr(data-value) " ";
16
+ white-space: pre-wrap;
17
+ visibility: hidden;
18
+ }
19
+
20
+ /* these properties need to be set on both for autogrow to work properly */
21
+ .textarea,
22
+ .wrapperAutogrow::after {
23
+ border: var(--border-solid-border-width) var(--border-solid-border-style)
24
+ var(--color-gray-500);
25
+ border-radius: var(--border-solid-border-radius);
26
+ padding: var(--spacing-sm);
27
+ box-sizing: border-box;
28
+ width: 100%;
29
+ font: inherit;
30
+ }
31
+
32
+ .textareaAutogrow,
33
+ .wrapperAutogrow::after {
34
+ grid-area: 2 / 1;
35
+ }
36
+
37
+ .textarea {
38
+ display: block;
39
+ border: var(--border-solid-border-width) var(--border-solid-border-style)
40
+ var(--color-gray-500);
41
+ border-radius: var(--border-solid-border-radius);
42
+ padding: var(--spacing-sm);
43
+ resize: vertical;
44
+
45
+ &:focus {
46
+ outline: var(--border-focus-ring-border-width)
47
+ var(--border-focus-ring-border-style) var(--color-blue-500);
48
+ outline-offset: 1px;
49
+ }
50
+
51
+ &:disabled {
52
+ resize: none;
53
+ }
54
+ }
55
+
56
+ .textareaAutogrow {
57
+ overflow: hidden;
58
+ }
59
+
60
+ .default {
61
+ &:not(.error, .caution) {
62
+ &:disabled {
63
+ border-color: rgba(var(--color-gray-500-rgb), 0.3);
64
+ }
65
+ }
66
+
67
+ &:focus:not([disabled]),
68
+ &:hover:not([disabled]),
69
+ &:hover:focus:not([disabled]) {
70
+ background-color: var(--color-gray-200);
71
+ border-color: var(--color-gray-600);
72
+ }
73
+
74
+ &.error {
75
+ border-color: var(--color-red-500);
76
+
77
+ &:focus:not([disabled]),
78
+ &:hover:not([disabled]),
79
+ &:hover:focus:not([disabled]) {
80
+ border-color: var(--color-red-500);
81
+ }
82
+ }
83
+
84
+ &.caution {
85
+ border-color: var(--color-yellow-600);
86
+
87
+ &:focus:not([disabled]),
88
+ &:hover:not([disabled]),
89
+ &:hover:focus:not([disabled]) {
90
+ border-color: var(--color-yellow-600);
91
+ }
92
+ }
93
+
94
+ &.disabled {
95
+ background-color: var(--color-white);
96
+ border-color: rgba(var(--color-gray-500-rgb), 0.3);
97
+ color: rgba(var(--color-purple-800-rgb), 0.3);
98
+ }
99
+ }
100
+
101
+ .reversed {
102
+ border-color: rgba(var(--color-white-rgb), 0.65);
103
+ background: transparent;
104
+ color: var(--color-white);
105
+
106
+ &:focus {
107
+ outline-color: var(--color-blue-300);
108
+ }
109
+
110
+ &:focus:not([disabled]),
111
+ &:hover:not([disabled]),
112
+ &:hover:focus:not([disabled]) {
113
+ background: rgba(var(--color-white-rgb), 0.1);
114
+ border-color: var(--color-white);
115
+ }
116
+
117
+ &.error {
118
+ border-color: var(--color-red-300);
119
+
120
+ &:focus:not([disabled]),
121
+ &:hover:not([disabled]),
122
+ &:hover:focus:not([disabled]) {
123
+ border-color: var(--color-red-300);
124
+ }
125
+ }
126
+
127
+ &.caution {
128
+ border-color: var(--color-yellow-400);
129
+
130
+ &:focus:not([disabled]),
131
+ &:hover:not([disabled]),
132
+ &:hover:focus:not([disabled]) {
133
+ border-color: var(--color-yellow-400);
134
+ }
135
+ }
136
+
137
+ &.disabled {
138
+ background: transparent;
139
+ border-color: rgba(var(--color-white-rgb), 0.3);
140
+ color: rgba(var(--color-white-rgb), 0.3);
141
+ }
142
+ }
@@ -1,16 +1,15 @@
1
- import React, {
2
- TextareaHTMLAttributes,
3
- useEffect,
4
- useRef,
5
- useState,
6
- } from "react"
1
+ import React, { TextareaHTMLAttributes, useRef, useState } from "react"
7
2
  import classnames from "classnames"
8
3
  import { OverrideClassName } from "~components/types/OverrideClassName"
9
- import styles from "./TextArea.module.scss"
4
+ import styles from "./TextArea.module.css"
10
5
 
11
6
  export type TextAreaProps = {
12
7
  textAreaRef?: React.RefObject<HTMLTextAreaElement>
13
8
  status?: "default" | "error" | "caution"
9
+ /**
10
+ * Grows the input height as more content is added
11
+ * Replace with CSS field-sizing once it's supported by all major browsers
12
+ */
14
13
  autogrow?: boolean
15
14
  reversed?: boolean
16
15
  /**
@@ -32,73 +31,46 @@ export const TextArea = ({
32
31
  onChange: propsOnChange,
33
32
  ...restProps
34
33
  }: TextAreaProps): JSX.Element => {
35
- const [textAreaHeight, setTextAreaHeight] = useState<string>("auto")
36
- const [parentHeight, setParentHeight] = useState<string>("auto")
37
34
  const [internalValue, setInternalValue] = useState<
38
35
  string | number | readonly string[] | undefined
39
- >(autogrow ? defaultValue : undefined)
36
+ >(autogrow && !value ? defaultValue : undefined)
40
37
  // ^ holds an internal state of the value so that autogrow can still work with uncontrolled textareas
41
- // essentially forces the textarea into an (interally) controlled mode if autogrow is true
42
- const textAreaRef = propsTextAreaRef || useRef(null)
43
-
44
- useEffect(() => {
45
- if (!autogrow) return
46
-
47
- const scrollHeight = textAreaRef.current!.scrollHeight
48
- if (scrollHeight < 1) return
49
-
50
- const borderWidth = textAreaRef.current
51
- ? parseInt(getComputedStyle(textAreaRef.current).borderTopWidth, 10)
52
- : 0
53
- const newHeight = scrollHeight + borderWidth * 2
54
- setParentHeight(`${newHeight}px`)
55
- setTextAreaHeight(`${newHeight}px`)
56
- }, [internalValue])
57
-
58
- const onChange = !autogrow
59
- ? undefined
60
- : (event: React.ChangeEvent<HTMLTextAreaElement>): void => {
61
- setTextAreaHeight("auto")
62
- // ^ this is required to avoid the textarea height from building up indefinitely
63
- // see https://medium.com/@lucasalgus/creating-a-custom-auto-resize-textarea-component-for-your-react-web-application-6959c0ad68bc#2dee
64
-
65
- setInternalValue(event.target.value)
66
- if (propsOnChange) {
67
- propsOnChange(event)
68
- }
69
- }
70
-
71
- const getWrapperStyle = (): { minHeight: string } | undefined =>
72
- autogrow ? { minHeight: parentHeight } : undefined
73
-
74
- const getTextAreaStyle = (): { height: string } | undefined =>
75
- autogrow ? { height: textAreaHeight } : undefined
38
+ // essentially forces the textarea into an (interally) controlled mode if autogrow is true and mode is uncontrolled
76
39
 
77
40
  const controlledValue = value || internalValue
41
+ const textAreaRef = propsTextAreaRef || useRef(null)
42
+
43
+ const onChange = (event: React.ChangeEvent<HTMLTextAreaElement>): void => {
44
+ propsOnChange && propsOnChange(event)
45
+ setInternalValue(event.target.value)
46
+ }
78
47
 
79
48
  return (
80
- <div className={styles.wrapper} style={getWrapperStyle()}>
49
+ <div
50
+ className={classnames(styles.wrapper, {
51
+ [styles.wrapperAutogrow]: autogrow,
52
+ })}
53
+ data-value={autogrow ? controlledValue : undefined}
54
+ >
81
55
  <textarea
82
56
  className={classnames(
83
57
  styles.textarea,
84
58
  styles[status],
85
59
  reversed ? styles.reversed : styles.default,
86
- disabled && styles.disabled
60
+ {
61
+ [styles.disabled]: disabled,
62
+ [styles.textareaAutogrow]: autogrow,
63
+ }
87
64
  )}
88
65
  rows={rows}
89
- onChange={onChange || propsOnChange}
66
+ onChange={onChange}
90
67
  value={controlledValue}
91
68
  defaultValue={controlledValue ? undefined : defaultValue}
92
69
  // ^ React throws a warning if you specify both a value and a defaultValue
93
70
  ref={textAreaRef}
94
- style={getTextAreaStyle()}
95
71
  disabled={disabled}
96
72
  {...restProps}
97
73
  />
98
-
99
- {/* Textareas aren't able to have pseudo elements like ::after on them,
100
- so we have to create an element ourselves for the focus ring */}
101
- <div className={styles.focusRing} />
102
74
  </div>
103
75
  )
104
76
  }
@@ -1,13 +0,0 @@
1
- 'use strict';
2
-
3
- var styles = {
4
- "wrapper": "TextArea-module_wrapper__ytS6M",
5
- "textarea": "TextArea-module_textarea__GeHn4",
6
- "focusRing": "TextArea-module_focusRing__kECqH",
7
- "default": "TextArea-module_default__Z8jvR",
8
- "error": "TextArea-module_error__XOQRm",
9
- "caution": "TextArea-module_caution__9BGd0",
10
- "disabled": "TextArea-module_disabled__N09tP",
11
- "reversed": "TextArea-module_reversed__-SoNq"
12
- };
13
- module.exports = styles;
@@ -1,11 +0,0 @@
1
- var styles = {
2
- "wrapper": "TextArea-module_wrapper__ytS6M",
3
- "textarea": "TextArea-module_textarea__GeHn4",
4
- "focusRing": "TextArea-module_focusRing__kECqH",
5
- "default": "TextArea-module_default__Z8jvR",
6
- "error": "TextArea-module_error__XOQRm",
7
- "caution": "TextArea-module_caution__9BGd0",
8
- "disabled": "TextArea-module_disabled__N09tP",
9
- "reversed": "TextArea-module_reversed__-SoNq"
10
- };
11
- export { styles as default };
@@ -1,137 +0,0 @@
1
- @import "~@kaizen/design-tokens/sass/spacing";
2
- @import "~@kaizen/design-tokens/sass/color";
3
- @import "~@kaizen/design-tokens/sass/border";
4
- @import "../../styles/utils/forms";
5
- @import "../../styles/utils/form-variables";
6
-
7
- // Vars
8
- $input-disabled-opacity: 0.3;
9
- $input-disabled-border-alpha: 50%;
10
-
11
- .wrapper {
12
- position: relative;
13
- }
14
-
15
- .textarea {
16
- @include form-input-reset;
17
-
18
- border-radius: $border-solid-border-radius;
19
- width: 100%;
20
- border: $border-solid-border-width $border-solid-border-style $color-gray-500;
21
- padding: $spacing-sm;
22
- color: $color-purple-800-rgb;
23
- display: block;
24
- resize: vertical;
25
-
26
- @include form-input-placeholder {
27
- line-height: 1.5;
28
- color: $dt-color-form-text-color-placeholder;
29
- }
30
-
31
- &:disabled {
32
- resize: none;
33
- }
34
- }
35
-
36
- .textarea:focus + .focusRing {
37
- $focus-ring-offset: 3px;
38
-
39
- position: absolute;
40
- background: transparent;
41
- border-radius: $border-focus-ring-border-radius;
42
- border-width: $border-focus-ring-border-width;
43
- border-style: $border-focus-ring-border-style;
44
- border-color: transparent;
45
- inset: -$focus-ring-offset;
46
- pointer-events: none;
47
- }
48
-
49
- .textarea.default {
50
- @include form-input-focus-state {
51
- background-color: $color-gray-200;
52
- border-color: $color-gray-600;
53
- }
54
-
55
- &:focus + .focusRing {
56
- border-color: $color-blue-500;
57
- }
58
-
59
- &:not(.error, .caution) {
60
- &:disabled {
61
- border-color: rgba($color-gray-500-rgb, $input-disabled-opacity);
62
- }
63
- }
64
-
65
- &.error {
66
- border-color: $color-red-500;
67
-
68
- @include form-input-focus-state {
69
- border-color: $color-red-500;
70
- }
71
- }
72
-
73
- &.caution {
74
- border-color: $color-yellow-600;
75
-
76
- @include form-input-focus-state {
77
- border-color: $color-yellow-600;
78
- }
79
- }
80
-
81
- &.disabled {
82
- background-color: $color-white;
83
- border-color: rgba($color-gray-500-rgb, $input-disabled-opacity);
84
- color: rgba($color-purple-800-rgb, $input-disabled-opacity);
85
-
86
- @include form-input-placeholder {
87
- opacity: $input-disabled-opacity;
88
- }
89
- }
90
- }
91
-
92
- // Reversed (Dark Backgrounds)
93
- .textarea.reversed {
94
- border-color: rgba($color-white-rgb, 0.65);
95
- background: transparent;
96
- color: $color-white;
97
-
98
- @include form-input-focus-state {
99
- background: rgba($color-white-rgb, 0.1);
100
- border-color: $color-white;
101
- }
102
-
103
- @include form-input-placeholder {
104
- line-height: 1.5;
105
- color: $color-white;
106
- }
107
-
108
- &:focus + .focusRing {
109
- border-color: $color-blue-300;
110
- }
111
-
112
- &.error {
113
- border-color: $color-red-300;
114
-
115
- @include form-input-focus-state {
116
- border-color: $color-red-300;
117
- }
118
- }
119
-
120
- &.caution {
121
- border-color: $color-yellow-400;
122
-
123
- @include form-input-focus-state {
124
- border-color: $color-yellow-400;
125
- }
126
- }
127
-
128
- &.disabled {
129
- background: transparent;
130
- border-color: rgba($color-white-rgb, $input-disabled-opacity);
131
- color: rgba($color-white-rgb, $input-disabled-opacity);
132
-
133
- @include form-input-placeholder {
134
- opacity: $input-disabled-opacity;
135
- }
136
- }
137
- }