/** * Outputs the selectors and properties for the Button component. * * @param {string} $primary-stylename (v-button) - the primary style name for the selectors * @param {bool} $include-additional-styles - should the mixin output all the different style variations of the component * * @group button */ @mixin valo-button ($primary-stylename: v-button, $include-additional-styles: contains($v-included-additional-styles, button)) { .#{$primary-stylename} { @include valo-button-static-style; @include valo-button-style; } @if $include-additional-styles { .#{$primary-stylename}-primary { @include valo-button-style($background-color: $v-selection-color); $padding-width: round($v-unit-size/2); padding: 0 $padding-width; font-weight: bold; $min-width: round($v-unit-size * 2.2); min-width: $min-width; // IE8 + border-box + min-width == fail .v-ie8 & { min-width: $min-width - ($padding-width * 2); } } .#{$primary-stylename}-friendly { @include valo-button-style($background-color: $v-friendly-color); } .#{$primary-stylename}-danger { @include valo-button-style($background-color: $v-error-indicator-color); } .#{$primary-stylename}-borderless { @include valo-button-borderless-style; } .#{$primary-stylename}-borderless-colored { @include valo-button-borderless-style($font-color: $v-selection-color); } .#{$primary-stylename}-quiet { @include valo-button-quiet-style; } .#{$primary-stylename}-link { @include valo-button-borderless-style; @include valo-link-style; } .#{$primary-stylename}-tiny { @include valo-button-style($unit-size: $v-unit-size--tiny, $bevel: null, $shadow: null, $background-color: null, $font-size: $v-font-size--tiny, $font-weight: null); } .#{$primary-stylename}-small { @include valo-button-style($unit-size: $v-unit-size--small, $bevel: null, $shadow: null, $background-color: null, $font-size: $v-font-size--small, $font-weight: null); } .#{$primary-stylename}-large { @include valo-button-style($unit-size: $v-unit-size--large, $bevel: null, $shadow: null, $background-color: null, $font-size: $v-font-size--large, $font-weight: null); } .#{$primary-stylename}-huge { @include valo-button-style($unit-size: $v-unit-size--huge, $bevel: null, $shadow: null, $background-color: null, $font-size: $v-font-size--huge, $font-weight: null); } .#{$primary-stylename}-icon-align-right { @include valo-button-icon-align-right-style; } .#{$primary-stylename}-icon-align-top { @include valo-button-icon-align-top-style; } .#{$primary-stylename}-icon-only { width: $v-unit-size; padding: 0; &.#{$primary-stylename}-tiny { width: $v-unit-size--tiny; } &.#{$primary-stylename}-small { width: $v-unit-size--small; } &.#{$primary-stylename}-large { width: $v-unit-size--large; } &.#{$primary-stylename}-huge { width: $v-unit-size--huge; } .#{$primary-stylename}-caption { display: none; } } } } /** * Outputs the static styles (i.e. styles which don't differ between button variants) for a button. * * @param {list} $states (normal hover focus active disabled) - The button states for which to output corresponding static styles * @param {bool} $vertical-centering (true) - Should the output contain a vertical centering guide * * @group button */ @mixin valo-button-static-style ($states: (normal, hover, focus, active, disabled), $vertical-centering: true) { @if contains($states, normal) { position: relative; text-align: center; white-space: nowrap; outline: none; @include valo-tappable; @if $vertical-centering { @include valo-button-vertical-centering; } } @if contains($states, hover) or contains($states, focus) or contains($states, active) { // Generated element for :hover, :focus and :active styles &:after { content: ""; position: absolute; top: 0; right: 0; bottom: 0; left: 0; border-radius: inherit; @if $v-animations-enabled { @include transition(box-shadow 180ms, border 180ms); } } } @if contains($states, focus) { &:focus:after { @if $v-animations-enabled { @include transition(none); } } } @if contains($states, disabled) { &.v-disabled { @include opacity($v-disabled-opacity); &:after { display: none; } } } } /** * Outputs the styles for a button variant. * * @param {size} $unit-size ($v-unit-size) - The sizing of the button, which corresponds its height * @param {size | list} $padding (null) - The padding of the button. Computed from other parameters by default. * @param {color} $font-color (null) - The font color of the button. Computed from the $background-color by default. * @param {number} $font-weight ($v-font-weight + 100) - The font weight of the button * @param {size} $font-size (null) - The font size of the button. Inherited from the parent by default. * @param {string} $cursor (null) - The mouse cursor of the button * @param {color} $background-color ($v-background-color) - The background color of the button * @param {list} $border ($v-border) - The border of the button * @param {size} $border-radius ($v-border-radius) - The border-radius of the button * @param {list} $gradient ($v-gradient) - Valo specific gradient value. See the documentation for $v-gradient. * @param {list} $bevel ($v-bevel) - Box-shadow value according to $v-bevel documentation * @param {list} $shadow ($v-shadow) - Box-shadow value according to $v-shadow documentation * @param {list} $states (normal hover focus active disabled) - The button states for which to output corresponding styles * * @group button */ @mixin valo-button-style ( $unit-size : $v-unit-size, $padding : null, $font-color : null, $font-weight : $v-font-weight + 100, $font-size : null, // Inherited by default $cursor : null, $background-color : $v-background-color, $border : $v-border, $border-radius : $v-border-radius, $gradient : $v-gradient, $bevel : $v-bevel, $shadow : $v-shadow, $states : (normal, hover, focus, active, disabled) ) { @if contains($states, focus) or contains($states, active) { $border-width: first-number($border); &:after { border: inherit; top: -$border-width; right: -$border-width; bottom: -$border-width; left: -$border-width; } } @if contains($states, normal) { @if $unit-size { height: $unit-size; @if type-of($padding) == number or type-of($padding) == list { padding: $padding; } @else { padding: 0 round($unit-size/2.4) + round($border-radius/3); } } $_font-color: $font-color or valo-font-color($background-color, 0.9); color: $_font-color; font-weight: $font-weight; font-size: $font-size; cursor: $cursor; border-radius: $border-radius; @if type-of($background-color) == color { @include valo-border-with-gradient($border: $border, $color: darkest-color($background-color, $v-background-color), $gradient: $gradient); @include valo-gradient($background-color, $gradient); @include box-shadow(valo-bevel-and-shadow($bevel: $bevel, $shadow: $shadow, $background-color: $background-color, $gradient: $gradient)); } @if $bevel and type-of($_font-color) == color and type-of($background-color) == color { text-shadow: valo-text-shadow($_font-color, $background-color); } @if $bevel == none and $shadow == none { @include box-shadow(none); } } @if $background-color { @if contains($states, hover) { &:hover:after { @include valo-button-hover-style($background-color); } } @if contains($states, focus) { &:focus:after { @include valo-button-focus-style($background-color); } } @if contains($states, active) { &:active:after { @include valo-button-active-style($background-color); } } } } /** * Outputs the hover state styles for a button. The styles are by default targeted * for a pseudo element which is shown on top of the normal state button. * * @group button * * @param {color} $background-color ($v-background-color) - The background color of the normal state button */ @mixin valo-button-hover-style ($background-color: $v-background-color) { $bg: darken($background-color, 25%); @if is-dark-color($background-color) { $bg: lighten($background-color, 15%); } background-color: rgba($bg, .1); } /** * Outputs the focus state styles for a button. The styles are by default targeted * for a pseudo element which is shown on top of the normal state button. * * @group button * * @param {color} $background-color ($v-background-color) - The background color of the normal state button * @param {list} $border-fallback (inherit) - If the luminance of $v-focus-color is less than the $background-color, the focus color is also used for the border color. If not, then $border-fallback is used for the focus element's border value. */ @mixin valo-button-focus-style ($background-color: $v-background-color, $border-fallback: inherit) { $focus-color: $v-focus-color; @if color-luminance($focus-color) + 50 < color-luminance($background-color) { border-color: $focus-color; } @else if $border-fallback != none { border: $border-fallback or valo-border($color: $background-color); } @include valo-focus-style; } /** * Outputs the active state (pressed/down) styles for a button. The styles are by default targeted * for a pseudo element which is shown on top of the normal state button. * * @group button * * @param {color} $background-color ($v-background-color) - The background color of the normal state button */ @mixin valo-button-active-style ($background-color: $v-background-color) { $bg: scale-color($background-color, $lightness: -50%, $saturation: saturation($background-color)); background-color: rgba($bg, .2); } /** * Outputs styles to allow vertical centering of the icon and the caption, independent of the * height of the button. * * @group button */ @mixin valo-button-vertical-centering { @include valo-vertical-align-guide($to-align: div, $pseudo-element: before); // WebKit handles line-heights and vertical-alignments somewhat differently, so we need to adjust .v-sa &:before { height: 110%; } // Firefox needs a bit of adjusting as well .v-ff &:before { height: 107%; } // ...and so does IE. Who knew? .v-ie &:before { margin-top: 4px; } } /** * Output styles for a borderless button. Expects that the targeted element * already has both valo-button-static-style and valo-button-style included. * * @param {color} $font-color (inherit) - The font color of the borderless button * * @group button */ @mixin valo-button-borderless-style ($font-color: inherit) { border: none; @include box-shadow(none); background: transparent; color: $font-color; &:hover { &:after { background: transparent; } @if type-of($font-color) == color { color: lighten($font-color, 10%); } } &:active { @include opacity(.7); &:after { background: transparent; } } } /** * Output styles for a "quiet" button (a button whose outline is only shown * once the user hovers over the button caption). Expects that the targeted * element already has both valo-button-static-style and valo-button-style * included. * * @group button */ @mixin valo-button-quiet-style { visibility: hidden; &:focus, &:hover { visibility: visible; } [class*="wrap"] { visibility: visible; } [class*="caption"] { // For IE8 display: inline-block; } } /** * Output styles to align a button's icon on the right side of its caption. * * @group button */ @mixin valo-button-icon-align-right-style { [class*="wrap"] { display: inline-block; } .v-icon { float: right; $padding-width: ceil($v-unit-size/2.4); margin-left: $padding-width + ceil($padding-width/-5); + span:not(:empty) { margin-left: 0; } } } /** * Output styles to align a button's icon on top of its caption. * * @group button */ @mixin valo-button-icon-align-top-style { height: auto; padding-top: ceil($v-unit-size/9); padding-bottom: ceil($v-unit-size/9); [class*="wrap"] { display: inline-block; } .v-icon { display: block; margin-left: auto; margin-right: auto; + span:not(:empty) { margin-top: ceil($v-unit-size/6); margin-left: 0; } } }