From 76ba4b12e38041f25e615c7b700f1efb883db494 Mon Sep 17 00:00:00 2001 From: simurai Date: Fri, 23 Nov 2018 11:38:11 +0900 Subject: [PATCH 1/8] Move Atom UI into Core --- static/atom-ui/README.md | 13 + static/atom-ui/_index.less | 35 + static/atom-ui/styles/badges.less | 65 ++ static/atom-ui/styles/button-groups.less | 187 +++++ static/atom-ui/styles/buttons.less | 274 +++++++ static/atom-ui/styles/git-status.less | 13 + static/atom-ui/styles/icons.less | 13 + static/atom-ui/styles/inputs.less | 382 ++++++++++ static/atom-ui/styles/layout.less | 85 +++ static/atom-ui/styles/lists.less | 291 ++++++++ static/atom-ui/styles/loading.less | 21 + static/atom-ui/styles/messages.less | 41 + static/atom-ui/styles/mixins/mixins.less | 87 +++ static/atom-ui/styles/modals.less | 82 ++ static/atom-ui/styles/panels.less | 36 + static/atom-ui/styles/private/README.md | 5 + static/atom-ui/styles/private/alerts.less | 114 +++ static/atom-ui/styles/private/close.less | 38 + static/atom-ui/styles/private/code.less | 77 ++ static/atom-ui/styles/private/forms.less | 705 ++++++++++++++++++ static/atom-ui/styles/private/links.less | 18 + static/atom-ui/styles/private/navs.less | 275 +++++++ .../atom-ui/styles/private/scaffolding.less | 55 ++ static/atom-ui/styles/private/sections.less | 38 + static/atom-ui/styles/private/tables.less | 208 ++++++ static/atom-ui/styles/private/utilities.less | 60 ++ static/atom-ui/styles/select-list.less | 57 ++ static/atom-ui/styles/site-colors.less | 9 + static/atom-ui/styles/text.less | 269 +++++++ static/atom-ui/styles/tooltip.less | 112 +++ .../atom-ui/styles/variables/variables.less | 231 ++++++ static/atom.less | 2 +- 32 files changed, 3897 insertions(+), 1 deletion(-) create mode 100644 static/atom-ui/README.md create mode 100644 static/atom-ui/_index.less create mode 100644 static/atom-ui/styles/badges.less create mode 100644 static/atom-ui/styles/button-groups.less create mode 100644 static/atom-ui/styles/buttons.less create mode 100644 static/atom-ui/styles/git-status.less create mode 100644 static/atom-ui/styles/icons.less create mode 100644 static/atom-ui/styles/inputs.less create mode 100644 static/atom-ui/styles/layout.less create mode 100644 static/atom-ui/styles/lists.less create mode 100644 static/atom-ui/styles/loading.less create mode 100644 static/atom-ui/styles/messages.less create mode 100644 static/atom-ui/styles/mixins/mixins.less create mode 100644 static/atom-ui/styles/modals.less create mode 100644 static/atom-ui/styles/panels.less create mode 100644 static/atom-ui/styles/private/README.md create mode 100644 static/atom-ui/styles/private/alerts.less create mode 100644 static/atom-ui/styles/private/close.less create mode 100644 static/atom-ui/styles/private/code.less create mode 100644 static/atom-ui/styles/private/forms.less create mode 100644 static/atom-ui/styles/private/links.less create mode 100644 static/atom-ui/styles/private/navs.less create mode 100644 static/atom-ui/styles/private/scaffolding.less create mode 100644 static/atom-ui/styles/private/sections.less create mode 100644 static/atom-ui/styles/private/tables.less create mode 100644 static/atom-ui/styles/private/utilities.less create mode 100644 static/atom-ui/styles/select-list.less create mode 100644 static/atom-ui/styles/site-colors.less create mode 100644 static/atom-ui/styles/text.less create mode 100644 static/atom-ui/styles/tooltip.less create mode 100644 static/atom-ui/styles/variables/variables.less diff --git a/static/atom-ui/README.md b/static/atom-ui/README.md new file mode 100644 index 000000000..b3c02c7df --- /dev/null +++ b/static/atom-ui/README.md @@ -0,0 +1,13 @@ +# :sparkles: Atom UI :sparkles: + +This is Atom's UI library. Originally forked from Bootstrap `3.3.6`, then merged with some core styles and now tweaked to Atom's needy needs. + +## Components + +Here a list of [all components](atom-ui.less). Open the [Styleguide](https://github.com/atom/styleguide) package (`cmd-ctrl-shift-g`) to see them in action and how to use them. + +![Styleguide](https://cloud.githubusercontent.com/assets/378023/15767543/ccecf9bc-2983-11e6-9c5e-d228d39f52b0.png) + +## Feature requests + +If you need something, feel free to open an issue and it might can be added. :v: diff --git a/static/atom-ui/_index.less b/static/atom-ui/_index.less new file mode 100644 index 000000000..4a1db024b --- /dev/null +++ b/static/atom-ui/_index.less @@ -0,0 +1,35 @@ +// Atom UI + +// Private! Don't use these in packages. +// If you need something, feel free to open an issue and it might can be made public +@import "styles/private/scaffolding.less"; + +@import "styles/private/alerts.less"; +@import "styles/private/close.less"; +@import "styles/private/code.less"; +@import "styles/private/forms.less"; +@import "styles/private/links.less"; +@import "styles/private/navs.less"; +@import "styles/private/sections.less"; +@import "styles/private/tables.less"; +@import "styles/private/utilities.less"; + + +// Public components +// Open the Styleguide to see them in action +@import "styles/badges.less"; +@import "styles/button-groups.less"; +@import "styles/buttons.less"; +@import "styles/git-status.less"; +@import "styles/icons.less"; +@import "styles/inputs.less"; +@import "styles/layout.less"; +@import "styles/lists.less"; +@import "styles/loading.less"; +@import "styles/messages.less"; +@import "styles/modals.less"; +@import "styles/panels.less"; +@import "styles/select-list.less"; +@import "styles/site-colors.less"; +@import "styles/text.less"; +@import "styles/tooltip.less"; diff --git a/static/atom-ui/styles/badges.less b/static/atom-ui/styles/badges.less new file mode 100644 index 000000000..bdb39de76 --- /dev/null +++ b/static/atom-ui/styles/badges.less @@ -0,0 +1,65 @@ +@import "ui-variables"; + +.badge { + display: inline-block; + line-height: 1; + vertical-align: middle; + font-weight: normal; + text-align: center; + white-space: nowrap; + border-radius: 1em; + + &:empty { + display: none; // Hide when un-used + } + + + // Color ---------------------- + + .badge-color( @fg: @text-color-selected; + @bg: @background-color-selected; ) { + color: @fg; + background-color: @bg; + } + .badge-color(); + &.badge-info { .badge-color(white, @background-color-info); } + &.badge-success { .badge-color(white, @background-color-success); } + &.badge-warning { .badge-color(white, @background-color-warning); } + &.badge-error { .badge-color(white, @background-color-error); } + + + // Size ---------------------- + + .badge-size( @size: @font-size; ) { + @padding: round(@size/4); + font-size: @size; + min-width: @size + @padding*2; + padding: @padding round(@padding*1.5); + } + .badge-size(); // default + + // Fixed size + &.badge-large { .badge-size(18px); } + &.badge-medium { .badge-size(14px); } + &.badge-small { .badge-size(10px); } + + // Flexible size + // The size changes depending on the parent element + // Best used for larger sizes, since em's can cause rounding errors + &.badge-flexible { + @size: .8em; + @padding: @size/2; + font-size: @size; + min-width: @size + @padding*2; + padding: @padding @padding*1.5; + } + + + // Icon ---------------------- + + &.icon { + font-size: round(@component-icon-size*0.8); + padding: @component-icon-padding @component-icon-padding*2; + } + +} diff --git a/static/atom-ui/styles/button-groups.less b/static/atom-ui/styles/button-groups.less new file mode 100644 index 000000000..430522071 --- /dev/null +++ b/static/atom-ui/styles/button-groups.less @@ -0,0 +1,187 @@ +@import "variables/variables"; +@import "ui-variables"; +@import "mixins/mixins"; + +// +// Button groups +// -------------------------------------------------- + +// Make the div behave like a button +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; // match .btn alignment given font-size hack above + > .btn { + position: relative; + float: left; + // Bring the "active" button to the front + &:hover, + &:focus, + &:active, + &.active { + z-index: 2; + } + } +} + + +// Borders +// --------------------------------------------------------- + +.btn-group > .btn { + border-left: 1px solid @button-border-color; + border-right: 1px solid @button-border-color; +} +.btn-group > .btn:first-child { + border-left: none; + border-top-left-radius: @component-border-radius; + border-bottom-left-radius: @component-border-radius; +} +.btn-group > .btn:last-child, +.btn-group > .btn.selected:last-child, +.btn-group > .dropdown-toggle { + border-right: none; + border-top-right-radius: @component-border-radius; + border-bottom-right-radius: @component-border-radius; +} + +// Prevent double borders when buttons are next to each other +.btn-group { + .btn + .btn, + .btn + .btn-group, + .btn-group + .btn, + .btn-group + .btn-group { + margin-left: -1px; + } +} + +// Optional: Group multiple button groups together for a toolbar +.btn-toolbar { + margin-left: -5px; // Offset the first child's margin + &:extend(.clearfix all); + + .btn, + .btn-group, + .input-group { + float: left; + } + > .btn, + > .btn-group, + > .input-group { + margin-left: 5px; + } +} + +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} + +// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match +.btn-group > .btn:first-child { + margin-left: 0; + &:not(:last-child):not(.dropdown-toggle) { + .border-right-radius(0); + } +} +// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + .border-left-radius(0); +} + +// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group) +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) { + > .btn:last-child, + > .dropdown-toggle { + .border-right-radius(0); + } +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + .border-left-radius(0); +} + +// On active and open, don't show outline +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} + + +// Sizing +// +// Remix the default button sizing classes into new ones for easier manipulation. + +.btn-group-xs > .btn { &:extend(.btn-xs); } +.btn-group-sm > .btn { &:extend(.btn-sm); } +.btn-group-lg > .btn { &:extend(.btn-lg); } + + +// Split button dropdowns +// ---------------------- + +// Give the line between buttons some depth +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} + +// The clickable button for toggling the menu +// Remove the gradient and set the same inset shadow as the :active state +.btn-group.open .dropdown-toggle { + box-shadow: inset 0 3px 5px rgba(0,0,0,.125); + + // Show no shadow for `.btn-link` since it has no other button styles. + &.btn-link { + box-shadow: none; + } +} + + +// Reposition the caret +.btn .caret { + margin-left: 0; +} +// Carets in other button sizes +.btn-lg .caret { + border-width: @caret-width-large @caret-width-large 0; + border-bottom-width: 0; +} +// Upside down carets for .dropup +.dropup .btn-lg .caret { + border-width: 0 @caret-width-large @caret-width-large; +} + + +// Justified button groups +// ---------------------- + +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; + > .btn, + > .btn-group { + float: none; + display: table-cell; + width: 1%; + } + > .btn-group .btn { + width: 100%; + } + + > .btn-group .dropdown-menu { + left: auto; + } +} diff --git a/static/atom-ui/styles/buttons.less b/static/atom-ui/styles/buttons.less new file mode 100644 index 000000000..5f5c35d9b --- /dev/null +++ b/static/atom-ui/styles/buttons.less @@ -0,0 +1,274 @@ +@import "variables/variables"; +@import "ui-variables"; +@import "mixins/mixins"; + +// +// Buttons +// -------------------------------------------------- + + +// Base styles +// -------------------------------------------------- + +.btn { + display: inline-block; + margin-bottom: 0; // For input.btn + height: @component-line-height + 2px; + padding: 0 @component-padding; + font-size: @font-size; + font-weight: normal; + line-height: @component-line-height; + text-align: center; + vertical-align: middle; + border: none; + border-radius: @component-border-radius; + background-color: @btn-default-bg; + white-space: nowrap; + cursor: pointer; + z-index: 0; + -webkit-user-select: none; + + &, + &:active, + &.active { + &:focus, + &.focus { + .tab-focus(); + } + } + + &:hover, + &:focus, + &.focus { + color: @btn-default-color; + text-decoration: none; + background-color: @button-background-color-hover; + } + + &:active, + &.active { + outline: 0; + background-image: none; + box-shadow: inset 0 3px 5px rgba(0,0,0,.125); + } + + &.selected, + &.selected:hover { + // we want the selected button to behave like the :hover button; it's on top of the other buttons. + z-index: 1; + color: @text-color-selected; + background-color: @button-background-color-selected; + } + + &.disabled, + &[disabled], + fieldset[disabled] & { + cursor: @cursor-disabled; + opacity: .65; + box-shadow: none; + } + + a& { + &.disabled, + fieldset[disabled] & { + pointer-events: none; // Future-proof disabling of clicks on `` elements + } + } +} + + +// Button variants +// -------------------------------------------------- + +.button-variant(@color; @background;) { + color: @color; + background-color: @background; + + &:focus, + &.focus { + color: @color; + background-color: darken(@background, 10%); + } + &:hover { + color: @color; + background-color: darken(@background, 10%); + } + &:active, + &.active { + color: @color; + background-color: darken(@background, 10%); + + &:hover, + &:focus, + &.focus { + color: @color; + background-color: darken(@background, 17%); + } + } + &.selected, + &.selected:hover { + // we want the selected button to behave like the :hover button; it's on top of the other buttons. + z-index: 1; + background-color: darken(@background, 10%); + } + + &.disabled, + &[disabled], + fieldset[disabled] & { + &:hover, + &:focus, + &.focus { + background-color: @background; + } + } + + .badge { + color: @background; + background-color: @color; + } +} + +.btn-primary { + .button-variant(@btn-primary-color; @btn-primary-bg;); +} +// Success appears as green +.btn-success { + .button-variant(@btn-success-color; @btn-success-bg;); +} +// Info appears as blue-green +.btn-info { + .button-variant(@btn-info-color; @btn-info-bg;); +} +// Warning appears as orange +.btn-warning { + .button-variant(@btn-warning-color; @btn-warning-bg;); +} +// Danger and error appear as red +.btn-error { + .button-variant(@btn-error-color; @btn-error-bg;); +} + + +// Button Sizes +// -------------------------------------------------- + +.btn-xs, +.btn-group-xs > .btn { + padding: @component-padding/4 @component-padding/2; + font-size: @font-size - 2px; + height: auto; + line-height: 1.3em; + &.icon:before { + font-size: @font-size - 2px; + } +} +.btn-sm, +.btn-group-sm > .btn { + padding: @component-padding/4 @component-padding/2; + height: auto; + line-height: 1.3em; + &.icon:before { + font-size: @font-size + 1px; + } +} +.btn-lg, +.btn-group-lg > .btn { + font-size: @font-size + 2px; + padding: @component-padding - 2px @component-padding + 2px; + height: auto; + line-height: 1.3em; + &.icon:before { + font-size: @font-size + 6px; + } +} + + +// Link button +// ------------------------- + +// Make a button look and behave like a link +.btn-link { + color: @link-color; + font-weight: normal; + border-radius: 0; + &, + &:active, + &.active, + &[disabled], + fieldset[disabled] & { + background-color: transparent; + box-shadow: none; + } + &:hover, + &:focus { + color: @link-hover-color; + text-decoration: @link-hover-decoration; + background-color: transparent; + } + &[disabled], + fieldset[disabled] & { + &:hover, + &:focus { + color: @btn-link-disabled-color; + text-decoration: none; + } + } +} + + +// Block button +// -------------------------------------------------- + +.btn-block { + display: block; + width: 100%; +} + +// Vertically space out multiple block buttons +.btn-block + .btn-block { + margin-top: 5px; +} + +// Specificity overrides +input[type="submit"], +input[type="reset"], +input[type="button"] { + &.btn-block { + width: 100%; + } +} + + +// Icon buttons +// -------------------------------------------------- + +.btn.icon { + &:before { + width: initial; + height: initial; + margin-right: .3125em; + } + &:empty:before { + margin-right: 0; + } +} + + +// Button Toolbar +// -------------------------------------------------- + +.btn-toolbar { + > .btn-group + .btn-group, + > .btn-group + .btn, + > .btn + .btn { + float: none; + display: inline-block; + margin-left: 0; + } + > * { + margin-right: @component-padding / 2; + } + > *:last-child { + margin-right: 0; + } +} diff --git a/static/atom-ui/styles/git-status.less b/static/atom-ui/styles/git-status.less new file mode 100644 index 000000000..ead7ed73d --- /dev/null +++ b/static/atom-ui/styles/git-status.less @@ -0,0 +1,13 @@ +@import "ui-variables"; + +// +// Git Status +// -------------------------------------------------- + +.status { + &-ignored { color: @text-color-subtle; } + &-added { color: @text-color-success; } + &-modified { color: @text-color-warning; } + &-removed { color: @text-color-error; } + &-renamed { color: @text-color-info; } +} diff --git a/static/atom-ui/styles/icons.less b/static/atom-ui/styles/icons.less new file mode 100644 index 000000000..993ba28f8 --- /dev/null +++ b/static/atom-ui/styles/icons.less @@ -0,0 +1,13 @@ +@import "ui-variables"; + +.icon::before { + margin-right: @component-icon-padding; +} + +a.icon { + text-decoration: none; + color: @text-color; + &:hover{ + color: @text-color-highlight; + } +} diff --git a/static/atom-ui/styles/inputs.less b/static/atom-ui/styles/inputs.less new file mode 100644 index 000000000..6d42c3d62 --- /dev/null +++ b/static/atom-ui/styles/inputs.less @@ -0,0 +1,382 @@ +@import "ui-variables"; + +@component-size: @component-icon-size; // use for text-less controls like radio, checkboxes etc. +@component-margin-side: .3em; +@text-component-height: 2em; +@component-background-color: mix(@text-color, @base-background-color, 20%); + + +// +// Overrides +// ------------------------- + +input.input-radio, +input.input-checkbox, +input.input-toggle { + margin-top: 0; // Override Bootstrap's 4px +} +.input-label { + margin-bottom: 0; +} + +// +// Mixins +// ------------------------- + +.input-field-mixin() { + padding: .25em .4em; + line-height: 1.5; // line-height + padding = @text-component-height + border-radius: @component-border-radius; + border: 1px solid @input-border-color; + background-color: @input-background-color; + &::-webkit-input-placeholder { + color: @text-color-subtle; + } + &:invalid { + color: @text-color-error; + border-color: @background-color-error; + } +} + +.input-block-mixin() { + display: block; + width: 100%; +} + + +// +// Checkbox +// ------------------------- + +.input-checkbox { + vertical-align: middle; + + & when (@use-custom-controls) { + -webkit-appearance: none; + display: inline-block; + position: relative; + width: @component-size; + height: @component-size; + font-size: inherit; + border-radius: @component-border-radius; + background-color: @component-background-color; + transition: background-color .16s cubic-bezier(0.5, 0.15, 0.2, 1); + + &&:focus { + outline: 0; // TODO: Add it back + } + &:active { + background-color: @background-color-info; + } + + &:before, + &:after { + content: ""; + position: absolute; + top: @component-size * .75; + left: @component-size * .4; + height: 2px; + border-radius: 1px; + background-color: @base-background-color; + transform-origin: 0 0; + opacity: 0; + transition: transform .1s cubic-bezier(0.5, 0.15, 0.2, 1), opacity .1s cubic-bezier(0.5, 0.15, 0.2, 1); + } + &:before { + width: @component-size * .33; + transform: translate3d(0,0,0) rotate(225deg) scale(0); + } + &:after { + width: @component-size * .66; + margin: -1px; + transform: translate3d(0,0,0) rotate(-45deg) scale(0); + transition-delay: .05s; + } + + &:checked { + background-color: @background-color-info; + &:active { + background-color: @component-background-color; + } + &:before { + opacity: 1; + transform: translate3d(0,0,0) rotate(225deg) scale(1); + transition-delay: .05s; + } + &:after { + opacity: 1; + transform: translate3d(0, 0, 0) rotate(-45deg) scale(1); + transition-delay: 0; + } + } + + &:indeterminate { + background-color: @background-color-info; + &:active { + background-color: @component-background-color; + } + &:after { + opacity: 1; + transform: translate3d(@component-size * -.14, @component-size * -.25, 0) rotate(0deg) scale(1); + transition-delay: 0; + } + } + } +} + + +// +// Color +// ------------------------- + + +.input-color { + vertical-align: middle; + + & when (@use-custom-controls) { + -webkit-appearance: none; + padding: 0; + width: @component-size * 2.5; + height: @component-size * 2.5; + border-radius: 50%; + border: 2px solid @input-border-color; + background-color: @input-background-color; + &::-webkit-color-swatch-wrapper { padding: 0; } + &::-webkit-color-swatch { + border: 1px solid hsla(0,0%,0%,.1); + border-radius: 50%; + transition: transform .16s cubic-bezier(0.5, 0.15, 0.2, 1); + &:active { + transition-duration: 0s; + transform: scale(.9); + } + } + } +} + + + +// +// Label +// ------------------------- + +.input-label { + .input-radio, + .input-checkbox, + .input-toggle { + margin-top: -.25em; // Vertical center (visually) - since most labels are upper case. + margin-right: @component-margin-side; + } +} + + +// +// Number +// ------------------------- + +.input-number { + vertical-align: middle; + + & when (@use-custom-controls) { + .input-field-mixin(); + position: relative; + width: auto; + .platform-darwin & { + padding-right: 1.2em; // space for the spin button + &::-webkit-inner-spin-button { + -webkit-appearance: menulist-button; + position: absolute; + top: 1px; + bottom: 1px; + right: 1px; + width: calc(.6em ~'+' 9px); // magic numbers, OMG! + outline: 1px solid @input-background-color; + outline-offset: -1px; // reduces border radius (that can't be changed) + border-right: .2em solid @background-color-highlight; // a bit more padding + background-color: @background-color-highlight; + transition: transform .16s cubic-bezier(0.5, 0.15, 0.2, 1); + &:active { + transform: scale(.9); + transition-duration: 0s; + } + } + } + } +} + + +// +// Radio +// ------------------------- + +.input-radio { + vertical-align: middle; + + & when (@use-custom-controls) { + -webkit-appearance: none; + display: inline-block; + position: relative; + width: @component-size; + height: @component-size; + font-size: inherit; + border-radius: 50%; + background-color: @component-background-color; + transition: background-color .16s cubic-bezier(0.5, 0.15, 0.2, 1); + + &:before { + content: ""; + position: absolute; + width: inherit; + height: inherit; + border-radius: inherit; + border: @component-size/3 solid transparent; + background-clip: content-box; + background-color: @base-background-color; + transform: scale(0); + transition: transform .1s cubic-bezier(0.5, 0.15, 0.2, 1); + } + &&:focus { + outline: none; + } + &:active { + background-color: @background-color-info; + } + &:checked { + background-color: @background-color-info; + &:before { + transform: scale(1); + } + } + } +} + + +// +// Range (Slider) +// ------------------------- + +.input-range { + & when (@use-custom-controls) { + -webkit-appearance: none; + margin: @component-padding 0; + height: 4px; + border-radius: @component-border-radius; + background-color: @component-background-color; + &::-webkit-slider-thumb { + -webkit-appearance: none; + width: @component-size; + height: @component-size; + border-radius: 50%; + background-color: @background-color-info; + transition: transform .16s; + &:active { + transition-duration: 0s; + transform: scale(.9); + } + } + } +} + + +// +// Search +// ------------------------- + +.input-search { + .input-block-mixin(); + &&::-webkit-search-cancel-button { + -webkit-appearance: searchfield-cancel-button; + } + + & when (@use-custom-controls) { + .input-field-mixin(); + } +} + + +// +// Select +// ------------------------- + +.input-select { + vertical-align: middle; + + & when (@use-custom-controls) { + height: calc(@text-component-height ~'+' 2px); // + 2px? Magic! + border-radius: @component-border-radius; + border: 1px solid @button-border-color; + background-color: @button-background-color; + } +} + + +// +// Text +// ------------------------- + +.input-text { + .input-block-mixin(); + + & when (@use-custom-controls) { + .input-field-mixin(); + } +} + + +// +// Text Area +// ------------------------- + +.input-textarea { + .input-block-mixin(); + + & when (@use-custom-controls) { + .input-field-mixin(); + } +} + + +// +// Toggle +// ------------------------- + +.input-toggle { + & when (@use-custom-controls) { + -webkit-appearance: none; + display: inline-block; + position: relative; + font-size: inherit; + width: @component-size * 2; + height: @component-size; + vertical-align: middle; + border-radius: 2em; + background-color: @component-background-color; + transition: background-color .2s cubic-bezier(0.5, 0.15, 0.2, 1); + + &&:focus { + outline: 0; + } + &:checked { + background-color: @background-color-info; + } + + // Thumb + &:before { + content: ""; + position: absolute; + width: @component-size; + height: @component-size; + border-radius: inherit; + border: @component-size/4 solid transparent; + background-clip: content-box; + background-color: @base-background-color; + transition: transform .2s cubic-bezier(0.5, 0.15, 0.2, 1); + } + &:active:before { + opacity: .5; + } + &:checked:before { + transform: translate3d(100%, 0, 0); + } + } +} diff --git a/static/atom-ui/styles/layout.less b/static/atom-ui/styles/layout.less new file mode 100644 index 000000000..83560fab9 --- /dev/null +++ b/static/atom-ui/styles/layout.less @@ -0,0 +1,85 @@ +@import "ui-variables"; +@import "mixins/mixins"; + +.padded { + padding: @component-padding; +} + +// Blocks + +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} + +// Must be div.block so as not to affect syntax highlighting. +ul.block, +div.block { + margin-bottom: @component-padding; +} +div > ul.block:last-child, +div > div.block:last-child { + margin-bottom: 0; +} + +// Inline Blocks + +.inline-block, +.inline-block-tight { + display: inline-block; + vertical-align: middle; +} +.inline-block { + margin-right: @component-padding; +} +.inline-block-tight { + margin-right: @component-padding/2; +} +div > .inline-block:last-child, +div > .inline-block-tight:last-child { + margin-right: 0; +} + +.inline-block .inline-block { + vertical-align: top; +} + +// Centering +// ------------------------- + +.pull-center { + margin-left: auto; + margin-right: auto; +} + +// Floats +// ------------------------- + +// Use left margin when it's in a float: right element. +// Sets the margin correctly when inline blocks are hidden and shown. +.pull-right { + float: right !important; + + .inline-block { + margin-right: 0; + margin-left: @component-padding; + } + .inline-block-tight { + margin-right: 0; + margin-left: @component-padding/2; + } + + > .inline-block:first-child, + > .inline-block-tight:first-child { + margin-left: 0; + } +} + +.pull-left { + float: left !important; +} + +.clearfix { + .clearfix(); +} diff --git a/static/atom-ui/styles/lists.less b/static/atom-ui/styles/lists.less new file mode 100644 index 000000000..d8a32d919 --- /dev/null +++ b/static/atom-ui/styles/lists.less @@ -0,0 +1,291 @@ +@import "variables/variables"; +@import "ui-variables"; +@import "mixins/mixins"; + +@import "octicon-mixins"; + +// +// List options +// -------------------------------------------------- + +// Unstyled keeps list items block level, just removes default browser padding and list-style +.list-unstyled { + padding-left: 0; + list-style: none; +} + +// Inline turns list items into inline-block +.list-inline { + .list-unstyled(); + margin-left: -5px; + + > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; + } +} + + +// +// List groups +// -------------------------------------------------- + +// Mixins + +.list-group-item-variant(@state; @background; @color) { + .list-group-item-@{state} { + color: @color; + background-color: @background; + + a&, + button& { + color: @color; + + .list-group-item-heading { + color: inherit; + } + + &:hover, + &:focus { + color: @color; + background-color: darken(@background, 5%); + } + &.active, + &.active:hover, + &.active:focus { + color: #fff; + background-color: @color; + border-color: @color; + } + } + } +} + + + +// Individual list items +// +// Use on `li`s or `div`s within the `.list-group` parent. + +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + // Place the border on the list items and negative margin up for better styling + margin-bottom: -1px; + background-color: @list-group-bg; + border: 1px solid @list-group-border; + + // Round the first and last items + &:first-child { + .border-top-radius(@list-group-border-radius); + } + &:last-child { + margin-bottom: 0; + .border-bottom-radius(@list-group-border-radius); + } +} + + +// Interactive list items +// +// Use anchor or button elements instead of `li`s or `div`s to create interactive items. +// Includes an extra `.active` modifier class for showing selected items. + +a.list-group-item, +button.list-group-item { + color: @list-group-link-color; + + .list-group-item-heading { + color: @list-group-link-heading-color; + } + + // Hover state + &:hover, + &:focus { + text-decoration: none; + color: @list-group-link-hover-color; + background-color: @list-group-hover-bg; + } +} + +button.list-group-item { + width: 100%; + text-align: left; +} + +.list-group-item { + // Disabled state + &.disabled, + &.disabled:hover, + &.disabled:focus { + background-color: @list-group-disabled-bg; + color: @list-group-disabled-color; + cursor: @cursor-disabled; + + // Force color to inherit for custom content + .list-group-item-heading { + color: inherit; + } + .list-group-item-text { + color: @list-group-disabled-text-color; + } + } + + // Active class on item itself, not parent + &.active, + &.active:hover, + &.active:focus { + z-index: 2; // Place active items above their siblings for proper border styling + color: @list-group-active-color; + background-color: @list-group-active-bg; + border-color: @list-group-active-border; + + // Force color to inherit for custom content + .list-group-item-heading, + .list-group-item-heading > small, + .list-group-item-heading > .small { + color: inherit; + } + .list-group-item-text { + color: @list-group-active-text-color; + } + } +} + + +// Contextual variants +// +// Add modifier classes to change text and background color on individual items. +// Organizationally, this must come after the `:hover` states. + +.list-group-item-variant(success; @state-success-bg; @state-success-text); +.list-group-item-variant(info; @state-info-bg; @state-info-text); +.list-group-item-variant(warning; @state-warning-bg; @state-warning-text); +.list-group-item-variant(danger; @state-danger-bg; @state-danger-text); + + +// Custom content options +// +// Extra classes for creating well-formatted content within `.list-group-item`s. + +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} + + + +// This is a bootstrap override +// --------------------------------------------- + +.list-group, +.list-group .list-group-item { + background-color: transparent; + border: none; + padding: 0; + margin: 0; + position: static; +} + +.list-group, +.list-tree { + margin: 0; + padding: 0; + list-style: none; + cursor: default; + + li:not(.list-nested-item), + li.list-nested-item > .list-item { + line-height: @component-line-height; + text-wrap: none; + white-space: nowrap; + } + + // The background highlight uses ::before rather than the item background so + // it can span the entire width of the parent container rather than the size + // of the list item. + .selected::before { + content: ''; + background-color: @background-color-selected; + position: absolute; + left: 0; + right: 0; + height: @component-line-height; + } + + // Make sure the background highlight is below the content. + .selected > * { + position: relative; + } + + .icon::before { + margin-right: @component-icon-padding; + position: relative; + top: 1px; + } + .no-icon { + padding-left: @component-icon-padding + @component-icon-size; + } +} + + + +// +// List Tree +// -------------------------------------------------- + +// Handle indentation of the tree. Assume disclosure arrows. + +.list-tree { + .list-nested-item > .list-tree > li, + .list-nested-item > .list-group > li { + padding-left: @component-icon-size + @component-icon-padding; + } + + &.has-collapsable-children { + @disclosure-arrow-padding: @disclosure-arrow-size + @component-icon-padding; + li.list-item { + margin-left: @disclosure-arrow-padding; + } + + .list-nested-item.collapsed > .list-group, + .list-nested-item.collapsed > .list-tree { + display: none; + } + + // Nested items always get disclosure arrows + .list-nested-item > .list-item { + .octicon(chevron-down, @disclosure-arrow-size); + &::before{ + position: relative; + top: -1px; + margin-right: @component-icon-padding; + } + } + .list-nested-item.collapsed > .list-item { + .octicon(chevron-right, @disclosure-arrow-size); + &::before{ + left: 1px; + } + } + + .list-nested-item > .list-tree > li, + .list-nested-item > .list-group > li { + padding-left: @disclosure-arrow-padding; + } + + // You want a subtree to be flat -- no collapsable children + .has-flat-children, + &.has-flat-children { + li.list-item { + margin-left: 0; + } + } + } +} diff --git a/static/atom-ui/styles/loading.less b/static/atom-ui/styles/loading.less new file mode 100644 index 000000000..dff5b1782 --- /dev/null +++ b/static/atom-ui/styles/loading.less @@ -0,0 +1,21 @@ +// +// Loading +// -------------------------------------------------- + +.loading-spinner(@size) { + display: block; + width: @size; + height: @size; + background-image: url(images/octocat-spinner-128.gif); + background-repeat: no-repeat; + background-size: cover; + + &.inline-block { + display: inline-block; + } +} + +.loading-spinner-tiny { .loading-spinner(16px); } +.loading-spinner-small { .loading-spinner(32px); } +.loading-spinner-medium { .loading-spinner(48px); } +.loading-spinner-large { .loading-spinner(64px); } diff --git a/static/atom-ui/styles/messages.less b/static/atom-ui/styles/messages.less new file mode 100644 index 000000000..a679c92cb --- /dev/null +++ b/static/atom-ui/styles/messages.less @@ -0,0 +1,41 @@ +@import "ui-variables"; + +.info-messages, +.error-messages { + margin: 0; + padding: 0; + list-style: none; +} + +.error-messages { + color: @text-color-error; +} + +ul.background-message { + font-size: @font-size * 3; + + margin: 0; + padding: 0; + + li { + margin: 0; + padding: 0; + list-style: none; + } + + &.centered { + display: flex; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + + align-items: center; + text-align: center; + + li { + width: 100%; + } + } +} diff --git a/static/atom-ui/styles/mixins/mixins.less b/static/atom-ui/styles/mixins/mixins.less new file mode 100644 index 000000000..0328894f2 --- /dev/null +++ b/static/atom-ui/styles/mixins/mixins.less @@ -0,0 +1,87 @@ + +// Core mixins +// ---------------------------------------- + +// Focus +// +.tab-focus() { + outline: 2px auto @text-color-info; + outline-offset: -2px; +} + + +// Border-radius +// +.border-top-radius(@radius) { + border-top-right-radius: @radius; + border-top-left-radius: @radius; +} +.border-right-radius(@radius) { + border-bottom-right-radius: @radius; + border-top-right-radius: @radius; +} +.border-bottom-radius(@radius) { + border-bottom-right-radius: @radius; + border-bottom-left-radius: @radius; +} +.border-left-radius(@radius) { + border-bottom-left-radius: @radius; + border-top-left-radius: @radius; +} + + +// Clearfix +// +// For modern browsers +// 1. The space content is one way to avoid an Opera bug when the +// contenteditable attribute is included anywhere else in the document. +// Otherwise it causes space to appear at the top and bottom of elements +// that are clearfixed. +// 2. The use of `table` rather than `block` is only necessary if using +// `:before` to contain the top-margins of child elements. +// +// Source: http://nicolasgallagher.com/micro-clearfix-hack/ + +.clearfix() { + &:before, + &:after { + content: " "; // 1 + display: table; // 2 + } + &:after { + clear: both; + } +} + + +// CSS image replacement +// +// Heads up! v3 launched with only `.hide-text()`, but per our pattern for +// mixins being reused as classes with the same name, this doesn't hold up. As +// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`. +// +// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757 + +// Deprecated as of v3.0.1 (has been removed in v4) +.hide-text() { + font: ~"0/0" a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +// New mixin to use as of v3.0.1 +.text-hide() { + .hide-text(); +} + + +// Text overflow +// Requires inline-block or block for proper styling + +.text-overflow() { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} diff --git a/static/atom-ui/styles/modals.less b/static/atom-ui/styles/modals.less new file mode 100644 index 000000000..781c1c3d6 --- /dev/null +++ b/static/atom-ui/styles/modals.less @@ -0,0 +1,82 @@ + +// +// Modals +// -------------------------------------------------- + +.overlay, // deprecated .overlay +atom-panel.modal { + position: absolute; + display: block; + top: 0; + left: 50%; + width: 500px; + margin-left: -250px; + z-index: 9999; + box-sizing: border-box; + border-top: none; + border-top-left-radius: 0; + border-top-right-radius: 0; + + color: @text-color; + background-color: @overlay-background-color; + + padding: 10px; + + // shrink modals when window gets narrow + @media (max-width: 500px) { + & { + width: 100%; + left: 0; + margin-left: 0; + } + } + + h1 { + margin-top: 0; + color: @text-color-highlight; + font-size: 1.6em; + font-weight: bold; + } + + h2 { + font-size: 1.3em; + } + + atom-text-editor[mini] { + margin-bottom: 10px; + } + + .message { + padding-top: 5px; + font-size: 11px; + } + + &.mini { + width: 200px; + margin-left: -100px; + font-size: 12px; + } +} + + +// Deprecated: overlay, from-top, from-bottom, floating +// -------------------------------------------------- +// TODO: Remove these! + +.overlay.from-top { + top: 0; + border-top: none; + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.overlay.from-bottom { + bottom: 0; + border-bottom: none; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +.overlay.floating { + left: auto; +} diff --git a/static/atom-ui/styles/panels.less b/static/atom-ui/styles/panels.less new file mode 100644 index 000000000..c0fe906f6 --- /dev/null +++ b/static/atom-ui/styles/panels.less @@ -0,0 +1,36 @@ +// +// Panels +// -------------------------------------------------- + +.tool-panel, // deprecated: .tool-panel +.panel, // deprecated: .panel +atom-panel { + background-color: @tool-panel-background-color; +} + +.inset-panel { + border-radius: @component-border-radius; + background-color: @inset-panel-background-color; +} + +.panel-heading { + margin: 0; + padding: @component-padding; + border-radius: 0; + font-size: @font-size; + line-height: 1; + background-color: @panel-heading-background-color; + + .inset-panel & { + border-radius: @component-border-radius @component-border-radius 0 0; + } + + .btn { + @btn-height: @component-line-height - 5px; + height: @btn-height; + line-height: @btn-height; + font-size: @font-size - 2px; + position: relative; + top: -5px; + } +} diff --git a/static/atom-ui/styles/private/README.md b/static/atom-ui/styles/private/README.md new file mode 100644 index 000000000..a383db448 --- /dev/null +++ b/static/atom-ui/styles/private/README.md @@ -0,0 +1,5 @@ +# Private components + +> Private! Don't use these in packages. + +If you need something, feel free to open an issue and it might can be made public. diff --git a/static/atom-ui/styles/private/alerts.less b/static/atom-ui/styles/private/alerts.less new file mode 100644 index 000000000..cc32a8c8c --- /dev/null +++ b/static/atom-ui/styles/private/alerts.less @@ -0,0 +1,114 @@ +@import "../variables/variables"; +@import "ui-variables"; + +// +// Alerts +// -------------------------------------------------- + +//## Define alert colors, border radius, and padding. + +@alert-padding: 15px; +@alert-border-radius: @border-radius-base; +@alert-link-font-weight: bold; + +@alert-success-bg: @state-success-bg; +@alert-success-text: @state-success-text; +@alert-success-border: @state-success-border; + +@alert-info-bg: @state-info-bg; +@alert-info-text: @state-info-text; +@alert-info-border: @state-info-border; + +@alert-warning-bg: @state-warning-bg; +@alert-warning-text: @state-warning-text; +@alert-warning-border: @state-warning-border; + +@alert-danger-bg: @state-danger-bg; +@alert-danger-text: @state-danger-text; +@alert-danger-border: @state-danger-border; + + +//## variant mixin + +.alert-variant(@background; @border; @text-color) { + background-color: @background; + border-color: @border; + color: @text-color; + + hr { + border-top-color: darken(@border, 5%); + } + .alert-link { + color: darken(@text-color, 10%); + } +} + + +// Base styles +// ------------------------- + +.alert { + padding: @alert-padding; + margin-bottom: @line-height-computed; + border: 1px solid transparent; + border-radius: @alert-border-radius; + + // Headings for larger alerts + h4 { + margin-top: 0; + // Specified for the h4 to prevent conflicts of changing @headings-color + color: inherit; + } + + // Provide class for links that match alerts + .alert-link { + font-weight: @alert-link-font-weight; + } + + // Improve alignment and spacing of inner content + > p, + > ul { + margin-bottom: 0; + } + + > p + p { + margin-top: 5px; + } +} + +// Dismissible alerts +// +// Expand the right padding and account for the close button's positioning. + +.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0. +.alert-dismissible { + padding-right: (@alert-padding + 20); + + // Adjust close link position + .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; + } +} + +// Alternate styles +// +// Generate contextual modifier classes for colorizing the alert. + +.alert-success { + .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text); +} + +.alert-info { + .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text); +} + +.alert-warning { + .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text); +} + +.alert-danger { + .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text); +} diff --git a/static/atom-ui/styles/private/close.less b/static/atom-ui/styles/private/close.less new file mode 100644 index 000000000..9befb2e9d --- /dev/null +++ b/static/atom-ui/styles/private/close.less @@ -0,0 +1,38 @@ +// +// Close icon (deprecated) +// -------------------------------------------------- + +.close { + @font-size-base: 14px; + @close-font-weight: bold; + @close-color: #000; + @close-text-shadow: 0 1px 0 #fff; + + float: right; + font-size: (@font-size-base * 1.5); + font-weight: @close-font-weight; + line-height: 1; + color: @close-color; + text-shadow: @close-text-shadow; + opacity: .2; + + &:hover, + &:focus { + color: @close-color; + text-decoration: none; + cursor: pointer; + opacity: .5; + } + + // Additional properties for button version + // iOS requires the button element instead of an anchor tag. + // If you want the anchor version, it requires `href="#"`. + // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile + button& { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; + } +} diff --git a/static/atom-ui/styles/private/code.less b/static/atom-ui/styles/private/code.less new file mode 100644 index 000000000..a657ca70e --- /dev/null +++ b/static/atom-ui/styles/private/code.less @@ -0,0 +1,77 @@ +@import "../variables/variables"; +@import "ui-variables"; + +// +// Code (inline and block) +// -------------------------------------------------- + +@code-color: @text-color-highlight; +@code-bg: @background-color-highlight; + +@pre-color: @code-color; +@pre-bg: @code-bg; +@pre-border-color: @base-border-color; +@pre-scrollable-max-height: 340px; + +// Inline and block code styles +code, +kbd, +pre, +samp { + font-family: @font-family-monospace; +} + +// Inline code +code { + padding: 2px 4px; + font-size: 90%; + color: @code-color; + background-color: @code-bg; + border-radius: @border-radius-base; +} + +// User input typically entered via keyboard +kbd { + padding: 2px 4px; + font-size: 90%; + color: @code-color; + background-color: @code-bg; + border-radius: @border-radius-small; + + kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + } +} + +// Blocks of code +pre { + display: block; + padding: ((@line-height-computed - 1) / 2); + margin: 0 0 (@line-height-computed / 2); + font-size: (@font-size-base - 1); // 14px to 13px + line-height: @line-height-base; + word-break: break-all; + word-wrap: break-word; + color: @pre-color; + background-color: @pre-bg; + border: 1px solid @pre-border-color; + border-radius: @border-radius-base; + + // Account for some code outputs that place code tags in pre tags + code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; + } +} + +// Enable scrollable blocks of code +.pre-scrollable { + max-height: @pre-scrollable-max-height; + overflow-y: scroll; +} diff --git a/static/atom-ui/styles/private/forms.less b/static/atom-ui/styles/private/forms.less new file mode 100644 index 000000000..c0172bb0d --- /dev/null +++ b/static/atom-ui/styles/private/forms.less @@ -0,0 +1,705 @@ +@import "../variables/variables"; +@import "ui-variables"; +@import "../mixins/mixins"; + +// +// Forms +// -------------------------------------------------- + + +@input-bg: #fff; //** `` background color +@input-bg-disabled: @gray-lighter; //** `` background color +@input-color: @gray; //** Text color for ``s +@input-border: #ccc; //** `` border color + +// TODO: Rename `@input-border-radius` to `@input-border-radius-base` in v4 +//** Default `.form-control` border radius +// This has no effect on ``s in CSS. +@input-border-radius: @border-radius-base; //** Large `.form-control` border radius +@input-border-radius-large: @border-radius-large; //** Small `.form-control` border radius +@input-border-radius-small: @border-radius-small; +@input-border-focus: #66afe9; //** Border color for inputs on focus +@input-color-placeholder: #999; //** Placeholder text color +@input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2); //** Default `.form-control` height +@input-height-large: (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2); //** Large `.form-control` height +@input-height-small: (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2); //** Small `.form-control` height + +@form-group-margin-bottom: 15px; //** `.form-group` margin + +@legend-color: @gray-dark; +@legend-border-color: #e5e5e5; + +@input-group-addon-bg: @gray-lighter; //** Background color for textual input addons +@input-group-addon-border-color: @input-border; //** Border color for textual input addons + +@cursor-disabled: not-allowed; //** Disabled cursor for form controls and buttons. + +@grid-gutter-width: 30px; //** Padding between columns. Gets divided in half for the left and right. + + +// Form validation states +// +// Used in forms.less to generate the form validation CSS for warnings, errors, +// and successes. + +.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) { + // Color the label and help text + .help-block, + .control-label, + .radio, + .checkbox, + .radio-inline, + .checkbox-inline, + &.radio label, + &.checkbox label, + &.radio-inline label, + &.checkbox-inline label { + color: @text-color; + } + // Set the border and box shadow on specific inputs to match + .form-control { + border-color: @border-color; + box-shadow: inset 0 1px 1px rgba(0,0,0,.075); // Redeclare so transitions work + &:focus { + border-color: darken(@border-color, 10%); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%); + } + } + // Set validation states also for addons + .input-group-addon { + color: @text-color; + border-color: @border-color; + background-color: @background-color; + } + // Optional feedback icon + .form-control-feedback { + color: @text-color; + } +} + + +// Form control focus state +// +// Generate a customized focus state and for any input with the specified color, +// which defaults to the `@input-border-focus` variable. +// +// We highly encourage you to not customize the default value, but instead use +// this to tweak colors on an as-needed basis. This aesthetic change is based on +// WebKit's default styles, but applicable to a wider range of browsers. Its +// usability and accessibility should be taken into account with any change. +// +// Example usage: change the default blue border and shadow to white for better +// contrast against a dark gray background. +.form-control-focus(@color: @input-border-focus) { + @color-rgba: rgba(red(@color), green(@color), blue(@color), .6); + &:focus { + border-color: @color; + outline: 0; + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @color-rgba; + } +} + +// Form control sizing +// +// Relative text size, padding, and border-radii changes for form controls. For +// horizontal sizing, wrap controls in the predefined grid classes. `s in some browsers, due to the limited stylability of `s in IE10+. + &::-ms-expand { + border: 0; + background-color: transparent; + } + + // Disabled and read-only inputs + // + // HTML5 says that controls under a fieldset > legend:first-child won't be + // disabled if the fieldset is disabled. Due to implementation difficulty, we + // don't honor that edge case; we style them as disabled anyway. + &[disabled], + &[readonly], + fieldset[disabled] & { + background-color: @input-bg-disabled; + opacity: 1; // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655 + } + + &[disabled], + fieldset[disabled] & { + cursor: @cursor-disabled; + } + + // Reset height for `textarea`s + textarea& { + height: auto; + } +} + + +// Form groups +// +// Designed to help with the organization and spacing of vertical forms. For +// horizontal forms, use the predefined grid classes. + +.form-group { + margin-bottom: @form-group-margin-bottom; +} + + +// Checkboxes and radios +// +// Indent the labels to position radios/checkboxes as hanging controls. + +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; + + label { + min-height: @line-height-computed; // Ensure the input doesn't jump when there is no text + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; + } +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-left: -20px; + margin-top: 4px \9; +} + +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing +} + +// Radios and checkboxes on same line +.radio-inline, +.checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; // space out consecutive inline controls +} + +// Apply same disabled cursor tweak as for inputs +// Some special care is needed because