From b8b8806dc4355907a264a104133ca13ff2e69b6d Mon Sep 17 00:00:00 2001 From: Gabriel Ledung Date: Fri, 28 Aug 2015 11:59:46 +0200 Subject: [PATCH 1/5] Added styling for basic form components --- less/components/action-button.less | 13 ++++ less/components/check-box.less | 90 +++++++++++++++++++++++++++ less/components/components.less | 17 +++++ less/components/input-field.less | 30 +++++++++ less/components/loading-spinner.less | 16 +++++ less/components/primary-button.less | 78 +++++++++++++++++++++++ less/components/radio-block.less | 64 +++++++++++++++++++ less/components/radio-button.less | 45 ++++++++++++++ less/components/radio-input.less | 7 +++ less/components/radio-switch.less | 44 +++++++++++++ less/components/secondary-button.less | 15 +++++ less/components/select-box.less | 43 +++++++++++++ less/components/shortcut-button.less | 20 ++++++ less/ffe.less | 1 + 14 files changed, 483 insertions(+) create mode 100644 less/components/action-button.less create mode 100644 less/components/check-box.less create mode 100644 less/components/components.less create mode 100644 less/components/input-field.less create mode 100644 less/components/loading-spinner.less create mode 100644 less/components/primary-button.less create mode 100644 less/components/radio-block.less create mode 100644 less/components/radio-button.less create mode 100644 less/components/radio-input.less create mode 100644 less/components/radio-switch.less create mode 100644 less/components/secondary-button.less create mode 100644 less/components/select-box.less create mode 100644 less/components/shortcut-button.less diff --git a/less/components/action-button.less b/less/components/action-button.less new file mode 100644 index 0000000000..bcd84577be --- /dev/null +++ b/less/components/action-button.less @@ -0,0 +1,13 @@ +.action-button { + &:extend(.primary-button all); + background-color: @green-wcag; + + &:focus, + &:hover { + background-color: darken(@green-wcag, 5%); + } + &:active, + &.-loading { + background-color: darken(@green-wcag, 10%); + } +} \ No newline at end of file diff --git a/less/components/check-box.less b/less/components/check-box.less new file mode 100644 index 0000000000..883bac87dc --- /dev/null +++ b/less/components/check-box.less @@ -0,0 +1,90 @@ +/* ---- Accessible and animated checkbox ---- + Requires the markup to wrap a checkbox-input and a label (in that order!) + in an element with class "checkbox" +*/ + +@keyframes checkmark { + 0% { height: 0; width: 6px; } + 50% { height: 11px; width: 6px; } +} + +.checkbox { + > input[type="checkbox"] { + opacity: 0; + position: absolute; + cursor: pointer; + + &:checked + label:before, + &:hover + label:before, + &:focus + label:before, + &:active + label:before { + outline: none; + } + + &:hover + label:before { + border-color: @blue-royal-light-wcag; + } + + &:active + label:before, + &:focus + label:before { + border-color: @blue-royal-light-wcag; + box-shadow: 0 0 0 2px @blue-focus; + } + + &:checked + label:before { + border-color: @blue-royal-light-wcag; + background-color: @blue-royal-light-wcag; + } + + &:focus + label:before { + box-shadow: 0 0 0 2px @blue-focus; + } + + + + &:checked + label:after { + animation: checkmark 0.4s; + border-color: white; + } + } + + > label { + position: relative; + + &:before { + border: solid 2px @grey; + border-radius: 2px; + content: ''; + display: inline-block; + height: 20px; + margin-right: 15px; + position: relative; + top: 3px; + transition: all 0.2s; + width: 20px; + background-color: white; + } + + &:after { + transform: scaleX(-1) rotate(180deg + -45deg); + transform-origin: left top; + + border-right: 3px solid transparent; + border-top: 3px solid transparent; + + content: ''; + display: block; + height: 11px; + width: 6px; + left: 4px; + top: 11px; + position: absolute; + } + } +} + +.error .checkbox { + > label:before { + border-color: @orange-wcag; + } +} \ No newline at end of file diff --git a/less/components/components.less b/less/components/components.less new file mode 100644 index 0000000000..d7571fcd14 --- /dev/null +++ b/less/components/components.less @@ -0,0 +1,17 @@ +/* Buttons */ +@import 'primary-button'; +@import 'secondary-button'; +@import 'shortcut-button'; +@import 'action-button'; + +/* Inputs*/ +@import 'input-field'; +@import 'select-box'; +@import 'check-box'; +@import 'radio-input'; +@import 'radio-button'; +@import 'radio-switch'; +@import 'radio-block'; + +/* Other*/ +@import 'loading-spinner'; diff --git a/less/components/input-field.less b/less/components/input-field.less new file mode 100644 index 0000000000..e70cc0e6f9 --- /dev/null +++ b/less/components/input-field.less @@ -0,0 +1,30 @@ +.input-field { + display: inline-block; + height: 45px; + padding: 13px; + font-family: MuseoSans-300, arial, sans-serif; + font-size: 18px; + border-radius: 6px; + border: 1px solid @grey-light; + transition: all 0.15s ease-in-out; + .shadow-inset(); + + &:hover { + border-color: @blue-royal-light-wcag; + } + &:focus, &:active { + border-color: @blue-royal-light-wcag; + box-shadow: 0 0 0 2px @blue-focus; + outline: none; + } + &.-small { + width: 95px; + } + &.-medium { + width: 130px; + } + &.-large { + width: 160px; + } + +} \ No newline at end of file diff --git a/less/components/loading-spinner.less b/less/components/loading-spinner.less new file mode 100644 index 0000000000..80ab8c9b3c --- /dev/null +++ b/less/components/loading-spinner.less @@ -0,0 +1,16 @@ +.loading-spinner { + display: inline-block; + vertical-align: middle; + + &:before { + .sb1-spinner(); + } + + &.-large:before { + border-width: 3px; + height: 40px; + width: 40px; + } +} + + diff --git a/less/components/primary-button.less b/less/components/primary-button.less new file mode 100644 index 0000000000..767258920d --- /dev/null +++ b/less/components/primary-button.less @@ -0,0 +1,78 @@ +.primary-button { + font-family: 'MuseoSans-500', arial, sans-serif; + font-size: 18px; + text-decoration: none; + cursor: pointer; + text-align: center; + vertical-align: middle; + padding: 0 30px; + border-radius: 4px; + color: @white; + background-color: @blue-flat; + border: 2px solid transparent; + display: block; + line-height: @button-height; + width: 100%; + overflow: hidden; + .shadow-buttons(); + transition: all 0.2s; + outline: none; + + &:focus { + box-shadow: 0 0 0 2px @blue-focus; + background-color: darken(@blue-flat,5%); + } + + &:hover { + .shadow-buttons-hover(); + background-color: darken(@blue-flat,5%); + } + &:active { + .shadow-buttons-active(); + background-color: darken(@blue-flat,10%); + } + > .icon { + width: 36px; + height: 36px; + } + + > .label { + overflow: hidden; + position: relative; + + > .label-text { + position: relative; + bottom: 0; + transition: bottom 0.2s; + } + + > .label-spinner { + .sb1-spinner(@white,22px); + position: absolute; + bottom: -40px; + left: ~"calc(50% - 11px)"; + transition: bottom 0.2s; + } + } + + &.-loading { + pointer-events: none; + background-color: darken(@blue-royal-light-wcag,10%); + > .label { + > .label-text { + bottom: 50px; + } + + > .label-spinner { + bottom: 0; + } + } + } +} + +@media screen and (min-width: @breakpoint-sm) { + .primary-button { + display: inline-block; + width: auto; + } +} diff --git a/less/components/radio-block.less b/less/components/radio-block.less new file mode 100644 index 0000000000..bdf589a65e --- /dev/null +++ b/less/components/radio-block.less @@ -0,0 +1,64 @@ +.radio-block { + margin: 10px 0; + max-width: 600px; + min-width: 260px; + transition: width 0.3s ease-in-out; + + .content { + width: 100%; + position: relative; + border: 2px solid @grey-light; + border-radius: 5px; + display: inline-block; + margin-right: 10px; + color: @black; + background-color: white; + cursor: pointer; + + &:before { + .sb1-radioblob(); + left: 18px; + top: 14px; + } + + > .header { + display: block; + padding: 10px 60px; + cursor: pointer; + } + + > .wrapper { + padding: 10px 0 25px 60px; + cursor: auto; + } + } + + .radio-input { + & + .content > .wrapper { + display: none; + } + + & + .content > .wrapper.-visible { + display: block; + } + + &:checked + .content { + border: 2px solid @blue-royal; + > .header { + background-color: @blue-royal; + color: white; + } + > .wrapper { + display: block; + } + } + + &:checked + .content:before { + .sb1-radioblob-active(); + } + + &:focus + .content { + box-shadow: 0 0 0 2px @blue-focus; + } + } +} \ No newline at end of file diff --git a/less/components/radio-button.less b/less/components/radio-button.less new file mode 100644 index 0000000000..b82702091a --- /dev/null +++ b/less/components/radio-button.less @@ -0,0 +1,45 @@ +.radio-button { + display: block; + position: relative; + color: @black; + background-color: @white; + cursor: pointer; + margin: 10px 0; + max-width: 600px; + min-width: 260px; + transition: width 0.15s ease-in-out; + text-align: left; + padding-left: 40px; + + &:before { + .sb1-radioblob(); + left: 10px; + top: 3px; + } + } + +.radio-input { + &:checked + .radio-button:before, + &:hover + .radio-button:before, + &:focus + .radio-button:before, + &:active + .radio-button:before { + outline: none; + } + + &:hover + .radio-button:before { + border-color: @blue-royal-light-wcag; + } + + &:active + .radio-button:before, + &:focus + .radio-button:before { + border-color: @blue-focus + } + + &:checked + .radio-button:before { + .sb1-radioblob-active(); + } + + &:focus + .radio-button:before { + box-shadow: 0 0 0 2px @blue-focus; + } +} \ No newline at end of file diff --git a/less/components/radio-input.less b/less/components/radio-input.less new file mode 100644 index 0000000000..a97fa8c8f1 --- /dev/null +++ b/less/components/radio-input.less @@ -0,0 +1,7 @@ +.radio-input { + position: absolute; + opacity: 0; + height: 0; + width: 0; + min-width: 0; +} \ No newline at end of file diff --git a/less/components/radio-switch.less b/less/components/radio-switch.less new file mode 100644 index 0000000000..a11b03f1a4 --- /dev/null +++ b/less/components/radio-switch.less @@ -0,0 +1,44 @@ +.radio-switch { + padding: 8px 20px 8px 50px; + position: relative; + border: 1px solid @grey-light; + border-radius: 30px; + display: inline-block; + min-width: 100px; + margin-right: 10px; + text-align: left; + color: @blue-royal-light; + font-family: "MuseoSansRounded-700", arial, sans-serif; + cursor: pointer; + transition: all 0.15s ease-in-out; + .shadow-buttons(); + + &:before { + .sb1-radioblob(); + left: 12px; + top: 11px; + } +} + +.radio-input { + + &:checked + .radio-switch { + border-color: @blue-royal; + background-color: @blue-royal; + color: @white; + } + + &:hover + .radio-switch{ + border-color: @blue-royal-light-wcag; + } + + &:focus + .radio-switch { + border-color: @blue-focus; + box-shadow: 0 0 0 1px @blue-focus; + } + + &:checked + .radio-switch:before { + .sb1-radioblob-active(); + } + +} \ No newline at end of file diff --git a/less/components/secondary-button.less b/less/components/secondary-button.less new file mode 100644 index 0000000000..2af1e600a6 --- /dev/null +++ b/less/components/secondary-button.less @@ -0,0 +1,15 @@ +.secondary-button { + &:extend(.primary-button all); + color: @blue-royal-light-wcag; + background-color: @white; + border: solid 2px @grey-light; + + &:hover, &:focus,&:active { + border-color: @blue-royal-light-wcag; + background-color: @white; + } + + &.-loading { + background-color: @blue-royal; + } +} \ No newline at end of file diff --git a/less/components/select-box.less b/less/components/select-box.less new file mode 100644 index 0000000000..29ce736157 --- /dev/null +++ b/less/components/select-box.less @@ -0,0 +1,43 @@ +@select-box-height: 45px; + +.select-box, +select { + padding: 10px 32px 10px 10px; + height: @select-box-height; + border: 1px solid @grey-light; + background-image: url('/sfo-client/open/images/chevron-royal-light.svg'); + background-color: #FFF; + background-size: 18px 18px; + background-repeat: no-repeat; + background-position: 94% 50%; + line-height: 20px; + font-size: 18px; + border-radius: 4px; + font-family: MuseoSans-300,arial,sans-serif; + min-width: 175px; + transition: all 0.15s ease-in-out; + .shadow(); + + &:hover { + border-color: @blue-royal-light-wcag; + } + &:focus, &:active { + border-color: @blue-royal-light-wcag; + box-shadow: 0 0 0 2px @blue-focus; + outline: none; + } + + &::-ms-expand { + display: none; + } + + &.error { + border-color: @orange-wcag; + border-style: solid; + margin-bottom: 5px; + + &:focus { + outline-color: #fff; + } + } +} diff --git a/less/components/shortcut-button.less b/less/components/shortcut-button.less new file mode 100644 index 0000000000..4a6b7bf6f7 --- /dev/null +++ b/less/components/shortcut-button.less @@ -0,0 +1,20 @@ +.shortcut-button { + &:extend(.secondary-button all); + padding-right: 35px; + + > .icon-chevron { + width: 16px; + height: 16px; + position: relative; + left: 15px; + bottom: 2px; + transition: left 0.1s; + } + + &:hover, &:active, &:focus { + + > .icon-chevron { + left: 20px; + } + } +} diff --git a/less/ffe.less b/less/ffe.less index 8d9a2ee658..065079d34d 100644 --- a/less/ffe.less +++ b/less/ffe.less @@ -3,3 +3,4 @@ @import 'fonts'; @import 'layout'; @import 'typography'; +@import 'components/components'; From e908ebc579b0827e2ea1838894dbf826e36e02f5 Mon Sep 17 00:00:00 2001 From: Gabriel Ledung Date: Fri, 28 Aug 2015 13:31:36 +0200 Subject: [PATCH 2/5] Added chevron icons used by buttons. Icons should only be added to FFE if there is a heavy design dependency. We do not want to have a bloated library with many unused icon references in the CSS --- icons/chevron-royal-light.svg | 11 ++++++++++ icons/chevron-royal.svg | 11 ++++++++++ icons/chevron-white.svg | 11 ++++++++++ icons/icons.less | 38 +++++++++++++++++++++++++++++++++++ less/ffe.less | 1 + 5 files changed, 72 insertions(+) create mode 100644 icons/chevron-royal-light.svg create mode 100644 icons/chevron-royal.svg create mode 100644 icons/chevron-white.svg create mode 100644 icons/icons.less diff --git a/icons/chevron-royal-light.svg b/icons/chevron-royal-light.svg new file mode 100644 index 0000000000..a5ba7b8f96 --- /dev/null +++ b/icons/chevron-royal-light.svg @@ -0,0 +1,11 @@ + + + + + + diff --git a/icons/chevron-royal.svg b/icons/chevron-royal.svg new file mode 100644 index 0000000000..ccd3082bde --- /dev/null +++ b/icons/chevron-royal.svg @@ -0,0 +1,11 @@ + + + + + + diff --git a/icons/chevron-white.svg b/icons/chevron-white.svg new file mode 100644 index 0000000000..b775256f78 --- /dev/null +++ b/icons/chevron-white.svg @@ -0,0 +1,11 @@ + + + + + + diff --git a/icons/icons.less b/icons/icons.less new file mode 100644 index 0000000000..2156848964 --- /dev/null +++ b/icons/icons.less @@ -0,0 +1,38 @@ +.icon-base { + width: 50px; + height: 50px; + display: inline-block; + vertical-align: middle; + background-size: cover; + + @media screen and (min-width: @breakpoint-sm) { + height: 75px; + width: 75px; + } + @media screen and (min-width: @breakpoint-md) { + height: 90px; + width: 90px; + } +} + +.icon-chevron { + &:extend(.icon-base all); + background: url("@{icon-url}/chevron-royal.svg"); + + &.-light-blue { + background: url("@{icon-url}/chevron-royal-light.svg"); + } + &.-white { + background: url("@{icon-url}/chevron-white.svg"); + } + + &.-up { + transform: rotate(180deg); + } + &.-left { + transform: rotate(90deg); + } + &.-right { + transform: rotate(-90deg); + } +} diff --git a/less/ffe.less b/less/ffe.less index 065079d34d..ae77b8a397 100644 --- a/less/ffe.less +++ b/less/ffe.less @@ -1,6 +1,7 @@ @import 'reset'; @import 'colors'; @import 'fonts'; +@import 'icons'; @import 'layout'; @import 'typography'; @import 'components/components'; From 738c8c1d2e7b374f24a8c5dadca6b8e84639038d Mon Sep 17 00:00:00 2001 From: Gabriel Ledung Date: Fri, 28 Aug 2015 13:35:03 +0200 Subject: [PATCH 3/5] Added mixins --- less/ffe.less | 3 ++- {icons => less}/icons.less | 0 less/mixins.less | 50 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) rename {icons => less}/icons.less (100%) create mode 100644 less/mixins.less diff --git a/less/ffe.less b/less/ffe.less index ae77b8a397..de86648c37 100644 --- a/less/ffe.less +++ b/less/ffe.less @@ -2,6 +2,7 @@ @import 'colors'; @import 'fonts'; @import 'icons'; -@import 'layout'; +@import 'mixins'; @import 'typography'; +@import 'layout'; @import 'components/components'; diff --git a/icons/icons.less b/less/icons.less similarity index 100% rename from icons/icons.less rename to less/icons.less diff --git a/less/mixins.less b/less/mixins.less new file mode 100644 index 0000000000..72de659fb4 --- /dev/null +++ b/less/mixins.less @@ -0,0 +1,50 @@ +.sb1-radioblob() { + content: ''; + background-color: @white; + border: 2px solid @grey; + width: 20px; + height: 20px; + border-radius: 50%; + position: absolute; + pointer-events: none; +} +.sb1-radioblob-active() { + background-color: @white; + border: 7px solid @blue-royal-light-wcag; +} + +.sb1-spinner(@color: @blue-royal-light, @size: 20px) { + content: ' '; + display: inline-block; + position: relative; + width: @size; + height: @size; + border: 3px solid @color; + border-top-color: transparent; + border-radius: 50%; + visibility: visible; + animation: spindindust 1s linear infinite; + + @keyframes spindindust { + 0% { transform: rotate(0); } + 100% { transform: rotate(360deg); } + } + +} + + +.shadow() { + box-shadow: 0 1px 2px @grey; +} +.shadow-inset() { + box-shadow: 0 1px 2px @grey inset; +} +.shadow-buttons() { + box-shadow: 0 1px 2px 1px rgba(0,0,0,0.05); +} +.shadow-buttons-hover() { + box-shadow: 0 1px 2px 1px rgba(0,0,0,0.15); +} +.shadow-buttons-active() { + box-shadow: inset 0 1px 1px 0 rgba(0,0,0,0.25); +} From 12e61cde10591f7d69561907df5171172d23516b Mon Sep 17 00:00:00 2001 From: Gabriel Ledung Date: Fri, 28 Aug 2015 14:02:09 +0200 Subject: [PATCH 4/5] Added variable paths for fonts and icons --- less/components/input-field.less | 2 +- less/components/select-box.less | 2 +- less/ffe.less | 4 ++++ less/fonts.less | 10 +++++----- less/mixins.less | 20 +++++++++++++------- 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/less/components/input-field.less b/less/components/input-field.less index e70cc0e6f9..e1ff1e0a03 100644 --- a/less/components/input-field.less +++ b/less/components/input-field.less @@ -7,7 +7,7 @@ border-radius: 6px; border: 1px solid @grey-light; transition: all 0.15s ease-in-out; - .shadow-inset(); + box-shadow: 0 1px 2px @grey inset; &:hover { border-color: @blue-royal-light-wcag; diff --git a/less/components/select-box.less b/less/components/select-box.less index 29ce736157..e9d59f7e93 100644 --- a/less/components/select-box.less +++ b/less/components/select-box.less @@ -16,7 +16,7 @@ select { font-family: MuseoSans-300,arial,sans-serif; min-width: 175px; transition: all 0.15s ease-in-out; - .shadow(); + &:hover { border-color: @blue-royal-light-wcag; diff --git a/less/ffe.less b/less/ffe.less index de86648c37..d907b0f4d9 100644 --- a/less/ffe.less +++ b/less/ffe.less @@ -1,3 +1,7 @@ +@base-url: "/"; +@font-url: "@{base-url}/fonts"; +@icon-url: "@{base-url}/icons"; + @import 'reset'; @import 'colors'; @import 'fonts'; diff --git a/less/fonts.less b/less/fonts.less index 8b8c349e75..f173d28bda 100644 --- a/less/fonts.less +++ b/less/fonts.less @@ -1,26 +1,26 @@ /* Museo Sans */ @font-face { font-family: "MuseoSans-500"; - src: url("@{base-url}/fonts/museoSans_500.otf"); + src: url("@{font-url}/museoSans_500.otf"); } @font-face { font-family: "MuseoSans-300"; - src: url("@{base-url}/fonts/museoSans-300.otf"); + src: url("@{font-url}/museoSans-300.otf"); } /* Museo Sans Rounded */ @font-face { font-family: "MuseoSansRounded-700"; - src: url("@{base-url}/fonts/museoSansRounded-700.otf"); + src: url("@{font-url}/museoSansRounded-700.otf"); } @font-face { font-family: "MuseoSansRounded-500"; - src: url("@{base-url}/fonts/museoSansRounded-500.otf"); + src: url("@{font-url}/museoSansRounded-500.otf"); } @font-face { font-family: "MuseoSansRounded-300"; - src: url("@{base-url}/fonts/museoSansRounded-300.otf"); + src: url("@{font-url}/museoSansRounded-300.otf"); } \ No newline at end of file diff --git a/less/mixins.less b/less/mixins.less index 72de659fb4..39a7533c11 100644 --- a/less/mixins.less +++ b/less/mixins.less @@ -1,3 +1,6 @@ +/* + Radioblob: Small design element on "radio button"-like elements +*/ .sb1-radioblob() { content: ''; background-color: @white; @@ -8,11 +11,18 @@ position: absolute; pointer-events: none; } + +/* + Radioblob: Active state of the blob +*/ .sb1-radioblob-active() { background-color: @white; border: 7px solid @blue-royal-light-wcag; } +/* + Spinner: Commonly found on buttons and loading pages +*/ .sb1-spinner(@color: @blue-royal-light, @size: 20px) { content: ' '; display: inline-block; @@ -32,13 +42,9 @@ } - -.shadow() { - box-shadow: 0 1px 2px @grey; -} -.shadow-inset() { - box-shadow: 0 1px 2px @grey inset; -} +/* + Shadow for buttons: Commonly found on elements supposed to be buttons +*/ .shadow-buttons() { box-shadow: 0 1px 2px 1px rgba(0,0,0,0.05); } From bde26fb4f0461d4d0892ba9ba8c0fc22a3ada193 Mon Sep 17 00:00:00 2001 From: Gabriel Ledung Date: Fri, 28 Aug 2015 14:12:34 +0200 Subject: [PATCH 5/5] More variable clean up --- less/components/primary-button.less | 2 +- less/components/select-box.less | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/less/components/primary-button.less b/less/components/primary-button.less index 767258920d..86852bffad 100644 --- a/less/components/primary-button.less +++ b/less/components/primary-button.less @@ -11,7 +11,7 @@ background-color: @blue-flat; border: 2px solid transparent; display: block; - line-height: @button-height; + line-height: 41; width: 100%; overflow: hidden; .shadow-buttons(); diff --git a/less/components/select-box.less b/less/components/select-box.less index e9d59f7e93..aca52a36e1 100644 --- a/less/components/select-box.less +++ b/less/components/select-box.less @@ -1,12 +1,9 @@ -@select-box-height: 45px; - -.select-box, -select { +.select-box { padding: 10px 32px 10px 10px; - height: @select-box-height; + height: 44px; border: 1px solid @grey-light; background-image: url('/sfo-client/open/images/chevron-royal-light.svg'); - background-color: #FFF; + background-color: @white; background-size: 18px 18px; background-repeat: no-repeat; background-position: 94% 50%;