Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(TextareaField)!: introduce 2.0 component #1911

Merged
merged 1 commit into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/components/InputField/InputField-v2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ export const InputField: InputFieldType = forwardRef(
leadingIcon,
maxLength,
onChange,
readOnly,
recommendedMaxLength,
required,
showHint,
Expand Down Expand Up @@ -289,6 +290,7 @@ export const InputField: InputFieldType = forwardRef(
setFieldText(e.target.value);
onChange && onChange(e);
}}
readOnly={readOnly}
ref={ref}
required={required}
type={type}
Expand Down
53 changes: 53 additions & 0 deletions src/components/TextareaField/TextareaField-v2.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
@import '../../design-tokens/mixins.css';

/*------------------------------------*\
# TEXTAREA FIELD
\*------------------------------------*/

/**
* Default input styles
*/
.textarea {
@mixin inputStylesV2;
}

/**
* Wraps the Label and the optional/required indicator.
*/
.textarea-field__overline {
display: flex;
margin-bottom: 0.25rem;
gap: 0.25rem;
}

.textarea-field__overline--no-label {
justify-content: flex-start;
}

.textarea-field__label {
font: var(--eds-theme-typography-form-label);
}

.textarea-field__label--disabled {
color: var(--eds-theme-color-text-utility-disabled-primary);
}

.textarea-field--invalid-length {
color: var(--eds-theme-color-text-utility-critical);
}

.textarea-field__footer {
display: flex;
justify-content: space-between;
}

.textarea-field__field-note {
flex: 1 0 50%;
}

.textarea-field__character-counter {
font: var(--eds-theme-typography-body-sm);

flex: 1 0 50%;
text-align: right;
}
161 changes: 161 additions & 0 deletions src/components/TextareaField/TextareaField-v2.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import type { StoryObj, Meta } from '@storybook/react';
import React from 'react';

import { TextareaField } from './TextareaField-v2';

const meta: Meta<typeof TextareaField> = {
title: 'Components/V2/TextareaField',
component: TextareaField,
args: {
placeholder: 'Enter long-form text here',
defaultValue: `Lorem ipsum, dolor sit amet consectetur adipisicing elit. Id neque nemo
dicta rerum commodi et fugiat quo optio veniam! Ea odio corporis nemo
praesentium, commodi eligendi asperiores quis dolorum porro.`,
label: 'Textarea Field',
rows: 5,
fieldNote: 'Longer Field description',
spellCheck: false,
},
parameters: {
badges: ['intro-1.3', 'current-2.0'],
},
decorators: [(Story) => <div className="p-8">{Story()}</div>],
};

export default meta;
type Story = StoryObj<typeof TextareaField>;

export const Default: Story = {
render: (args) => (
<TextareaField aria-label="Text Label" {...args}></TextareaField>
),
};

/**
* You can specify the content of `TextareaField` by using children. Convenient for cases where
* specifying `value` or `defaultValue` is inconvenient.
*/
export const WhenUsingChildren: Story = {
args: {
children: `Lorem ipsum, dolor sit amet consectetur adipisicing elit. Id neque nemo
dicta rerum commodi et fugiat quo optio veniam! Ea odio corporis nemo
praesentium, commodi eligendi asperiores quis dolorum porro.`,
defaultValue: '',
},
};

/**
* `TextareaField` does not require any initial content.
*/
export const WhenNoDefaultValue: Story = {
args: {
defaultValue: undefined,
fieldNote: undefined,
},
};

export const WhenDisabled: Story = {
args: {
disabled: true,
rows: 2,
},
parameters: {
axe: {
// Disabled input does not need to meet color contrast
disabledRules: ['color-contrast'],
},
},
};

export const WhenReadOnly: Story = {
args: {
readOnly: true,
rows: 2,
},
parameters: {
axe: {
// Disabled input does not need to meet color contrast
disabledRules: ['color-contrast'],
},
},
};

export const WhenError: Story = {
args: {
isError: true,
fieldNote: 'Text should be at least 100 characters',
},
};

export const WhenWarning: Story = {
args: {
isWarning: true,
fieldNote: 'Text should be at least 100 characters',
},
};

export const WhenRequired: Story = {
args: {
required: true,
showHint: true,
},
};

export const WhenOptional: Story = {
args: {
required: false,
showHint: true,
},
};

/**
* You can size `TextareaField` by specifying `row` attribute, inherited from
* [textarea](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea).
*/
export const WithADifferentSize: Story = {
args: {
rows: 10,
},
};

/**
* You can lock the maximum length of the text content of `TextareaField`. When setting `maxLength`,
* the field will reuse the browser's [textarea](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea)
* behavior (e.g., prevent further text from being typed, prevent keydown events, etc.).
*/
export const WithAMaxLength: Story = {
args: {
rows: 10,
maxLength: 144,
required: true,
},
render: (args) => <TextareaField {...args} />,
};

/**
* 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
* `recommendedMaxLength`. This will show a similar UI to using `maxLength` but will allow more text to be typed, and
* emit any appropriate events.
*/
export const WithARecommendedLength: Story = {
args: {
rows: 10,
recommendedMaxLength: 144,
required: true,
},
render: (args) => <TextareaField {...args} />,
};

/**
* Both `maxLength` and `recommendedMaxLength` can be specified at the same time. Text length between `recommendedMaxLength`
* and `maxLength` will show the treatment warning the user about the text length being violated.
*/
export const WithBothRecommendedAndMaxLengths: Story = {
args: {
rows: 10,
maxLength: 256,
recommendedMaxLength: 144,
required: true,
},
render: (args) => <TextareaField {...args} />,
};
Loading
Loading