From: Shahyar Date: Wed, 30 Jul 2014 16:51:24 +0000 (-0400) Subject: mw-ui-button: Revamp the LESS to be simpler, and improve cross-browser support X-Git-Tag: 1.31.0-rc.0~13985 X-Git-Url: https://git.cyclocoop.org/%28%28?a=commitdiff_plain;h=c0ec2d64c0ea79e840072627407aeb16131e0f88;p=lhc%2Fweb%2Fwiklou.git mw-ui-button: Revamp the LESS to be simpler, and improve cross-browser support Uses a slightly modified iteration of the button design Drops mw-ui-primary Change-Id: Ia6deef500ada2cf33c96ce70909592764df39901 --- diff --git a/resources/src/mediawiki.ui/components/buttons.less b/resources/src/mediawiki.ui/components/buttons.less index 7142d4d071..73ff5c5a55 100644 --- a/resources/src/mediawiki.ui/components/buttons.less +++ b/resources/src/mediawiki.ui/components/buttons.less @@ -2,229 +2,304 @@ @import "mediawiki.ui/variables"; @import "mediawiki.ui/mixins"; -// Buttons -// -// All buttons start with mw-ui-button class, modified by other classes. -// It can be any element. Due to a lack of a CSS reset, the exact styling of -// the button depends on what type of element is used. -// There are two kinds of buttons, the default is a "Call to Action" with an obvious border -// and there is a quiet kind without a border. -// -// Styleguide 2. - -@buttonBorderRadius: 3px; -@transitionDuration: .1s; -@transitionFunction: ease-in-out; - -// Neutral button styling -// -// Markup: -// -// -// -// Styleguide 2.1. -.mw-ui-button { - // Inherit the font rather than apply user agent stylesheet (bug 70072) - font-family: inherit; - font-size: 1em; +/* +Buttons + +

Guidelines:

+ +- .mw-ui-button can **only** be used on **A, INPUT, and BUTTON tags**. There is support for some input types, but this doesn't work in older browsers. +- .mw-ui-progressive, .mw-ui-constructive, and .mw-ui-destructive can be applied alone on A (see Styleguide 4.0), but can be applied in tandem with .mw-ui-button. *The class order is important:* **base type** (mw-ui-button) must come **first**, **mode** (mw-ui-quiet) **second**, and **context** (mw-ui-progressive) comes **last**. +- A .mw-ui-quiet button may **never** be the first or only button in a form. +- Semantically, the **first button in a form should always be the affirmative action** (eg. Submit). This is for accessibility purposes. Where it appears visually is not as important. + +

Notes:

