diff --git a/ui_framework/components/_mixins.scss b/ui_framework/components/_mixins.scss index f57cae5343fc0..5e555a7aadc0c 100644 --- a/ui_framework/components/_mixins.scss +++ b/ui_framework/components/_mixins.scss @@ -109,7 +109,7 @@ */ @mixin formControlBase { appearance: none; - padding: 3px 12px 4px; + padding: $globalFormControlPadding; font-size: $globalFontSize; font-weight: 400; line-height: $globalLineHeight; diff --git a/ui_framework/components/_variables.scss b/ui_framework/components/_variables.scss index 42a0d61af814a..bb6b42166b08b 100644 --- a/ui_framework/components/_variables.scss +++ b/ui_framework/components/_variables.scss @@ -63,3 +63,7 @@ $toolBarHeight: 50px; $toolBarPadding: 10px; $toolBarSectionSpacing: 50px; $toolBarItsemSpacing: 10px; + +// Form +$globalFormControlHorizontalPadding: 12px; +$globalFormControlPadding: 3px $globalFormControlHorizontalPadding 4px; diff --git a/ui_framework/components/form/_assisted_input.scss b/ui_framework/components/form/_assisted_input.scss new file mode 100644 index 0000000000000..59f14b296f025 --- /dev/null +++ b/ui_framework/components/form/_assisted_input.scss @@ -0,0 +1,17 @@ +/** + * 1. Set inline-block so this wrapper shrinks to fit the input. + */ +.kuiAssistedInput { + display: inline-block; /* 1 */ + position: relative; +} + + /** + * 1. Vertically center the assistance, regardless of its height. + */ + .kuiAssistedInput__assistance { + position: absolute; + right: $globalFormControlHorizontalPadding; + top: 50%; /* 1 */ + transform: translateY(-50%); /* 1 */ + } diff --git a/ui_framework/components/form/_index.scss b/ui_framework/components/form/_index.scss index e51503eb1de64..c96e130058238 100644 --- a/ui_framework/components/form/_index.scss +++ b/ui_framework/components/form/_index.scss @@ -1,3 +1,4 @@ +@import "assisted_input"; @import "check_box"; @import "search_input"; @import "select"; diff --git a/ui_framework/components/local_nav/_local_nav.scss b/ui_framework/components/local_nav/_local_nav.scss index 13ca572760929..5c5035987d379 100644 --- a/ui_framework/components/local_nav/_local_nav.scss +++ b/ui_framework/components/local_nav/_local_nav.scss @@ -10,6 +10,7 @@ min-height: 70px; /* 1 */ color: $localNavTextColor; background-color: $localNavBackgroundColor; + line-height: $globalLineHeight; @include darkTheme { color: $localNavTextColor--darkTheme; diff --git a/ui_framework/components/local_nav/_local_search.scss b/ui_framework/components/local_nav/_local_search.scss index 3d9b1b35b20de..483978dba0e39 100644 --- a/ui_framework/components/local_nav/_local_search.scss +++ b/ui_framework/components/local_nav/_local_search.scss @@ -4,38 +4,16 @@ } .kuiLocalSearchInput { + @include formControl; flex: 1 1 100%; - padding: 3px 15px; - font-size: $globalFontSize; - color: $localNavTextColor; - background-color: $localSearchBackgroundColor; - border: 1px solid $localSearchBackgroundColor; - border-bottom-left-radius: 4px; - border-top-left-radius: 4px; - border-bottom-right-radius: 0; - border-top-right-radius: 0; + border-color: $localSearchBackgroundColor; + border-top-color: $localSearchBackgroundColor; + border-bottom-color: $localSearchBackgroundColor; + border-radius: $globalBorderRadius 0 0 $globalBorderRadius; &.kuiLocalSearchInput-isInvalid { border-color: $localSearchBorderColor-isInvalid; } - - &:focus { - @include formControlFocus; - } - - @include darkTheme { - color: $localNavTextColor--darkTheme; - background-color: $localSearchBackgroundColor--darkTheme; - border-color: $localSearchBackgroundColor--darkTheme; - - &.kuiLocalSearchInput-isInvalid { - border-color: $localSearchBorderColor-isInvalid--darkTheme; - } - - &:focus { - @include formControlFocus; - } - } } .kuiLocalSearchInput--secondary { @@ -45,13 +23,35 @@ border-left-color: $globalFormControlBorderColor; @include darkTheme { - border-color: $localNavBackgroundColor--darkTheme; - border-top-color: $localSearchBackgroundColor--darkTheme; - border-bottom-color: $localSearchBackgroundColor--darkTheme; - border-right-color: $localSearchBackgroundColor--darkTheme; + border-left-color: $localNavBackgroundColor--darkTheme; + border-right-color: $localNavBackgroundColor--darkTheme; } } +.kuiLocalSearchAssistedInput { + display: flex; + flex: 1 1 100%; + position: relative; +} + + /** + * 1. Vertically center the assistance, regardless of its height. + */ + .kuiLocalSearchAssistedInput__assistance { + position: absolute; + right: $globalFormControlHorizontalPadding; + top: 50%; /* 1 */ + transform: translateY(-50%); /* 1 */ + } + +.kuiLocalSearchSelect { + @include select; + + border-color: $localSearchBackgroundColor; + border-left-color: $globalFormControlBorderColor; + border-radius: 0; +} + .kuiLocalSearchButton { width: 43px; height: $localSearchHeight; @@ -59,10 +59,7 @@ color: $localSearchButtonTextColor; background-color: $localSearchButtonBackgroundColor; border: 0; - border-bottom-left-radius: 0; - border-top-left-radius: 0; - border-bottom-right-radius: 4px; - border-top-right-radius: 4px; + border-radius: 0 $globalBorderRadius $globalBorderRadius 0; &:focus { @include focus($globalFocusColor, $globalBorderColor); diff --git a/ui_framework/dist/ui_framework.css b/ui_framework/dist/ui_framework.css index 39d7f8d50ee76..831fed1b08cfb 100644 --- a/ui_framework/dist/ui_framework.css +++ b/ui_framework/dist/ui_framework.css @@ -629,6 +629,26 @@ body { line-height: 1.5; color: #9fa3a7; } +/** + * 1. Set inline-block so this wrapper shrinks to fit the input. + */ +.kuiAssistedInput { + display: inline-block; + /* 1 */ + position: relative; } + +/** + * 1. Vertically center the assistance, regardless of its height. + */ +.kuiAssistedInput__assistance { + position: absolute; + right: 12px; + top: 50%; + /* 1 */ + -webkit-transform: translateY(-50%); + transform: translateY(-50%); + /* 1 */ } + /** * 1. Deliberately disable only webkit appearance. If we disable it in Firefox, we get a really * ugly default appearance which we can't customize, so our best option is to give Firefox @@ -1436,7 +1456,8 @@ body { min-height: 70px; /* 1 */ color: #2d2d2d; - background-color: #e4e4e4; } + background-color: #e4e4e4; + line-height: 1.5; } .theme-dark .kuiLocalNav { color: #cecece; background-color: #333333; } @@ -1485,33 +1506,51 @@ body { width: 100%; } .kuiLocalSearchInput { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + padding: 3px 12px 4px; + font-size: 14px; + font-weight: 400; + line-height: 1.5; + color: #191E23; + background-color: #ffffff; + border: 1px solid #DEDEDE; + border-radius: 4px; + -webkit-transition: border-color 0.1s linear; + transition: border-color 0.1s linear; + /** + * 1. Angular will add an ng-untouched class to an input if it hasn't been touched yet. + * We only want invalid inputs to appear invalid after the user has had a chance to interact + * with it. + */ -webkit-box-flex: 1; -webkit-flex: 1 1 100%; -ms-flex: 1 1 100%; flex: 1 1 100%; - padding: 3px 15px; - font-size: 14px; - color: #2d2d2d; - background-color: #ffffff; - border: 1px solid #ffffff; - border-bottom-left-radius: 4px; - border-top-left-radius: 4px; - border-bottom-right-radius: 0; - border-top-right-radius: 0; } - .kuiLocalSearchInput.kuiLocalSearchInput-isInvalid { - border-color: #e74C3c; } + border-color: #ffffff; + border-top-color: #ffffff; + border-bottom-color: #ffffff; + border-radius: 4px 0 0 4px; } + .theme-dark .kuiLocalSearchInput { + color: #cecece; } + .kuiLocalSearchInput:invalid:not(.ng-untouched) { + /* 1 */ + border-color: #D86051; } .kuiLocalSearchInput:focus { outline: none; border-color: #6EADC1; } + .kuiLocalSearchInput:disabled { + opacity: 0.4; + cursor: not-allowed; } .theme-dark .kuiLocalSearchInput { - color: #cecece; - background-color: #4e4e4e; - border-color: #4e4e4e; } - .theme-dark .kuiLocalSearchInput.kuiLocalSearchInput-isInvalid { - border-color: #ff6758; } + background-color: #444444; + border-color: #444444; } .theme-dark .kuiLocalSearchInput:focus { outline: none; border-color: #6EADC1; } + .kuiLocalSearchInput.kuiLocalSearchInput-isInvalid { + border-color: #e74C3c; } .kuiLocalSearchInput--secondary { height: 30px; @@ -1522,10 +1561,82 @@ body { border-radius: 0; border-left-color: #DEDEDE; } .theme-dark .kuiLocalSearchInput--secondary { - border-color: #333333; - border-top-color: #4e4e4e; - border-bottom-color: #4e4e4e; - border-right-color: #4e4e4e; } + border-left-color: #333333; + border-right-color: #333333; } + +.kuiLocalSearchAssistedInput { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-flex: 1; + -webkit-flex: 1 1 100%; + -ms-flex: 1 1 100%; + flex: 1 1 100%; + position: relative; } + +/** + * 1. Vertically center the assistance, regardless of its height. + */ +.kuiLocalSearchAssistedInput__assistance { + position: absolute; + right: 12px; + top: 50%; + /* 1 */ + -webkit-transform: translateY(-50%); + transform: translateY(-50%); + /* 1 */ } + +.kuiLocalSearchSelect { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + padding: 3px 12px 4px; + font-size: 14px; + font-weight: 400; + line-height: 1.5; + color: #191E23; + background-color: #ffffff; + border: 1px solid #DEDEDE; + border-radius: 4px; + -webkit-transition: border-color 0.1s linear; + transition: border-color 0.1s linear; + /** + * 1. Angular will add an ng-untouched class to an input if it hasn't been touched yet. + * We only want invalid inputs to appear invalid after the user has had a chance to interact + * with it. + */ + padding-right: 30px; + /* 2 */ + background-image: url('data:image/svg+xml;utf8,'); + /* 1 */ + background-size: 14px; + background-repeat: no-repeat; + background-position: calc(100% - 8px); + /* 2 */ + border-color: #ffffff; + border-left-color: #DEDEDE; + border-radius: 0; } + .theme-dark .kuiLocalSearchSelect { + color: #cecece; } + .kuiLocalSearchSelect:invalid:not(.ng-untouched) { + /* 1 */ + border-color: #D86051; } + .kuiLocalSearchSelect:focus { + outline: none; + border-color: #6EADC1; } + .kuiLocalSearchSelect:disabled { + opacity: 0.4; + cursor: not-allowed; } + .theme-dark .kuiLocalSearchSelect { + background-color: #444444; + border-color: #444444; } + .theme-dark .kuiLocalSearchSelect:focus { + outline: none; + border-color: #6EADC1; } + .theme-dark .kuiLocalSearchSelect { + background-image: url('data:image/svg+xml;utf8,'); + /* 1 */ } .kuiLocalSearchButton { width: 43px; @@ -1534,10 +1645,7 @@ body { color: #ffffff; background-color: #9c9c9c; border: 0; - border-bottom-left-radius: 0; - border-top-left-radius: 0; - border-bottom-right-radius: 4px; - border-top-right-radius: 4px; } + border-radius: 0 4px 4px 0; } .kuiLocalSearchButton:focus { z-index: 1; /* 1 */ diff --git a/ui_framework/doc_site/src/views/form/assisted_input.html b/ui_framework/doc_site/src/views/form/assisted_input.html new file mode 100644 index 0000000000000..d950f0e501190 --- /dev/null +++ b/ui_framework/doc_site/src/views/form/assisted_input.html @@ -0,0 +1,14 @@ +
+ + +
+

+ API docs +

+
+
diff --git a/ui_framework/doc_site/src/views/form/form_example.js b/ui_framework/doc_site/src/views/form/form_example.js index a67cef7405fc1..524b79f41b3bb 100644 --- a/ui_framework/doc_site/src/views/form/form_example.js +++ b/ui_framework/doc_site/src/views/form/form_example.js @@ -1,6 +1,7 @@ import React from 'react'; import { + GuideCode, GuideDemo, GuidePage, GuideSection, @@ -9,6 +10,7 @@ import { } from '../../components'; const textInputHtml = require('./text_input.html'); +const assistedInputHtml = require('./assisted_input.html'); const searchInputHtml = require('./search_input.html'); const staticInputHtml = require('./static_input.html'); const textAreaHtml = require('./text_area.html'); @@ -35,6 +37,30 @@ export default props => ( /> + + + Note: You have to specify right-side padding using a custom class or + inline style to keep the input text from overlapping with the assistance content. + Use em units for this padding so that it scales appropriately if the + user changes their root font-size. + + + + + + +
- +
+ +
+

+ API docs +

+
+