From dc7d9494f7801634eed6e371e5da879b4f132c59 Mon Sep 17 00:00:00 2001 From: Elizabeth Mitchell Date: Thu, 28 Jul 2022 07:45:24 -0700 Subject: [PATCH] feat(field): add leading/trailing content styles PiperOrigin-RevId: 463835470 --- field/lib/_content.scss | 77 ++++++++++++---------------- field/lib/_field-theme.scss | 6 +-- field/lib/_field.scss | 22 ++++++++ field/lib/_filled-field-theme.scss | 12 +++-- field/lib/_outlined-field-theme.scss | 8 +-- field/lib/field.ts | 11 ++++ 6 files changed, 80 insertions(+), 56 deletions(-) diff --git a/field/lib/_content.scss b/field/lib/_content.scss index c0bb22c9a6..8f10cec45b 100644 --- a/field/lib/_content.scss +++ b/field/lib/_content.scss @@ -9,64 +9,53 @@ @use 'sass:math'; @use '@material/web/motion/animation'; +// Duration of the label animation. +$_label-duration: 150ms; +// Duration of the content's visibility animation. +$_visible-duration: math.round(math.div($_label-duration * 5, 9)); +// Short delay when entering (focusing/populating) so that the label may move +// out of the way before the content starts to appear. +$_enter-delay: $_label-duration - $_visible-duration; + @mixin static-styles() { .md3-field__start, .md3-field__middle, .md3-field__end { - @include section; + display: flex; + align-items: center; + box-sizing: border-box; + height: 100%; + // Relative position for absolutely positioned labels (to avoid interfering + // with baseline alignment). + position: relative; + } + + .md3-field__start, + .md3-field__end { + justify-content: center; } .md3-field__middle { - @include middle; + // The container of the field aligns sections by "center". Only the middle + // section opts in to baseline alignment. + // + // Labels are absolutely positioned, which leaves only the content as the + // evaluated baseline for the field. + // + // See https://www.w3.org/TR/css-flexbox-1/#baseline-participation + align-self: baseline; } .md3-field__content { - @include content; + display: flex; + opacity: 0; + transition: animation.standard(opacity, $_visible-duration); .md3-field--no-label &, .md3-field:focus-within &, .md3-field--populated & { - @include content-visible; + opacity: 1; + transition-delay: $_enter-delay; } } } - -@mixin section() { - display: flex; - align-items: center; - box-sizing: border-box; - height: 100%; - // Relative position for absolutely positioned labels (to avoid interfering - // with baseline alignment). - position: relative; -} - -@mixin middle() { - // The container of the field aligns sections by "center". Only the middle - // section opts in to baseline alignment. - // - // Labels are absolutely positioned, which leaves only the content as the - // evaluated baseline for the field. - // - // See https://www.w3.org/TR/css-flexbox-1/#baseline-participation - align-self: baseline; -} - -// Duration of the label animation. -$_label-duration: 150ms; -// Duration of the content's visibility animation. -$_visible-duration: math.round(math.div($_label-duration * 5, 9)); -// Short delay when entering (focusing/populating) so that the label may move -// out of the way before the content starts to appear. -$_enter-delay: $_label-duration - $_visible-duration; - -@mixin content() { - display: flex; - opacity: 0; - transition: animation.standard(opacity, $_visible-duration); -} - -@mixin content-visible() { - opacity: 1; - transition-delay: $_enter-delay; -} diff --git a/field/lib/_field-theme.scss b/field/lib/_field-theme.scss index 5f2bbfdd18..7aa2ce6927 100644 --- a/field/lib/_field-theme.scss +++ b/field/lib/_field-theme.scss @@ -9,11 +9,7 @@ @use 'sass:map'; @mixin theme-styles($theme) { - @include _container-height(map.get($theme, container-height)); -} - -@mixin _container-height($height) { .md3-field__container { - flex-basis: $height; + flex-basis: map.get($theme, container-height); } } diff --git a/field/lib/_field.scss b/field/lib/_field.scss index 27f0597788..57f28b0214 100644 --- a/field/lib/_field.scss +++ b/field/lib/_field.scss @@ -26,4 +26,26 @@ flex: 1; position: relative; } + + .md3-field--disabled { + pointer-events: none; + } + + // TODO(b/239188049): remove when layout tokens are ready + .md3-field--with-start .md3-field__start, + .md3-field--with-end .md3-field__end { + min-width: 48px; + } + + .md3-field--with-start { + .md3-field__start { + margin-inline-end: 4px; + } + } + + .md3-field--with-end { + .md3-field__end { + margin-inline-start: 4px; + } + } } diff --git a/field/lib/_filled-field-theme.scss b/field/lib/_filled-field-theme.scss index f38d98347c..08d7677e03 100644 --- a/field/lib/_filled-field-theme.scss +++ b/field/lib/_filled-field-theme.scss @@ -314,12 +314,16 @@ $dark-theme: values( } @mixin _container-padding-horizontal($padding) { - .md3-field__start { - padding-inline-start: $padding; + &:not(.md3-field--with-start) { + .md3-field__start { + padding-inline-start: $padding; + } } - .md3-field__end { - padding-inline-end: $padding; + &:not(.md3-field--with-end) { + .md3-field__end { + padding-inline-end: $padding; + } } } diff --git a/field/lib/_outlined-field-theme.scss b/field/lib/_outlined-field-theme.scss index 22691d5087..7466b6caee 100644 --- a/field/lib/_outlined-field-theme.scss +++ b/field/lib/_outlined-field-theme.scss @@ -194,12 +194,14 @@ $dark-theme: values( $label-padding: map.get($theme, outline-label-padding); .md3-field__outline-start, - .md3-field__start { + &:not(.md3-field--with-start) .md3-field__start { padding-inline-start: max($padding, $shape-start + $label-padding); } - .md3-field__end { - padding-inline-end: max($padding, $shape-end); + &:not(.md3-field--with-end) { + .md3-field__end { + padding-inline-end: max($padding, $shape-end); + } } } diff --git a/field/lib/field.ts b/field/lib/field.ts index 96c83a32f0..e3e4954fdb 100644 --- a/field/lib/field.ts +++ b/field/lib/field.ts @@ -19,6 +19,15 @@ export class Field extends LitElement { @property({type: Boolean}) populated = false; @property({type: Boolean}) required = false; + /** + * Whether or not the field has leading content. + */ + @property({type: Boolean}) hasStart = false; + /** + * Whether or not the field has trailing content. + */ + @property({type: Boolean}) hasEnd = false; + @state() protected focused = false; @state() protected isAnimating = false; @@ -59,6 +68,8 @@ export class Field extends LitElement { return { 'md3-field--disabled': this.disabled, 'md3-field--error': this.error, + 'md3-field--with-start': this.hasStart, + 'md3-field--with-end': this.hasEnd, 'md3-field--populated': this.populated, 'md3-field--required': this.required, 'md3-field--no-label': !this.label,