+ +- IE6 does not apply any .mw-ui-button styles at all on BUTTON. +- IE6 only applies the base .mw-ui-CONTEXT color on A, and doesn't care if you are combining it (ie. .mw-ui-destructive.mw-ui-quiet = always red text). +- IE7 and IE8 look slightly different from other browsers when rendering certain modes of these buttons. + +Markup: + + + + + + +.mw-ui-quiet - Quiet: A button that doesn't look like a button. +.mw-ui-inline - Inline: An even smaller button (zero padding) which also inherits font weight. +.mw-ui-big - Big: 1.3x font-size. + +Styleguide 2. +*/ + +// Helpers +// Individual Button Contexts +.mixin-mw-ui-button-context( @contextualColor ) { + @textShadowColor: spin( @colorTextLight, 180 ); + @borderColor: mix( @contextualColor, #000, 75% ); + @raisedColor: mix( @contextualColor, #fff, 92% ); + @depressedColor: darken( @contextualColor, 8% ); + @quietDepressedColor: darken( @contextualColor, 25% ); + + .mixin-mw-ui-button-disabled-state() { + &[disabled], + &[disabled]:hover, + &[disabled]:focus { + background: @colorGrayLight; + color: @colorWhite; + text-shadow: none; + .box-shadow( ~"none" ); + } + } + + .mixin-mw-ui-button-normal-mode() { + background: @contextualColor; + color: @colorWhite; + text-shadow: 0 1px fade( @textShadowColor, 10% ); + + .mixin-mw-ui-button-disabled-state(); + + &:hover, + &:focus { + background: @raisedColor; + text-shadow: 0 1px fade( @textShadowColor, 33% ); + } + + &:hover { + // Shadow under outer, 3D raising inner, edge shading inner + .box-shadow( ~"0 1px 0 0 rgba(0, 0, 0, .15), inset 0 -4px 0 0 @{borderColor}, inset 0 -1px 1px 0 rgba(0, 0, 0, .05)" ); + } + + &:focus { + // 3D raising inner, edge shading inner + .box-shadow( ~"inset 0 -4px 0 0 @{borderColor}, inset 0 -1px 1px 0 rgba(0, 0, 0, .05), inset 0 0 0 1px @{borderColor}" ); + } + + &:active { + background: @depressedColor; + // Slight 3D raising inner, deep edge shading inner + .box-shadow( ~"inset 0 -2px 0 0 @{depressedColor}, inset 0 2px 0 0 rgba(0, 0, 0, .25)" ); + } + } + + // Default mode (fully colored) + &:not(.mw-ui-quiet) { + .mixin-mw-ui-button-normal-mode(); + } + .lte-ie8 & { // IE7 & IE8 do not support :not() selector + .mixin-mw-ui-button-normal-mode(); + } + + // Quiet mode (transparent bg, no border; text color on activity) + .lte-ie8 &.mw-ui-quiet, + &.mw-ui-quiet { + background: transparent; + color: @colorTextLight; + + &:hover { + color: @contextualColor; + } + + &:active { + color: @depressedColor; + } + + &:focus { + color: @quietDepressedColor; + } + + .mixin-mw-ui-button-disabled-state(); + } +} + +// Default button styles +.mixin-mw-ui-button-default() { + background: @colorGrayLightest; + color: @colorTextLight; + @textShadowColor: spin( @colorTextLight, 180 ); + @borderColor: mix( @colorGrayLightest, #000, 75% ); + @raisedColor: mix( @colorGrayLightest, #fff, 92% ); + @depressedColor: darken( @colorGrayLightest, 8% ); + @quietDepressedColor: darken( @colorGrayLightest, 25% ); + + .mixin-mw-ui-button-normal-mode() { + &:hover, + &:focus { + background: @raisedColor; + text-shadow: 0 1px fade( @textShadowColor, 33% ); + } + + &:hover { + // Shadow under outer, 3D raising inner, edge shading inner + .box-shadow( ~"0 1px 0 0 rgba(0, 0, 0, .15), inset 0 -4px 0 0 @{borderColor}, inset 0 -1px 1px 0 rgba(0, 0, 0, .05)" ); + } + + &:focus { + // 3D raising inner, edge shading inner + .box-shadow( ~"inset 0 -4px 0 0 @{borderColor}, inset 0 -1px 1px 0 rgba(0, 0, 0, .05), inset 0 0 0 1px @{borderColor}" ); + } + + &:active { + background: @depressedColor; + // Slight 3D raising inner, deep edge shading inner + .box-shadow( ~"inset 0 -2px 0 0 @{depressedColor}, inset 0 2px 0 0 rgba(0, 0, 0, .25)" ); + } + } + + // Default mode (fully colored) + &:not(.mw-ui-quiet) { + .mixin-mw-ui-button-normal-mode(); + } + .lte-ie8 & { // IE7 & IE8 do not support :not() selector + .mixin-mw-ui-button-normal-mode(); + } + + // Quiet mode (transparent bg, no border; text color on activity) + .lte-ie8 &.mw-ui-quiet, + &.mw-ui-quiet { + background: transparent; + + &:hover, + &:focus, + &:active { + color: @colorText; + } + } +} + +// Selector mixins, used for customization if needed +.mixin-mw-ui-button() { // Container layout display: inline-block; padding: .5em 1em; margin: 0; + vertical-align: middle; .box-sizing(border-box); - // Disable weird iOS styling - -webkit-appearance: none; - // IE6/IE7 hack - // http://stackoverflow.com/a/5838575/365238 *display: inline; zoom: 1; - // Container styling - .button-colors(#FFF); - border-radius: @buttonBorderRadius; - - // Ensure that buttons and inputs are nicely aligned when they have differing heights - vertical-align: middle; + // Disable weird iOS styling + -webkit-appearance: none; - // Content styling - text-align: center; + // Typography + font-family: inherit; + font-size: 1em; font-weight: bold; + line-height: inherit; + text-decoration: none; - // Interaction styling + // Design + border: 0px solid transparent; + border-radius: 3px; cursor: pointer; + // Animation + .transition( ~"box-shadow .1s linear, background-color .1s linear, opacity .5s linear" ); + + // Disabled state (cursor fix) &:disabled { - text-shadow: none; cursor: default; } + // Focus/active state (outline fix) + &:focus, &:active { + outline: none; + } - .transition(background @transitionDuration @transitionFunction, color @transitionDuration @transitionFunction, box-shadow @transitionDuration @transitionFunction;); + /* + * Button modes (continued in .mw-ui-button-context()) + */ - // Styling for specific button types - // ----------------------------------------- + // Thin mode (no padding) + &.mw-ui-inline { + padding: 0; + font-weight: inherit; + vertical-align: inherit; + } - // Big buttons - // - // Not all buttons are equal. You can emphasise certain actions over others - // using the mw-ui-big class. - // - // Markup: - // - // - // - // - // - // Styleguide 2.1.6. + // Big mode (1.3x font size) &.mw-ui-big { font-size: 1.3em; } - // Block buttons - // - // Some buttons might need to be stacked. - // - // Markup: - // - // - // - // - // - // Styleguide 2.1.5. - &.mw-ui-block { - display: block; - width: 100%; - } - - // Progressive buttons - // - // Use progressive buttons for actions which lead to a next step in the process. - // .mw-ui-primary is deprecated, kept for compatibility. - // - // Markup: - // - // - // - // Styleguide 2.1.1. - &.mw-ui-progressive, - &.mw-ui-primary { - .button-colors(@colorProgressive); - - &.mw-ui-quiet { - .button-colors-quiet(@colorProgressive); - } + /* + * Default button styles + */ + + .mixin-mw-ui-button-default(); + + /* + * Contextual classes + */ + + // Progressive context + &.mw-ui-progressive { + .mixin-mw-ui-button-context( @colorProgressive ); } - // Constructive buttons - // - // Use constructive buttons for actions which result in a final action in the process that results - // in a change of state. - // e.g. save changes button - // - // Markup: - // - // - // - // Styleguide 2.1.2. + // Constructive context &.mw-ui-constructive { - .button-colors(@colorConstructive); - - &.mw-ui-quiet { - .button-colors-quiet(@colorConstructive); - } + .mixin-mw-ui-button-context( @colorConstructive ); } - // Destructive buttons - // - // Use destructive buttons for actions which result in the destruction of data. - // e.g. deleting a page. - // This should not be used for cancel buttons. - // - // Markup: - // - // - // - // Styleguide 2.1.3. + // Destructive context &.mw-ui-destructive { - .button-colors(@colorDestructive); - - &.mw-ui-quiet { - .button-colors-quiet(@colorDestructive); - } + .mixin-mw-ui-button-context( @colorDestructive ); } +} - // Quiet buttons - // - // Use quiet buttons when they are less important and alongisde other progressive/destructive/progressive buttons. - // - // Markup: - // - // - // - // - // - // - // - // - // Styleguide 2.1.4. - &.mw-ui-quiet { - background: transparent; - border: none; - text-shadow: none; - .button-colors-quiet(@colorButtonText); +// Button selectors +.mw-ui-button { + .mixin-mw-ui-button; - &:hover, - &:focus { - box-shadow: none; - } + // Default mw-ui-button implementation forces min dimensions for improved touch access + min-width: 48px; + min-height: 33px; - &:active, - &:disabled { - background: transparent; - } + // When these buttons are children of mw-ui-button-group, adjust accordingly + .mw-ui-button-group > & { + .mw-ui-button-group-child; } } -a.mw-ui-button { - text-decoration: none; +/* +Button groups + +Group of buttons. + +Markup: +
+ A + B + C + D +
- // This overrides an underline declaration on a:hover and a:focus in - // commonElements.css, which the class alone isn't specific enough to do. - &:hover, - &:focus { - text-decoration: none; +Styleguide 2.1. +*/ +.mw-ui-button-group { + // Clearfix + zoom: 1; + &:after { + content: ""; + display: table; + clear: both; } } -// Button groups -// -// Group of buttons. Make sure you clear the floating after using a mw-ui-button-group. -// -// Markup: -//
-//
A
-//
B
-//
C
-//
D
-//
-// -// Styleguide 2.2. -.mw-ui-button-group > * { +// To be used within .mw-ui-button selector +.mw-ui-button-group-child() { border-radius: 0; float: left; &:first-child { - border-top-left-radius: @buttonBorderRadius; - border-bottom-left-radius: @buttonBorderRadius; - } - - &:not(:first-child) { - border-left: none; + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; } - &:last-child{ - border-top-right-radius: @buttonBorderRadius; - border-bottom-right-radius: @buttonBorderRadius; + &:last-child { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; } }