Skip to content

Commit a68a255

Browse files
authored
feat(TextareaField)!: introduce 2.0 component (#1911)
- add stories - add component updates - include checks and integrtion between InputField
1 parent f6ebbdf commit a68a255

File tree

6 files changed

+520
-0
lines changed

6 files changed

+520
-0
lines changed

src/components/InputField/InputField-v2.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ export const InputField: InputFieldType = forwardRef(
174174
leadingIcon,
175175
maxLength,
176176
onChange,
177+
readOnly,
177178
recommendedMaxLength,
178179
required,
179180
showHint,
@@ -289,6 +290,7 @@ export const InputField: InputFieldType = forwardRef(
289290
setFieldText(e.target.value);
290291
onChange && onChange(e);
291292
}}
293+
readOnly={readOnly}
292294
ref={ref}
293295
required={required}
294296
type={type}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
@import '../../design-tokens/mixins.css';
2+
3+
/*------------------------------------*\
4+
# TEXTAREA FIELD
5+
\*------------------------------------*/
6+
7+
/**
8+
* Default input styles
9+
*/
10+
.textarea {
11+
@mixin inputStylesV2;
12+
}
13+
14+
/**
15+
* Wraps the Label and the optional/required indicator.
16+
*/
17+
.textarea-field__overline {
18+
display: flex;
19+
margin-bottom: 0.25rem;
20+
gap: 0.25rem;
21+
}
22+
23+
.textarea-field__overline--no-label {
24+
justify-content: flex-start;
25+
}
26+
27+
.textarea-field__label {
28+
font: var(--eds-theme-typography-form-label);
29+
}
30+
31+
.textarea-field__label--disabled {
32+
color: var(--eds-theme-color-text-utility-disabled-primary);
33+
}
34+
35+
.textarea-field--invalid-length {
36+
color: var(--eds-theme-color-text-utility-critical);
37+
}
38+
39+
.textarea-field__footer {
40+
display: flex;
41+
justify-content: space-between;
42+
}
43+
44+
.textarea-field__field-note {
45+
flex: 1 0 50%;
46+
}
47+
48+
.textarea-field__character-counter {
49+
font: var(--eds-theme-typography-body-sm);
50+
51+
flex: 1 0 50%;
52+
text-align: right;
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
import type { StoryObj, Meta } from '@storybook/react';
2+
import React from 'react';
3+
4+
import { TextareaField } from './TextareaField-v2';
5+
6+
const meta: Meta<typeof TextareaField> = {
7+
title: 'Components/V2/TextareaField',
8+
component: TextareaField,
9+
args: {
10+
placeholder: 'Enter long-form text here',
11+
defaultValue: `Lorem ipsum, dolor sit amet consectetur adipisicing elit. Id neque nemo
12+
dicta rerum commodi et fugiat quo optio veniam! Ea odio corporis nemo
13+
praesentium, commodi eligendi asperiores quis dolorum porro.`,
14+
label: 'Textarea Field',
15+
rows: 5,
16+
fieldNote: 'Longer Field description',
17+
spellCheck: false,
18+
},
19+
parameters: {
20+
badges: ['intro-1.3', 'current-2.0'],
21+
},
22+
decorators: [(Story) => <div className="p-8">{Story()}</div>],
23+
};
24+
25+
export default meta;
26+
type Story = StoryObj<typeof TextareaField>;
27+
28+
export const Default: Story = {
29+
render: (args) => (
30+
<TextareaField aria-label="Text Label" {...args}></TextareaField>
31+
),
32+
};
33+
34+
/**
35+
* You can specify the content of `TextareaField` by using children. Convenient for cases where
36+
* specifying `value` or `defaultValue` is inconvenient.
37+
*/
38+
export const WhenUsingChildren: Story = {
39+
args: {
40+
children: `Lorem ipsum, dolor sit amet consectetur adipisicing elit. Id neque nemo
41+
dicta rerum commodi et fugiat quo optio veniam! Ea odio corporis nemo
42+
praesentium, commodi eligendi asperiores quis dolorum porro.`,
43+
defaultValue: '',
44+
},
45+
};
46+
47+
/**
48+
* `TextareaField` does not require any initial content.
49+
*/
50+
export const WhenNoDefaultValue: Story = {
51+
args: {
52+
defaultValue: undefined,
53+
fieldNote: undefined,
54+
},
55+
};
56+
57+
export const WhenDisabled: Story = {
58+
args: {
59+
disabled: true,
60+
rows: 2,
61+
},
62+
parameters: {
63+
axe: {
64+
// Disabled input does not need to meet color contrast
65+
disabledRules: ['color-contrast'],
66+
},
67+
},
68+
};
69+
70+
export const WhenReadOnly: Story = {
71+
args: {
72+
readOnly: true,
73+
rows: 2,
74+
},
75+
parameters: {
76+
axe: {
77+
// Disabled input does not need to meet color contrast
78+
disabledRules: ['color-contrast'],
79+
},
80+
},
81+
};
82+
83+
export const WhenError: Story = {
84+
args: {
85+
isError: true,
86+
fieldNote: 'Text should be at least 100 characters',
87+
},
88+
};
89+
90+
export const WhenWarning: Story = {
91+
args: {
92+
isWarning: true,
93+
fieldNote: 'Text should be at least 100 characters',
94+
},
95+
};
96+
97+
export const WhenRequired: Story = {
98+
args: {
99+
required: true,
100+
showHint: true,
101+
},
102+
};
103+
104+
export const WhenOptional: Story = {
105+
args: {
106+
required: false,
107+
showHint: true,
108+
},
109+
};
110+
111+
/**
112+
* You can size `TextareaField` by specifying `row` attribute, inherited from
113+
* [textarea](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea).
114+
*/
115+
export const WithADifferentSize: Story = {
116+
args: {
117+
rows: 10,
118+
},
119+
};
120+
121+
/**
122+
* You can lock the maximum length of the text content of `TextareaField`. When setting `maxLength`,
123+
* the field will reuse the browser's [textarea](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea)
124+
* behavior (e.g., prevent further text from being typed, prevent keydown events, etc.).
125+
*/
126+
export const WithAMaxLength: Story = {
127+
args: {
128+
rows: 10,
129+
maxLength: 144,
130+
required: true,
131+
},
132+
render: (args) => <TextareaField {...args} />,
133+
};
134+
135+
/**
136+
* If you want to signal that a field has reached a maximum length but want to allow more text to be typed, you can use
137+
* `recommendedMaxLength`. This will show a similar UI to using `maxLength` but will allow more text to be typed, and
138+
* emit any appropriate events.
139+
*/
140+
export const WithARecommendedLength: Story = {
141+
args: {
142+
rows: 10,
143+
recommendedMaxLength: 144,
144+
required: true,
145+
},
146+
render: (args) => <TextareaField {...args} />,
147+
};
148+
149+
/**
150+
* Both `maxLength` and `recommendedMaxLength` can be specified at the same time. Text length between `recommendedMaxLength`
151+
* and `maxLength` will show the treatment warning the user about the text length being violated.
152+
*/
153+
export const WithBothRecommendedAndMaxLengths: Story = {
154+
args: {
155+
rows: 10,
156+
maxLength: 256,
157+
recommendedMaxLength: 144,
158+
required: true,
159+
},
160+
render: (args) => <TextareaField {...args} />,
161+
};

0 commit comments

Comments
 (0)