diff --git a/atst/ui_modules.py b/atst/ui_modules.py index 0ced7fad..748ca980 100644 --- a/atst/ui_modules.py +++ b/atst/ui_modules.py @@ -1,4 +1,6 @@ from tornado.web import UIModule +# from tornado.template import raw +import re class Alert(UIModule): def render(self, title, message=None, actions=None, level='info'): @@ -9,6 +11,26 @@ class Alert(UIModule): actions=actions, level=level) +class TextInput(UIModule): + def render(self, field, placeholder=''): + return self.render_string( + "components/text_input.html.to", + field=field, + label=re.sub('<[^<]+?>', '', str(field.label)), + errors=field.errors, + placeholder=placeholder, + description=field.description) + +class OptionsInput(UIModule): + def render(self, field, inline=False): + return self.render_string( + "components/options_input.html.to", + field=field, + label=re.sub('<[^<]+?>', '', str(field.label)), + errors=field.errors, + description=field.description, + inline=inline) + class Icon(UIModule): def render(self, name, classes=''): with open('static/icons/%s.svg' % name) as svg: diff --git a/scss/atat.scss b/scss/atat.scss index 2810db63..e8cbb614 100644 --- a/scss/atat.scss +++ b/scss/atat.scss @@ -5,12 +5,12 @@ @import 'core/util'; @import 'elements/typography'; +@import 'elements/icons'; @import 'elements/inputs'; @import 'elements/buttons'; @import 'elements/panels'; @import 'elements/block_lists'; @import 'elements/tables'; -@import 'elements/icons'; @import 'elements/sidenav'; @import 'elements/action_group'; diff --git a/scss/core/_util.scss b/scss/core/_util.scss index 505b4ed5..9b716bee 100644 --- a/scss/core/_util.scss +++ b/scss/core/_util.scss @@ -23,3 +23,7 @@ position: unset; width: unset; } + +@mixin line-max { + max-width: 45em; +} diff --git a/scss/elements/_inputs.scss b/scss/elements/_inputs.scss index b3151653..768b4210 100644 --- a/scss/elements/_inputs.scss +++ b/scss/elements/_inputs.scss @@ -4,6 +4,157 @@ * @source https://github.com/uswds/uswds/blob/develop/src/stylesheets/elements/_inputs.scss */ +@mixin input-icon { + width: 1.6rem; + height: 1.6rem; + display: block; +} + +@mixin input-state($state) { + $border-width: 1px; + $state-color: $color-gray; + + @if $state == 'error' { + $border-width: 2px; + $state-color: $color-red; + + } @else if $state == 'warning' { + $border-width: 2px; + $state-color: $color-gold; + + } @else if $state == 'success' { + $border-width: 2px; + $state-color: $color-green; + } + + .icon { + @include icon-color($state-color); + } + + .usa-input__message { + color: $state-color; + } + + input, + textarea, + select { + border-color: $state-color; + border-width: $border-width; + } + + fieldset { + input[type='radio'] { + + label::before { + box-shadow: 0 0 0 1px $color-white, 0 0 0 3px $color-red; + } + } + + input[type='checkbox'] { + + label::before { + box-shadow: 0 0 0 2px $color-red; + } + } + } +} + +.usa-input { + margin: ($gap * 4) ($gap * 2) ($gap * 4) 0; + + @includ media($medium-screen) { + margin: ($gap * 4) 0; + } + + label { + padding: 0 0 $gap 0; + @include h4; + @include line-max; + position: relative; + + .usa-input__help { + display: block; + @include h5; + font-weight: normal; + padding-top: $gap / 2; + @include line-max; + } + + .icon { + position: absolute; + left: 100%; + top: 100%; + margin-top: 1.4rem; + margin-left: $gap; + } + } + + input, + textarea, + select { + @include line-max; + margin: 0; + } + + .usa-input__choices { // checkbox & radio sets + legend { + padding: 0 0 $gap 0; + @include h4; + + .icon { + vertical-align: middle; + } + } + + ul { + list-style: none; + margin: 0; + padding: 0; + + > li { + margin: 0; + + [type='radio'] + label, + [type='checkbox'] + label { + margin: 0; + } + } + } + + label { + font-weight: normal; + margin: 0; + } + + .usa-input__message { + display: block; + } + + &.usa-input__choices--inline { + label { + display: inline-block; + padding-right: $gap * 3; + } + } + } + + .usa-input__message { + @include h5; + display: inline-block; + padding-top: $gap; + } + + &.usa-input--error { + @include input-state('error'); + } + + &.usa-input--warning { + @include input-state('warning'); + } + + &.usa-input--success { + @include input-state('success'); + } +} + select { border-radius: 0; -webkit-appearance: none; @@ -39,4 +190,33 @@ select { min-height: 4.4rem; } -} \ No newline at end of file +} + + +// Form Grid +.form-row { + margin: ($gap * 4) 0; + + .form-col { + flex-grow: 1; + + &:first-child .usa-input { + margin-top: 0; + } + + &:last-child .usa-input { + margin-bottom: 0; + } + } + + @include media($medium-screen) { + @include grid-row; + align-items: flex-start; + + .form-col { + .usa-input { + margin: 0 ($gap * 4) 0 0; + } + } + } +} diff --git a/scss/elements/_typography.scss b/scss/elements/_typography.scss index 57e310db..8a292e73 100644 --- a/scss/elements/_typography.scss +++ b/scss/elements/_typography.scss @@ -11,7 +11,7 @@ p { margin: 0 0 ($gap * 2) 0; - max-width: 45em; + @include line-max; } h1, h2, h3, h4, h5, h6 { diff --git a/templates/components/options_input.html.to b/templates/components/options_input.html.to new file mode 100644 index 00000000..ab296a5f --- /dev/null +++ b/templates/components/options_input.html.to @@ -0,0 +1,24 @@ +