<div class="text-area--dark">
<div class="text-area__wrapper">
<textarea class="text-area__input" id="text" type="text" name="text"></textarea>
<label class="text-area__label" for="text">Text</label>
</div>
<!-- NOTE: This div is reserved for field-specific error messages by a backend -->
<div class="text-area__error">Please provide a value for this field</div>
</div>
<div class="text-area--{{splitDashLast _self.name}}">
<div class="text-area__wrapper">
<textarea class="text-area__input" id="{{id}}" type="text" name="{{name}}" {{#if value}}value="{{value}}"{{/if}} {{#if disabled}}disabled{{/if}} {{#if required }}required="true"{{/if}}></textarea>
<label class="text-area__label" for="{{id}}">{{label}}</label>
</div>
{{#if helper}}
<div class="text-area__helper">{{helper}}</div>
{{/if}}
<!-- NOTE: This div is reserved for field-specific error messages by a backend -->
{{#if error}}
<div class="text-area__error">{{error}}</div>
{{else}}
<!--<div class="text-area__error">Put in the error message here...</div>-->
{{/if}}
</div>
{
"id": "text",
"name": "text",
"label": "Text",
"required": false,
"value": "",
"disabled": false,
"error": "Please provide a value for this field",
"helper": ""
}
import './text-area-material-like.scss';
export * from './text-area-material-like';
import FormComponent from '../../form-component';
export class TextArea extends FormComponent {
constructor(context, options) {
super(
context,
context.querySelector('.text-area__input'),
context.querySelector('.text-area__error'),
'Text Area',
options
);
super.init();
this.initEvents();
}
initEvents() {
this.field.addEventListener('focus', () => {
this.setIsFilledIn(true);
});
this.field.addEventListener('blur', () => this.setIsFilledIn());
this.field.addEventListener('input', () => {
// Don't just call setIsFilledIn() for the case where you've removed
// the text field value but are still focusing the text field
this.setIsFilledIn(
this.field.value || this.field === document.activeElement
);
});
}
}
export const selector = '[class^="text-area--"]';
@import "~shared/base";
/*******************************************************************************
* Contextual classes:
* - is-disabled: When input is disabled
* - is-filled-in: When value is available or the user clicked into the input
* - is-tabbed: When the input is focused by tabbing (a11y)
* - is-focused: When the input is focused
* - is-initialized: When the JS for the component is initialized
* - has-no-label: If there is no label available
******************************************************************************/
// font settings
$textAreaLabelFontSize: 1.125rem;
$textAreaLabelFontSizeFilledIn: 0.75rem;
$textAreaLabelFontFamily: inherit;
$textAreaFontSize: 1.125rem;
$textAreaLineHeight: 1.375rem;
$textAreaFontFamily: inherit;
$textAreaErrorFontSize: 1rem;
$textAreaHelperFontSize: 1rem;
// size settings
$textAreaHeight: $textAreaLineHeight * 5;
$textAreaPaddingX: 15px;
$textAreaPaddingY: 10px;
$textAreaLabelSpacing: 5px;
$textAreaBorderRadius: 2px;
// need to use string here due to:
// https://github.com/webpack-contrib/sass-loader/issues/487
$variants: "dark", "light";
@each $color in $variants {
@if $color == "light" {
// color settings
$textAreaBorderColor: $black !global;
$textAreaBorderActiveColor: $black !global;
$textAreaBorderInvalidColor: $red !global;
$textAreaBorderInvalidActiveColor: $red !global;
$textAreaBackgroundColor: $white !global;
$textAreaBackgroundActiveColor: $white !global;
$textAreaBackgroundInvalidColor: $white !global;
$textAreaBackgroundInvalidActiveColor: $white !global;
$textAreaColor: $black !global;
$textAreaActiveColor: $black !global;
$textAreaInvalidColor: $black !global;
$textAreaInvalidActiveColor: $black !global;
$textAreaLabelColor: $black !global;
$textAreaLabelFilledInColor: $textAreaLabelColor !global;
$textAreaLabelFilledInActiveColor: $textAreaLabelColor !global;
$textAreaLabelInvalidColor: $red !global;
$textAreaLabelInvalidFilledInColor: $textAreaLabelInvalidColor !global;
$textAreaLabelInvalidFilledInActiveColor: $textAreaLabelInvalidColor !global;
$textAreaErrorColor: $red !global;
$textAreaHelperColor: $black !global;
$textAreaHelperInvalidColor: $black !global;
$textAreaBorderTabbedColor: #95a5a6 !global;
} @else {
// color settings
$textAreaBorderColor: $white !global;
$textAreaBorderActiveColor: $white !global;
$textAreaBorderInvalidColor: $red !global;
$textAreaBorderInvalidActiveColor: $red !global;
$textAreaBackgroundColor: $white !global;
$textAreaBackgroundActiveColor: $white !global;
$textAreaBackgroundInvalidColor: $white !global;
$textAreaBackgroundInvalidActiveColor: $white !global;
$textAreaColor: $black !global;
$textAreaActiveColor: $black !global;
$textAreaInvalidColor: $black !global;
$textAreaInvalidActiveColor: $black !global;
$textAreaLabelColor: $black !global;
$textAreaLabelFilledInColor: $textAreaLabelColor !global;
$textAreaLabelFilledInActiveColor: $textAreaLabelColor !global;
$textAreaLabelInvalidColor: $red !global;
$textAreaLabelInvalidFilledInColor: $textAreaLabelInvalidColor !global;
$textAreaLabelInvalidFilledInActiveColor: $textAreaLabelInvalidColor !global;
$textAreaErrorColor: $red !global;
$textAreaHelperColor: $white !global;
$textAreaHelperInvalidColor: $white !global;
$textAreaBorderTabbedColor: #95a5a6 !global;
}
/*****************************************************************************
* General
****************************************************************************/
.text-area {
$block: &;
&--#{unquote($color)} {
&.is-tabbed {
outline: 1px solid $textAreaBorderTabbedColor;
outline-offset: 3px;
}
#{$block}__wrapper {
position: relative;
width: 100%;
border: 1px solid $textAreaBorderColor;
padding: 1px;
box-sizing: border-box;
border-radius: $textAreaBorderRadius;
background: $textAreaBackgroundColor;
// Fix inconsistency in Chrome
// https://stackoverflow.com/questions/24923424/textarea-padding-inconsistency-in-firefox-and-chrome
&:before {
position: absolute;
top: 0;
left: 0;
width: calc(100% - 25px - 2px); // 25px == scrollbar reserve, 2px border
background: $textAreaBackgroundColor;
content: "";
z-index: 1;
height: calc(#{$textAreaLabelFontSizeFilledIn} + #{$textAreaPaddingY} + #{$textAreaLabelSpacing});
}
}
&.is-focused #{$block}__wrapper {
border-width: 2px;
border-color: $textAreaBorderActiveColor;
padding: 0;
&:before {
height: calc(#{$textAreaLabelFontSizeFilledIn} + #{$textAreaPaddingY} + #{$textAreaLabelSpacing} - 1px);
}
}
&.is-invalid #{$block}__wrapper {
border-color: $textAreaBorderInvalidColor;
}
&.is-invalid.is-focused #{$block}__wrapper {
border-color: $textAreaBorderInvalidActiveColor;
}
/*************************************************************************
* Input
************************************************************************/
#{$block}__input {
&,
&:invalid,
&:required {
border: none;
cursor: text;
display: block;
height: calc(#{$textAreaHeight} + #{$textAreaLabelFontSizeFilledIn} + (#{$textAreaPaddingY} * 2) + #{$textAreaLabelSpacing});
line-height: $textAreaLineHeight;
box-sizing: border-box;
padding: calc(#{$textAreaLabelFontSizeFilledIn} + #{$textAreaPaddingY} + #{$textAreaLabelSpacing}) #{$textAreaPaddingX} #{$textAreaPaddingY} #{$textAreaPaddingX};
background: $textAreaBackgroundColor;
font-size: $textAreaFontSize;
font-family: $textAreaFontFamily;
resize: none;
border-radius: $textAreaBorderRadius;
width: 100%;
color: $textAreaColor;
box-shadow: none; // red border removal in case it's invalid/required
// Active
&:focus {
outline: none;
background: $textAreaBackgroundActiveColor;
color: $textAreaActiveColor;
}
}
}
// Disabled
&.is-disabled #{$block}__input {
cursor: not-allowed;
}
// Invalid
&.is-invalid #{$block}__input {
background: $textAreaBackgroundInvalidColor;
color: $textAreaInvalidColor;
// Invalid & Active
&:focus,
&:invalid:focus,
&:required:focus {
border-color: transparent transparent $textAreaBorderInvalidActiveColor transparent;
color: $textAreaInvalidActiveColor;
background: $textAreaBackgroundInvalidActiveColor;
}
}
/*************************************************************************
* Label (will be moved to top when value available)
************************************************************************/
#{$block}__label {
position: absolute;
top: calc(#{$textAreaLabelFontSizeFilledIn} + #{$textAreaPaddingY});
left: 0;
height: $textAreaHeight;
line-height: $textAreaLineHeight;
width: calc(100% - 25px); // 25px == scrollbar reserve
box-sizing: border-box;
cursor: text;
padding: 0 0 0 $textAreaPaddingX;
font-size: $textAreaLabelFontSize;
font-family: $textAreaLabelFontFamily;
color: $textAreaLabelColor;
user-select: none;
background-color: transparent;
transform: translateY(0);
z-index: 2;
@include transition("transform .275s", "height .275s", "font-size .275s", "color .275s", "line-height .275s");
}
// Disabled
&.is-disabled #{$block}__label {
cursor: not-allowed;
user-select: none;
}
// Filled in
// NOTE: We need to use two selectors here, as otherwise it won't work in
// Firefox. Mixins aren't allowed inside @each directives, so we can only
// use redundant code in these two selectors
// NOTE: Also trigger this style when the text field isn't initialized yet
// to avoid label jumping when forms with filled-in values are loaded
// via AJAX
&.is-filled-in #{$block}__label,
&:not(.is-initialized) #{$block}__label {
transform: translateY(-#{$textAreaPaddingY});
height: $textAreaLabelFontSizeFilledIn;
font-size: $textAreaLabelFontSizeFilledIn;
color: $textAreaLabelFilledInColor;
line-height: $textAreaLabelFontSizeFilledIn;
}
#{$block}__input:-webkit-autofill + #{$block}__label {
// webkit autofill is used to remove the delay between Chrome, which
// fills in predefined data, and JS that's being loaded
transform: translateY(-#{$textAreaPaddingY});
height: $textAreaLabelFontSizeFilledIn;
font-size: $textAreaLabelFontSizeFilledIn;
color: $textAreaLabelFilledInColor;
line-height: $textAreaLabelFontSizeFilledIn;
}
// Filled in & Active
&.is-filled-in.is-focused #{$block}__label,
&.is-filled-in.is-focused:not(.is-initialized) #{$block}__label {
color: $textAreaLabelFilledInActiveColor;
margin-top: -1px;
margin-left: -1px;
}
&.is-filled-in.is-focused #{$block}__input:-webkit-autofill + #{$block}__label {
color: $textAreaLabelFilledInActiveColor;
margin-top: -1px;
margin-left: -1px;
}
// Invalid
&.is-invalid #{$block}__label,
&.is-invalid:not(.is-initialized) #{$block}__label {
color: $textAreaLabelInvalidColor;
}
&.is-invalid #{$block}__input:-webkit-autofill + #{$block}__label {
color: $textAreaLabelInvalidColor;
}
// Invalid & Filled In
&.is-invalid.is-filled-in #{$block}__label,
&.is-invalid.is-filled-in:not(.is-initialized) #{$block}__label {
color: $textAreaLabelInvalidFilledInColor;
}
&.is-invalid.is-filled-in #{$block}__input:-webkit-autofill + #{$block}__label {
color: $textAreaLabelInvalidFilledInColor;
}
// Invalid & Filled in & Active
&.is-invalid.is-filled-in.is-focused #{$block}__label,
&.is-invalid.is-filled-in.is-focused:not(.is-initialized) #{$block}__label {
color: $textAreaLabelInvalidFilledInActiveColor;
}
&.is-invalid.is-filled-in.is-focused #{$block}__input:-webkit-autofill + #{$block}__label {
color: $textAreaLabelInvalidFilledInActiveColor;
}
/*************************************************************************
* Error
************************************************************************/
#{$block}__error {
font-size: $textAreaErrorFontSize;
color: $textAreaErrorColor;
margin: 5px 0;
a {
color: $textAreaErrorColor;
}
}
/*************************************************************************
* Helper
************************************************************************/
#{$block}__helper {
font-size: $textAreaHelperFontSize;
color: $textAreaHelperColor;
margin: 5px 0;
}
&.is-invalid #{$block}__helper {
color: $textAreaHelperInvalidColor;
}
}
}
}
No notes defined.