diff --git a/package.json b/package.json index 69eb6ae0e463d2662087fa33458a6d9bc8b72784..93fbd110ecaf43f2c4dd8dc913f588baa82a7b57 100644 --- a/package.json +++ b/package.json @@ -22,13 +22,13 @@ "css": "npm-run-all --parallel css-lint* css-compile* --sequential css-prefix* css-minify*", "css-main": "npm-run-all --parallel css-lint css-compile --sequential css-prefix css-minify", "css-docs": "npm-run-all --parallel css-lint-docs css-compile-docs --sequential css-prefix-docs css-minify-docs", - "css-compile": "node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 scss/bootstrap.scss dist/css/bootstrap.css && node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 scss/bootstrap-grid.scss dist/css/bootstrap-grid.css && node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 scss/bootstrap-reboot.scss dist/css/bootstrap-reboot.css", + "css-compile": "node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 scss/bootstrap.scss dist/css/bootstrap.css && node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 scss/bootstrap-grid.scss dist/css/bootstrap-grid.css && node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 scss/bootstrap-placeholders.scss dist/css/bootstrap-placeholders.css && node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 scss/bootstrap-reboot.scss dist/css/bootstrap-reboot.css", "css-compile-docs": "node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 assets/scss/docs.scss assets/css/docs.min.css", "css-lint": "stylelint --config build/.stylelintrc --syntax scss \"scss/**/*.scss\"", "css-lint-docs": "stylelint --config build/.stylelintrc --syntax scss \"assets/scss/*.scss\" && stylelint --config docs/4.0/examples/.stylelintrc \"docs/**/*.css\"", "css-prefix": "postcss --config build/postcss.config.js --replace \"dist/css/*.css\"", "css-prefix-docs": "postcss --config build/postcss.config.js --replace \"assets/css/docs.min.css\" \"docs/**/*.css\"", - "css-minify": "cleancss --level 1 --source-map --source-map-inline-sources --output dist/css/bootstrap.min.css dist/css/bootstrap.css && cleancss --level 1 --source-map --source-map-inline-sources --output dist/css/bootstrap-grid.min.css dist/css/bootstrap-grid.css && cleancss --level 1 --source-map --source-map-inline-sources --output dist/css/bootstrap-reboot.min.css dist/css/bootstrap-reboot.css", + "css-minify": "cleancss --level 1 --source-map --source-map-inline-sources --output dist/css/bootstrap.min.css dist/css/bootstrap.css && cleancss --level 1 --source-map --source-map-inline-sources --output dist/css/bootstrap-grid.min.css dist/css/bootstrap-grid.css && cleancss --level 1 --source-map --source-map-inline-sources --output dist/css/bootstrap-placeholders.min.css dist/css/bootstrap-placeholders.css && cleancss --level 1 --source-map --source-map-inline-sources --output dist/css/bootstrap-reboot.min.css dist/css/bootstrap-reboot.css", "css-minify-docs": "cleancss --level 1 --source-map --source-map-inline-sources --output assets/css/docs.min.css assets/css/docs.min.css", "js": "npm-run-all js-lint* js-compile* js-minify*", "js-main": "npm-run-all js-lint js-compile js-minify", @@ -64,6 +64,7 @@ }, "style": "dist/css/bootstrap.css", "sass": "scss/bootstrap.scss", + "sass-placeholders": "scss/bootstrap-placeholders.scss", "main": "dist/js/bootstrap", "repository": { "type": "git", @@ -147,6 +148,14 @@ "path": "./dist/css/bootstrap-grid.min.css", "maxSize": "5 kB" }, + { + "path": "./dist/css/bootstrap-placeholders.css", + "maxSize": "215 B" + }, + { + "path": "./dist/css/bootstrap-placeholders.min.css", + "maxSize": "215 B" + }, { "path": "./dist/css/bootstrap-reboot.css", "maxSize": "5 kB" diff --git a/scss/bootstrap-grid.scss b/scss/bootstrap-grid.scss index d7d4e7863d9f9a4debd6fdf477a749142d88fc31..7d3dbb256df66fed0e6e1d5ddd4c757e1a76ac6d 100644 --- a/scss/bootstrap-grid.scss +++ b/scss/bootstrap-grid.scss @@ -31,5 +31,5 @@ html { @import "mixins/grid-framework"; @import "mixins/grid"; -@import "grid"; +@import "components/grid"; @import "utilities/flex"; diff --git a/scss/bootstrap-placeholders.scss b/scss/bootstrap-placeholders.scss new file mode 100644 index 0000000000000000000000000000000000000000..68c216a6906aa18430cc2d9a246f877145d91892 --- /dev/null +++ b/scss/bootstrap-placeholders.scss @@ -0,0 +1,42 @@ +/*! + * Bootstrap v4.0.0-beta.2 (https://getbootstrap.com) + * Copyright 2011-2017 The Bootstrap Authors + * Copyright 2011-2017 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +@import "functions"; +@import "variables"; +@import "mixins"; +//@import "root"; +//@import "print"; +// @import "reboot"; +@import "placeholders/type"; +@import "placeholders/images"; +@import "placeholders/code"; +@import "placeholders/grid"; +// @import "placeholders/tables"; +// @import "placeholders/forms"; +// @import "placeholders/buttons"; +// @import "placeholders/transitions"; +// @import "placeholders/dropdown"; +// @import "placeholders/button-group"; +// @import "placeholders/input-group"; +// @import "placeholders/custom-forms"; +// @import "placeholders/nav"; +// @import "placeholders/navbar"; +// @import "placeholders/card"; +// @import "placeholders/breadcrumb"; +// @import "placeholders/pagination"; +// @import "placeholders/badge"; +// @import "placeholders/jumbotron"; +// @import "placeholders/alert"; +// @import "placeholders/progress"; +// @import "placeholders/media"; +// @import "placeholders/list-group"; +// @import "placeholders/close"; +// @import "placeholders/modal"; +// @import "placeholders/tooltip"; +// @import "placeholders/popover"; +// @import "placeholders/carousel"; +//@import "utilities"; diff --git a/scss/bootstrap.scss b/scss/bootstrap.scss index bfeffacacf7c22b73d6e60949feeebd080e37d8a..f520ff5f766ca240cc8b7b76f2f3111b4c14249f 100644 --- a/scss/bootstrap.scss +++ b/scss/bootstrap.scss @@ -11,32 +11,32 @@ @import "root"; @import "print"; @import "reboot"; -@import "type"; -@import "images"; -@import "code"; -@import "grid"; -@import "tables"; -@import "forms"; -@import "buttons"; -@import "transitions"; -@import "dropdown"; -@import "button-group"; -@import "input-group"; -@import "custom-forms"; -@import "nav"; -@import "navbar"; -@import "card"; -@import "breadcrumb"; -@import "pagination"; -@import "badge"; -@import "jumbotron"; -@import "alert"; -@import "progress"; -@import "media"; -@import "list-group"; -@import "close"; -@import "modal"; -@import "tooltip"; -@import "popover"; -@import "carousel"; +@import "components/type"; +@import "components/images"; +@import "components/code"; +@import "components/grid"; +@import "components/tables"; +@import "components/forms"; +@import "components/buttons"; +@import "components/transitions"; +@import "components/dropdown"; +@import "components/button-group"; +@import "components/input-group"; +@import "components/custom-forms"; +@import "components/nav"; +@import "components/navbar"; +@import "components/card"; +@import "components/breadcrumb"; +@import "components/pagination"; +@import "components/badge"; +@import "components/jumbotron"; +@import "components/alert"; +@import "components/progress"; +@import "components/media"; +@import "components/list-group"; +@import "components/close"; +@import "components/modal"; +@import "components/tooltip"; +@import "components/popover"; +@import "components/carousel"; @import "utilities"; diff --git a/scss/_alert.scss b/scss/components/_alert.scss similarity index 100% rename from scss/_alert.scss rename to scss/components/_alert.scss diff --git a/scss/_badge.scss b/scss/components/_badge.scss similarity index 100% rename from scss/_badge.scss rename to scss/components/_badge.scss diff --git a/scss/_breadcrumb.scss b/scss/components/_breadcrumb.scss similarity index 100% rename from scss/_breadcrumb.scss rename to scss/components/_breadcrumb.scss diff --git a/scss/_button-group.scss b/scss/components/_button-group.scss similarity index 100% rename from scss/_button-group.scss rename to scss/components/_button-group.scss diff --git a/scss/_buttons.scss b/scss/components/_buttons.scss similarity index 100% rename from scss/_buttons.scss rename to scss/components/_buttons.scss diff --git a/scss/_card.scss b/scss/components/_card.scss similarity index 100% rename from scss/_card.scss rename to scss/components/_card.scss diff --git a/scss/_carousel.scss b/scss/components/_carousel.scss similarity index 100% rename from scss/_carousel.scss rename to scss/components/_carousel.scss diff --git a/scss/_close.scss b/scss/components/_close.scss similarity index 100% rename from scss/_close.scss rename to scss/components/_close.scss diff --git a/scss/components/_code.scss b/scss/components/_code.scss new file mode 100644 index 0000000000000000000000000000000000000000..635b3577be238ca67c02f8de041370439ca3c794 --- /dev/null +++ b/scss/components/_code.scss @@ -0,0 +1,23 @@ +@import "../placeholders/code"; + +// Inline and block code styles +code { @extend %code; } +kbd { @extend %kbd; } +pre { @extend %pre; } +samp { @extend %samp; } + +a > code { + @extend %a_code; +} + +kbd kbd { + @extend %kbd__kbd; +} +pre code { + @extend %pre__code; +} + +// Enable scrollable blocks of code +.pre-scrollable { + @extend %pre-scrollable; +} diff --git a/scss/_custom-forms.scss b/scss/components/_custom-forms.scss similarity index 100% rename from scss/_custom-forms.scss rename to scss/components/_custom-forms.scss diff --git a/scss/_dropdown.scss b/scss/components/_dropdown.scss similarity index 100% rename from scss/_dropdown.scss rename to scss/components/_dropdown.scss diff --git a/scss/_forms.scss b/scss/components/_forms.scss similarity index 100% rename from scss/_forms.scss rename to scss/components/_forms.scss diff --git a/scss/components/_grid.scss b/scss/components/_grid.scss new file mode 100644 index 0000000000000000000000000000000000000000..4433d3996ece5deb3bdf84ee51702eba619932e5 --- /dev/null +++ b/scss/components/_grid.scss @@ -0,0 +1,50 @@ +@import "../placeholders/grid"; +// Container widths +// +// Set the container width, and override it for fixed navbars in media queries. + +@if $enable-grid-classes { + .container { + @extend %container; + } +} + +// Fluid container +// +// Utilizes the mixin meant for fixed width containers, but with 100% width for +// fluid, full width layouts. + +@if $enable-grid-classes { + .container-fluid { + @extend %container-fluid; + } +} + +// Row +// +// Rows contain and clear the floats of your columns. + +@if $enable-grid-classes { + .row { + @extend %row; + } + + // Remove the negative margin from default .row, then the horizontal padding + // from all immediate children columns (to prevent runaway style inheritance). + .no-gutters { + @extend %no-gutters; + + > .col, + > [class*="col-"] { + @extend %no-gutters_col; + } + } +} + +// Columns +// +// Common styles for small and large grid columns + +@if $enable-grid-classes { + @include make-grid-columns(); +} diff --git a/scss/components/_images.scss b/scss/components/_images.scss new file mode 100644 index 0000000000000000000000000000000000000000..713a60675d82989f354715230a8fca40bc42be95 --- /dev/null +++ b/scss/components/_images.scss @@ -0,0 +1,33 @@ +@import "../placeholders/images"; +// Responsive images (ensure images don't scale beyond their parents) +// +// This is purposefully opt-in via an explicit class rather than being the default for all `<img>`s. +// We previously tried the "images are responsive by default" approach in Bootstrap v2, +// and abandoned it in Bootstrap v3 because it breaks lots of third-party widgets (including Google Maps) +// which weren't expecting the images within themselves to be involuntarily resized. +// See also https://github.com/twbs/bootstrap/issues/18178 +.img-fluid { + @extend %img-fluid; +} + + +// Image thumbnails +.img-thumbnail { + @extend %img-thumbnail; +} + +// +// Figures +// + +.figure { + @extend %figure; +} + +.figure-img { + @extend %figure-img; +} + +.figure-caption { + @extend %figure-caption; +} diff --git a/scss/_input-group.scss b/scss/components/_input-group.scss similarity index 100% rename from scss/_input-group.scss rename to scss/components/_input-group.scss diff --git a/scss/_jumbotron.scss b/scss/components/_jumbotron.scss similarity index 100% rename from scss/_jumbotron.scss rename to scss/components/_jumbotron.scss diff --git a/scss/_list-group.scss b/scss/components/_list-group.scss similarity index 100% rename from scss/_list-group.scss rename to scss/components/_list-group.scss diff --git a/scss/_media.scss b/scss/components/_media.scss similarity index 100% rename from scss/_media.scss rename to scss/components/_media.scss diff --git a/scss/_modal.scss b/scss/components/_modal.scss similarity index 100% rename from scss/_modal.scss rename to scss/components/_modal.scss diff --git a/scss/_nav.scss b/scss/components/_nav.scss similarity index 100% rename from scss/_nav.scss rename to scss/components/_nav.scss diff --git a/scss/_navbar.scss b/scss/components/_navbar.scss similarity index 100% rename from scss/_navbar.scss rename to scss/components/_navbar.scss diff --git a/scss/_pagination.scss b/scss/components/_pagination.scss similarity index 100% rename from scss/_pagination.scss rename to scss/components/_pagination.scss diff --git a/scss/_popover.scss b/scss/components/_popover.scss similarity index 100% rename from scss/_popover.scss rename to scss/components/_popover.scss diff --git a/scss/_progress.scss b/scss/components/_progress.scss similarity index 100% rename from scss/_progress.scss rename to scss/components/_progress.scss diff --git a/scss/_tables.scss b/scss/components/_tables.scss similarity index 100% rename from scss/_tables.scss rename to scss/components/_tables.scss diff --git a/scss/_tooltip.scss b/scss/components/_tooltip.scss similarity index 100% rename from scss/_tooltip.scss rename to scss/components/_tooltip.scss diff --git a/scss/_transitions.scss b/scss/components/_transitions.scss similarity index 100% rename from scss/_transitions.scss rename to scss/components/_transitions.scss diff --git a/scss/components/_type.scss b/scss/components/_type.scss new file mode 100644 index 0000000000000000000000000000000000000000..86bbcc70601c50d61674fed0d6954ae2ad6e1be3 --- /dev/null +++ b/scss/components/_type.scss @@ -0,0 +1,92 @@ +@import "../placeholders/type"; +// stylelint-disable declaration-no-important, selector-list-comma-newline-after + +// +// Headings +// + + +h1, .h1 { @extend %h1; } +h2, .h2 { @extend %h2; } +h3, .h3 { @extend %h3; } +h4, .h4 { @extend %h4; } +h5, .h5 { @extend %h5; } +h6, .h6 { @extend %h6; } + +.lead { + @extend %lead; +} + +// Type display classes +.display-1 { + @extend %display-1; +} +.display-2 { + @extend %display-1; +} +.display-3 { + @extend %display-1; +} +.display-4 { + @extend %display-1; +} + + +// +// Horizontal rules +// + +hr { + @extend %hr; +} + + +// +// Emphasis +// + +small, +.small { + @extend %small; +} + +mark, +.mark { + @extend %mark; +} + + +// +// Lists +// + +.list-unstyled { + @extend %list-unstyled; +} + +// Inline turns list items into inline-block +.list-inline { + @extend %list-inline; +} +.list-inline-item { + @extend %list-inline-item; +} + + +// +// Misc +// + +// Builds on `abbr` +.initialism { + @extend %initialism; +} + +// Blockquotes +.blockquote { + @extend %blockquote; +} + +.blockquote-footer { + @extend %blockquote-footer; +} diff --git a/scss/mixins/_grid-framework.scss b/scss/mixins/_grid-framework.scss index 41bdf4646da2140fc46a514131a7886bfbc961f8..28294129c39e6240163068e22a957253cbe53cf6 100644 --- a/scss/mixins/_grid-framework.scss +++ b/scss/mixins/_grid-framework.scss @@ -3,7 +3,7 @@ // Used only by Bootstrap to generate the correct number of grid classes given // any value of `$grid-columns`. -@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) { +@mixin make-grid-columns-placeholders($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) { // Common properties for all breakpoints %grid-column { position: relative; @@ -18,40 +18,40 @@ // Allow columns to stretch full width below their breakpoints @for $i from 1 through $columns { - .col#{$infix}-#{$i} { + %col#{$infix}-#{$i} { @extend %grid-column; } } - .col#{$infix}, - .col#{$infix}-auto { + %col#{$infix}, + %col#{$infix}-auto { @extend %grid-column; } @include media-breakpoint-up($breakpoint, $breakpoints) { // Provide basic `.col-{bp}` classes for equal-width flexbox columns - .col#{$infix} { + %col#{$infix} { flex-basis: 0; flex-grow: 1; max-width: 100%; } - .col#{$infix}-auto { + %col#{$infix}-auto { flex: 0 0 auto; width: auto; max-width: none; // Reset earlier grid tiers } @for $i from 1 through $columns { - .col#{$infix}-#{$i} { + %col#{$infix}-#{$i} { @include make-col($i, $columns); } } - .order#{$infix}-first { + %order#{$infix}-first { order: -1; } @for $i from 1 through $columns { - .order#{$infix}-#{$i} { + %order#{$infix}-#{$i} { order: $i; } } @@ -59,7 +59,7 @@ // `$columns - 1` because offsetting by the width of an entire row isn't possible @for $i from 0 through ($columns - 1) { @if not ($infix == "" and $i == 0) { // Avoid emitting useless .offset-0 - .offset#{$infix}-#{$i} { + %offset#{$infix}-#{$i} { @include make-col-offset($i, $columns); } } @@ -67,3 +67,60 @@ } } } + +@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) { + + @include make-grid-columns-placeholders($columns, $gutter, $breakpoints); + + @each $breakpoint in map-keys($breakpoints) { + $infix: breakpoint-infix($breakpoint, $breakpoints); + + // Allow columns to stretch full width below their breakpoints + @for $i from 1 through $columns { + .col#{$infix}-#{$i} { + @extend %col#{$infix}-#{$i}; + } + } + .col#{$infix} { + @extend %col#{$infix}; + } + .col#{$infix}-auto { + @extend %col#{$infix}-auto; + } + + @include media-breakpoint-up($breakpoint, $breakpoints) { + + .col#{$infix} { + @extend %col#{$infix}; + } + .col#{$infix}-auto { + @extend %col#{$infix}-auto; + } + + @for $i from 1 through $columns { + .col#{$infix}-#{$i} { + @extend %col#{$infix}-#{$i}; + } + } + + .order#{$infix}-first { + @extend %order#{$infix}-first; + } + + @for $i from 1 through $columns { + .order#{$infix}-#{$i} { + @extend %order#{$infix}-#{$i}; + } + } + + @for $i from 0 through ($columns - 1) { + @if not ($infix == "" and $i == 0) { // Avoid emitting useless .offset-0 + .offset#{$infix}-#{$i} { + @extend %offset#{$infix}-#{$i}; + } + } + } + + } + } +} diff --git a/scss/placeholders/_alert.scss b/scss/placeholders/_alert.scss new file mode 100644 index 0000000000000000000000000000000000000000..66fba24ead2b33a4844c5884fee8dca10ff727f5 --- /dev/null +++ b/scss/placeholders/_alert.scss @@ -0,0 +1,49 @@ +// +// Base styles +// + +.alert { + position: relative; + padding: $alert-padding-y $alert-padding-x; + margin-bottom: $alert-margin-bottom; + border: $alert-border-width solid transparent; + @include border-radius($alert-border-radius); +} + +// Headings for larger alerts +.alert-heading { + // Specified to prevent conflicts of changing $headings-color + color: inherit; +} + +// Provide class for links that match alerts +.alert-link { + font-weight: $alert-link-font-weight; +} + + +// Dismissible alerts +// +// Expand the right padding and account for the close button's positioning. + +.alert-dismissible { + // Adjust close link position + .close { + position: absolute; + top: 0; + right: 0; + padding: $alert-padding-y $alert-padding-x; + color: inherit; + } +} + + +// Alternate styles +// +// Generate contextual modifier classes for colorizing the alert. + +@each $color, $value in $theme-colors { + .alert-#{$color} { + @include alert-variant(theme-color-level($color, -10), theme-color-level($color, -9), theme-color-level($color, 6)); + } +} diff --git a/scss/placeholders/_badge.scss b/scss/placeholders/_badge.scss new file mode 100644 index 0000000000000000000000000000000000000000..b87a1b00495abc8b00d4c813ec301c22cb320f80 --- /dev/null +++ b/scss/placeholders/_badge.scss @@ -0,0 +1,47 @@ +// Base class +// +// Requires one of the contextual, color modifier classes for `color` and +// `background-color`. + +.badge { + display: inline-block; + padding: $badge-padding-y $badge-padding-x; + font-size: $badge-font-size; + font-weight: $badge-font-weight; + line-height: 1; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + @include border-radius($badge-border-radius); + + // Empty badges collapse automatically + &:empty { + display: none; + } +} + +// Quick fix for badges in buttons +.btn .badge { + position: relative; + top: -1px; +} + +// Pill badges +// +// Make them extra rounded with a modifier to replace v3's badges. + +.badge-pill { + padding-right: $badge-pill-padding-x; + padding-left: $badge-pill-padding-x; + @include border-radius($badge-pill-border-radius); +} + +// Colors +// +// Contextual variations (linked badges get darker on :hover). + +@each $color, $value in $theme-colors { + .badge-#{$color} { + @include badge-variant($value); + } +} diff --git a/scss/placeholders/_breadcrumb.scss b/scss/placeholders/_breadcrumb.scss new file mode 100644 index 0000000000000000000000000000000000000000..25b9d85a1285b323b3023a3e788256c50f72e2fe --- /dev/null +++ b/scss/placeholders/_breadcrumb.scss @@ -0,0 +1,38 @@ +.breadcrumb { + display: flex; + flex-wrap: wrap; + padding: $breadcrumb-padding-y $breadcrumb-padding-x; + margin-bottom: $breadcrumb-margin-bottom; + list-style: none; + background-color: $breadcrumb-bg; + @include border-radius($border-radius); +} + +.breadcrumb-item { + // The separator between breadcrumbs (by default, a forward-slash: "/") + + .breadcrumb-item::before { + display: inline-block; // Suppress underlining of the separator in modern browsers + padding-right: $breadcrumb-item-padding; + padding-left: $breadcrumb-item-padding; + color: $breadcrumb-divider-color; + content: "#{$breadcrumb-divider}"; + } + + // IE9-11 hack to properly handle hyperlink underlines for breadcrumbs built + // without `<ul>`s. The `::before` pseudo-element generates an element + // *within* the .breadcrumb-item and thereby inherits the `text-decoration`. + // + // To trick IE into suppressing the underline, we give the pseudo-element an + // underline and then immediately remove it. + + .breadcrumb-item:hover::before { + text-decoration: underline; + } + // stylelint-disable-next-line no-duplicate-selectors + + .breadcrumb-item:hover::before { + text-decoration: none; + } + + &.active { + color: $breadcrumb-active-color; + } +} diff --git a/scss/placeholders/_button-group.scss b/scss/placeholders/_button-group.scss new file mode 100644 index 0000000000000000000000000000000000000000..1a373f323282b31e07f13bd851bfb9120a53621d --- /dev/null +++ b/scss/placeholders/_button-group.scss @@ -0,0 +1,207 @@ +// stylelint-disable selector-no-qualifying-type + +// Make the div behave like a button +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-flex; + vertical-align: middle; // match .btn alignment given font-size hack above + + > .btn { + position: relative; + flex: 0 1 auto; + + // Bring the hover, focused, and "active" buttons to the front to overlay + // the borders properly + @include hover { + z-index: 2; + } + &:focus, + &:active, + &.active { + z-index: 2; + } + } + + // Prevent double borders when buttons are next to each other + .btn + .btn, + .btn + .btn-group, + .btn-group + .btn, + .btn-group + .btn-group { + margin-left: -$input-btn-border-width; + } +} + +// Optional: Group multiple button groups together for a toolbar +.btn-toolbar { + display: flex; + flex-wrap: wrap; + justify-content: flex-start; + + .input-group { + width: auto; + } +} + +.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) { + @include 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) { + @include 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 { + @include border-right-radius(0); + } +} + +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + @include border-left-radius(0); +} + + +// Sizing +// +// Remix the default button sizing classes into new ones for easier manipulation. + +.btn-group-sm > .btn { @extend .btn-sm; } +.btn-group-lg > .btn { @extend .btn-lg; } + + +// +// Split button dropdowns +// + +.btn + .dropdown-toggle-split { + padding-right: $input-btn-padding-x * .75; + padding-left: $input-btn-padding-x * .75; + + &::after { + margin-left: 0; + } +} + +.btn-sm + .dropdown-toggle-split { + padding-right: $input-btn-padding-x-sm * .75; + padding-left: $input-btn-padding-x-sm * .75; +} + +.btn-lg + .dropdown-toggle-split { + padding-right: $input-btn-padding-x-lg * .75; + padding-left: $input-btn-padding-x-lg * .75; +} + + +// The clickable button for toggling the menu +// Set the same inset shadow as the :active state +.btn-group.show .dropdown-toggle { + @include box-shadow($btn-active-box-shadow); + + // Show no shadow for `.btn-link` since it has no other button styles. + &.btn-link { + @include box-shadow(none); + } +} + + +// +// Vertical button groups +// + +.btn-group-vertical { + flex-direction: column; + align-items: flex-start; + justify-content: center; + + .btn, + .btn-group { + width: 100%; + } + + > .btn + .btn, + > .btn + .btn-group, + > .btn-group + .btn, + > .btn-group + .btn-group { + margin-top: -$input-btn-border-width; + margin-left: 0; + } + + > .btn { + &:not(:first-child):not(:last-child) { + border-radius: 0; + } + + &:first-child:not(:last-child) { + @include border-bottom-radius(0); + } + + &:last-child:not(:first-child) { + @include border-top-radius(0); + } + } + + > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; + } + + > .btn-group:first-child:not(:last-child) { + > .btn:last-child, + > .dropdown-toggle { + @include border-bottom-radius(0); + } + } + + > .btn-group:last-child:not(:first-child) > .btn:first-child { + @include border-top-radius(0); + } +} + + +// Checkbox and radio options +// +// In order to support the browser's form validation feedback, powered by the +// `required` attribute, we have to "hide" the inputs via `clip`. We cannot use +// `display: none;` or `visibility: hidden;` as that also hides the popover. +// Simply visually hiding the inputs via `opacity` would leave them clickable in +// certain cases which is prevented by using `clip` and `pointer-events`. +// This way, we ensure a DOM element is visible to position the popover from. +// +// See https://github.com/twbs/bootstrap/pull/12794 and +// https://github.com/twbs/bootstrap/pull/14559 for more information. + +[data-toggle="buttons"] { + > .btn, + > .btn-group > .btn { + input[type="radio"], + input[type="checkbox"] { + position: absolute; + clip: rect(0,0,0,0); + pointer-events: none; + } + } +} diff --git a/scss/placeholders/_buttons.scss b/scss/placeholders/_buttons.scss new file mode 100644 index 0000000000000000000000000000000000000000..7cd27830b5966b2c1394d9c9cd80ff039b74e007 --- /dev/null +++ b/scss/placeholders/_buttons.scss @@ -0,0 +1,136 @@ +// stylelint-disable selector-no-qualifying-type + +// +// Base styles +// + +.btn { + display: inline-block; + font-weight: $btn-font-weight; + text-align: center; + white-space: nowrap; + vertical-align: middle; + user-select: none; + border: $input-btn-border-width solid transparent; + @include button-size($input-btn-padding-y, $input-btn-padding-x, $font-size-base, $input-btn-line-height, $btn-border-radius); + @include transition($btn-transition); + + // Share hover and focus styles + @include hover-focus { + text-decoration: none; + } + &:focus, + &.focus { + outline: 0; + box-shadow: $input-btn-focus-box-shadow; + } + + // Disabled comes first so active can properly restyle + &.disabled, + &:disabled { + opacity: .65; + @include box-shadow(none); + } + + &:not([disabled]):not(.disabled):active, + &:not([disabled]):not(.disabled).active { + background-image: none; + @include box-shadow($input-btn-focus-box-shadow, $btn-active-box-shadow); + } +} + +// Future-proof disabling of clicks on `<a>` elements +a.btn.disabled, +fieldset[disabled] a.btn { + pointer-events: none; +} + + +// +// Alternate buttons +// + +@each $color, $value in $theme-colors { + .btn-#{$color} { + @include button-variant($value, $value); + } +} + +@each $color, $value in $theme-colors { + .btn-outline-#{$color} { + @if $color == "light" { + @include button-outline-variant($value, $gray-900); + } @else { + @include button-outline-variant($value, $white); + } + } +} + + +// +// Link buttons +// + +// Make a button look and behave like a link +.btn-link { + font-weight: $font-weight-normal; + color: $link-color; + background-color: transparent; + + @include hover { + color: $link-hover-color; + text-decoration: $link-hover-decoration; + background-color: transparent; + border-color: transparent; + } + + &:focus, + &.focus { + border-color: transparent; + box-shadow: none; + } + + &:disabled, + &.disabled { + color: $btn-link-disabled-color; + } + + // No need for an active state here +} + + +// +// Button Sizes +// + +.btn-lg { + @include button-size($input-btn-padding-y-lg, $input-btn-padding-x-lg, $font-size-lg, $input-btn-line-height-lg, $btn-border-radius-lg); +} + +.btn-sm { + @include button-size($input-btn-padding-y-sm, $input-btn-padding-x-sm, $font-size-sm, $input-btn-line-height-sm, $btn-border-radius-sm); +} + + +// +// Block button +// + +.btn-block { + display: block; + width: 100%; +} + +// Vertically space out multiple block buttons +.btn-block + .btn-block { + margin-top: $btn-block-spacing-y; +} + +// Specificity overrides +input[type="submit"], +input[type="reset"], +input[type="button"] { + &.btn-block { + width: 100%; + } +} diff --git a/scss/placeholders/_card.scss b/scss/placeholders/_card.scss new file mode 100644 index 0000000000000000000000000000000000000000..a739f193558aaae11ab2ff6a572217485c150c3a --- /dev/null +++ b/scss/placeholders/_card.scss @@ -0,0 +1,259 @@ +// +// Base styles +// + +.card { + position: relative; + display: flex; + flex-direction: column; + min-width: 0; + word-wrap: break-word; + background-color: $card-bg; + background-clip: border-box; + border: $card-border-width solid $card-border-color; + @include border-radius($card-border-radius); + + > hr { + margin-right: 0; + margin-left: 0; + } + + > .list-group:first-child { + .list-group-item:first-child { + @include border-top-radius($card-border-radius); + } + } + + > .list-group:last-child { + .list-group-item:last-child { + @include border-bottom-radius($card-border-radius); + } + } +} + +.card-body { + // Enable `flex-grow: 1` for decks and groups so that card blocks take up + // as much space as possible, ensuring footers are aligned to the bottom. + flex: 1 1 auto; + padding: $card-spacer-x; +} + +.card-title { + margin-bottom: $card-spacer-y; +} + +.card-subtitle { + margin-top: -($card-spacer-y / 2); + margin-bottom: 0; +} + +.card-text:last-child { + margin-bottom: 0; +} + +.card-link { + @include hover { + text-decoration: none; + } + + + .card-link { + margin-left: $card-spacer-x; + } +} + +// +// Optional textual caps +// + +.card-header { + padding: $card-spacer-y $card-spacer-x; + margin-bottom: 0; // Removes the default margin-bottom of <hN> + background-color: $card-cap-bg; + border-bottom: $card-border-width solid $card-border-color; + + &:first-child { + @include border-radius($card-inner-border-radius $card-inner-border-radius 0 0); + } + + + .list-group { + .list-group-item:first-child { + border-top: 0; + } + } +} + +.card-footer { + padding: $card-spacer-y $card-spacer-x; + background-color: $card-cap-bg; + border-top: $card-border-width solid $card-border-color; + + &:last-child { + @include border-radius(0 0 $card-inner-border-radius $card-inner-border-radius); + } +} + + +// +// Header navs +// + +.card-header-tabs { + margin-right: -($card-spacer-x / 2); + margin-bottom: -$card-spacer-y; + margin-left: -($card-spacer-x / 2); + border-bottom: 0; +} + +.card-header-pills { + margin-right: -($card-spacer-x / 2); + margin-left: -($card-spacer-x / 2); +} + +// Card image +.card-img-overlay { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + padding: $card-img-overlay-padding; +} + +.card-img { + width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch + @include border-radius($card-inner-border-radius); +} + +// Card image caps +.card-img-top { + width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch + @include border-top-radius($card-inner-border-radius); +} + +.card-img-bottom { + width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch + @include border-bottom-radius($card-inner-border-radius); +} + + +// Card deck + +.card-deck { + display: flex; + flex-direction: column; + + .card { + margin-bottom: $card-deck-margin; + } + + @include media-breakpoint-up(sm) { + flex-flow: row wrap; + margin-right: -$card-deck-margin; + margin-left: -$card-deck-margin; + + .card { + display: flex; + // Flexbugs #4: https://github.com/philipwalton/flexbugs#4-flex-shorthand-declarations-with-unitless-flex-basis-values-are-ignored + flex: 1 0 0%; + flex-direction: column; + margin-right: $card-deck-margin; + margin-bottom: 0; // Override the default + margin-left: $card-deck-margin; + } + } +} + + +// +// Card groups +// + +.card-group { + display: flex; + flex-direction: column; + + .card { + margin-bottom: $card-group-margin; + } + + @include media-breakpoint-up(sm) { + flex-flow: row wrap; + + .card { + // Flexbugs #4: https://github.com/philipwalton/flexbugs#4-flex-shorthand-declarations-with-unitless-flex-basis-values-are-ignored + flex: 1 0 0%; + margin-bottom: 0; + + + .card { + margin-left: 0; + border-left: 0; + } + + // Handle rounded corners + @if $enable-rounded { + &:first-child { + @include border-right-radius(0); + + .card-img-top { + border-top-right-radius: 0; + } + .card-img-bottom { + border-bottom-right-radius: 0; + } + } + + &:last-child { + @include border-left-radius(0); + + .card-img-top { + border-top-left-radius: 0; + } + .card-img-bottom { + border-bottom-left-radius: 0; + } + } + + &:only-child { + @include border-radius($card-border-radius); + + .card-img-top { + @include border-top-radius($card-border-radius); + } + .card-img-bottom { + @include border-bottom-radius($card-border-radius); + } + } + + &:not(:first-child):not(:last-child):not(:only-child) { + border-radius: 0; + + .card-img-top, + .card-img-bottom { + border-radius: 0; + } + } + } + } + } +} + + +// +// Columns +// + +.card-columns { + .card { + margin-bottom: $card-columns-margin; + } + + @include media-breakpoint-up(sm) { + column-count: $card-columns-count; + column-gap: $card-columns-gap; + + .card { + display: inline-block; // Don't let them vertically span multiple columns + width: 100%; // Don't let their width change + } + } +} diff --git a/scss/placeholders/_carousel.scss b/scss/placeholders/_carousel.scss new file mode 100644 index 0000000000000000000000000000000000000000..c3c207387c9b3ee180b7fe4bd8c0530064c9d901 --- /dev/null +++ b/scss/placeholders/_carousel.scss @@ -0,0 +1,191 @@ +// Wrapper for the slide container and indicators +.carousel { + position: relative; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} + +.carousel-item { + position: relative; + display: none; + align-items: center; + width: 100%; + @include transition($carousel-transition); + backface-visibility: hidden; + perspective: 1000px; +} + +.carousel-item.active, +.carousel-item-next, +.carousel-item-prev { + display: block; +} + +.carousel-item-next, +.carousel-item-prev { + position: absolute; + top: 0; +} + +// CSS3 transforms when supported by the browser +.carousel-item-next.carousel-item-left, +.carousel-item-prev.carousel-item-right { + transform: translateX(0); + + @supports (transform-style: preserve-3d) { + transform: translate3d(0, 0, 0); + } +} + +.carousel-item-next, +.active.carousel-item-right { + transform: translateX(100%); + + @supports (transform-style: preserve-3d) { + transform: translate3d(100%, 0, 0); + } +} + +.carousel-item-prev, +.active.carousel-item-left { + transform: translateX(-100%); + + @supports (transform-style: preserve-3d) { + transform: translate3d(-100%, 0, 0); + } +} + + +// +// Left/right controls for nav +// + +.carousel-control-prev, +.carousel-control-next { + position: absolute; + top: 0; + bottom: 0; + // Use flex for alignment (1-3) + display: flex; // 1. allow flex styles + align-items: center; // 2. vertically center contents + justify-content: center; // 3. horizontally center contents + width: $carousel-control-width; + color: $carousel-control-color; + text-align: center; + opacity: $carousel-control-opacity; + // We can't have a transition here because WebKit cancels the carousel + // animation if you trip this while in the middle of another animation. + + // Hover/focus state + @include hover-focus { + color: $carousel-control-color; + text-decoration: none; + outline: 0; + opacity: .9; + } +} +.carousel-control-prev { + left: 0; + @if $enable-gradients { + background: linear-gradient(90deg, rgba(0,0,0,.25), rgba(0,0,0,.001)); + } +} +.carousel-control-next { + right: 0; + @if $enable-gradients { + background: linear-gradient(270deg, rgba(0,0,0,.25), rgba(0,0,0,.001)); + } +} + +// Icons for within +.carousel-control-prev-icon, +.carousel-control-next-icon { + display: inline-block; + width: $carousel-control-icon-width; + height: $carousel-control-icon-width; + background: transparent no-repeat center center; + background-size: 100% 100%; +} +.carousel-control-prev-icon { + background-image: $carousel-control-prev-icon-bg; +} +.carousel-control-next-icon { + background-image: $carousel-control-next-icon-bg; +} + + +// Optional indicator pips +// +// Add an ordered list with the following class and add a list item for each +// slide your carousel holds. + +.carousel-indicators { + position: absolute; + right: 0; + bottom: 10px; + left: 0; + z-index: 15; + display: flex; + justify-content: center; + padding-left: 0; // override <ol> default + // Use the .carousel-control's width as margin so we don't overlay those + margin-right: $carousel-control-width; + margin-left: $carousel-control-width; + list-style: none; + + li { + position: relative; + flex: 0 1 auto; + width: $carousel-indicator-width; + height: $carousel-indicator-height; + margin-right: $carousel-indicator-spacer; + margin-left: $carousel-indicator-spacer; + text-indent: -999px; + background-color: rgba($carousel-indicator-active-bg, .5); + + // Use pseudo classes to increase the hit area by 10px on top and bottom. + &::before { + position: absolute; + top: -10px; + left: 0; + display: inline-block; + width: 100%; + height: 10px; + content: ""; + } + &::after { + position: absolute; + bottom: -10px; + left: 0; + display: inline-block; + width: 100%; + height: 10px; + content: ""; + } + } + + .active { + background-color: $carousel-indicator-active-bg; + } +} + + +// Optional captions +// +// + +.carousel-caption { + position: absolute; + right: ((100% - $carousel-caption-width) / 2); + bottom: 20px; + left: ((100% - $carousel-caption-width) / 2); + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: $carousel-caption-color; + text-align: center; +} diff --git a/scss/placeholders/_close.scss b/scss/placeholders/_close.scss new file mode 100644 index 0000000000000000000000000000000000000000..897d4868443ab748ecd4cd22ce437ec2bda010a9 --- /dev/null +++ b/scss/placeholders/_close.scss @@ -0,0 +1,29 @@ +.close { + float: right; + font-size: $close-font-size; + font-weight: $close-font-weight; + line-height: 1; + color: $close-color; + text-shadow: $close-text-shadow; + opacity: .5; + + @include hover-focus { + color: $close-color; + text-decoration: none; + opacity: .75; + } +} + +// 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 + +// stylelint-disable property-no-vendor-prefix, selector-no-qualifying-type +button.close { + padding: 0; + background: transparent; + border: 0; + -webkit-appearance: none; +} +// stylelint-enable diff --git a/scss/_code.scss b/scss/placeholders/_code.scss similarity index 78% rename from scss/_code.scss rename to scss/placeholders/_code.scss index b88f5b61dee156f49935fb361ea40fb9da048179..d7180a46ef6fc44fa1073e60718e126bafe5f6b1 100644 --- a/scss/_code.scss +++ b/scss/placeholders/_code.scss @@ -1,29 +1,30 @@ // Inline and block code styles -code, -kbd, -pre, -samp { +%code, +%kbd, +%pre, +%samp { font-family: $font-family-monospace; } // Inline code -code { +%code { padding: $code-padding-y $code-padding-x; font-size: $code-font-size; color: $code-color; background-color: $code-bg; @include border-radius($border-radius); - // Streamline the style when inside anchors to avoid broken underline and more - a > & { - padding: 0; - color: inherit; - background-color: inherit; - } } +// Streamline the style when inside anchors to avoid broken underline and more +%a_code { + padding: 0; + color: inherit; + background-color: inherit; +} + // User input typically entered via keyboard -kbd { +%kbd { padding: $code-padding-y $code-padding-x; font-size: $code-font-size; color: $kbd-color; @@ -31,7 +32,7 @@ kbd { @include border-radius($border-radius-sm); @include box-shadow($kbd-box-shadow); - kbd { + &__kbd { padding: 0; font-size: 100%; font-weight: $nested-kbd-font-weight; @@ -40,13 +41,15 @@ kbd { } // Blocks of code -pre { +%pre { display: block; + margin-top: 0; + margin-bottom: 1rem; font-size: $code-font-size; color: $pre-color; // Account for some code outputs that place code tags in pre tags - code { + &__code { padding: 0; font-size: inherit; color: inherit; @@ -56,7 +59,7 @@ pre { } // Enable scrollable blocks of code -.pre-scrollable { +%pre-scrollable { max-height: $pre-scrollable-max-height; overflow-y: scroll; } diff --git a/scss/placeholders/_custom-forms.scss b/scss/placeholders/_custom-forms.scss new file mode 100644 index 0000000000000000000000000000000000000000..a521dbdc9445db37c507e036abb7c73b8b6055b6 --- /dev/null +++ b/scss/placeholders/_custom-forms.scss @@ -0,0 +1,257 @@ +// Embedded icons from Open Iconic. +// Released under MIT and copyright 2014 Waybury. +// https://useiconic.com/open + + +// Checkboxes and radios +// +// Base class takes care of all the key behavioral aspects. + +.custom-control { + position: relative; + display: inline-flex; + min-height: (1rem * $line-height-base); + padding-left: $custom-control-gutter; + margin-right: $custom-control-spacer-x; +} + +.custom-control-input { + position: absolute; + z-index: -1; // Put the input behind the label so it doesn't overlay text + opacity: 0; + + &:checked ~ .custom-control-indicator { + color: $custom-control-indicator-checked-color; + @include gradient-bg($custom-control-indicator-checked-bg); + @include box-shadow($custom-control-indicator-checked-box-shadow); + } + + &:focus ~ .custom-control-indicator { + // the mixin is not used here to make sure there is feedback + box-shadow: $custom-control-indicator-focus-box-shadow; + } + + &:active ~ .custom-control-indicator { + color: $custom-control-indicator-active-color; + @include gradient-bg($custom-control-indicator-active-bg); + @include box-shadow($custom-control-indicator-active-box-shadow); + } + + &:disabled { + ~ .custom-control-indicator { + background-color: $custom-control-indicator-disabled-bg; + } + + ~ .custom-control-description { + color: $custom-control-description-disabled-color; + } + } +} + +// Custom indicator +// +// Generates a shadow element to create our makeshift checkbox/radio background. + +.custom-control-indicator { + position: absolute; + top: (($line-height-base - $custom-control-indicator-size) / 2); + left: 0; + display: block; + width: $custom-control-indicator-size; + height: $custom-control-indicator-size; + pointer-events: none; + user-select: none; + background-color: $custom-control-indicator-bg; + background-repeat: no-repeat; + background-position: center center; + background-size: $custom-control-indicator-bg-size; + @include box-shadow($custom-control-indicator-box-shadow); +} + +// Checkboxes +// +// Tweak just a few things for checkboxes. + +.custom-checkbox { + .custom-control-indicator { + @include border-radius($custom-checkbox-indicator-border-radius); + } + + .custom-control-input:checked ~ .custom-control-indicator { + background-image: $custom-checkbox-indicator-icon-checked; + } + + .custom-control-input:indeterminate ~ .custom-control-indicator { + background-color: $custom-checkbox-indicator-indeterminate-bg; + background-image: $custom-checkbox-indicator-icon-indeterminate; + @include box-shadow($custom-checkbox-indicator-indeterminate-box-shadow); + } +} + +// Radios +// +// Tweak just a few things for radios. + +.custom-radio { + .custom-control-indicator { + border-radius: $custom-radio-indicator-border-radius; + } + + .custom-control-input:checked ~ .custom-control-indicator { + background-image: $custom-radio-indicator-icon-checked; + } +} + + +// Layout options +// +// By default radios and checkboxes are `inline-block` with no additional spacing +// set. Use these optional classes to tweak the layout. + +.custom-controls-stacked { + display: flex; + flex-direction: column; + + .custom-control { + margin-bottom: $custom-control-spacer-y; + + + .custom-control { + margin-left: 0; + } + } +} + + +// Select +// +// Replaces the browser default select with a custom one, mostly pulled from +// http://primercss.io. +// + +.custom-select { + display: inline-block; + max-width: 100%; + height: $input-height; + padding: $custom-select-padding-y ($custom-select-padding-x + $custom-select-indicator-padding) $custom-select-padding-y $custom-select-padding-x; + line-height: $custom-select-line-height; + color: $custom-select-color; + vertical-align: middle; + background: $custom-select-bg $custom-select-indicator no-repeat right $custom-select-padding-x center; + background-size: $custom-select-bg-size; + border: $custom-select-border-width solid $custom-select-border-color; + @if $enable-rounded { + border-radius: $custom-select-border-radius; + } @else { + border-radius: 0; + } + appearance: none; + + &:focus { + border-color: $custom-select-focus-border-color; + outline: none; + @include box-shadow($custom-select-focus-box-shadow); + + &::-ms-value { + // For visual consistency with other platforms/browsers, + // supress the default white text on blue background highlight given to + // the selected option text when the (still closed) <select> receives focus + // in IE and (under certain conditions) Edge. + // See https://github.com/twbs/bootstrap/issues/19398. + color: $input-color; + background-color: $input-bg; + } + } + + &[multiple] { + height: auto; + background-image: none; + } + + &:disabled { + color: $custom-select-disabled-color; + background-color: $custom-select-disabled-bg; + } + + // Hides the default caret in IE11 + &::-ms-expand { + opacity: 0; + } +} + +.custom-select-sm { + height: $custom-select-height-sm; + padding-top: $custom-select-padding-y; + padding-bottom: $custom-select-padding-y; + font-size: $custom-select-font-size-sm; +} + + +// File +// +// Custom file input. + +.custom-file { + position: relative; + display: inline-block; + max-width: 100%; + height: $custom-file-height; + margin-bottom: 0; +} + +.custom-file-input { + min-width: $custom-file-width; + max-width: 100%; + height: $custom-file-height; + margin: 0; + opacity: 0; + + &:focus ~ .custom-file-control { + box-shadow: $custom-file-focus-box-shadow; + } +} + +.custom-file-control { + position: absolute; + top: 0; + right: 0; + left: 0; + z-index: 5; + height: $custom-file-height; + padding: $custom-file-padding-y $custom-file-padding-x; + line-height: $custom-file-line-height; + color: $custom-file-color; + pointer-events: none; + user-select: none; + background-color: $custom-file-bg; + border: $custom-file-border-width solid $custom-file-border-color; + @include border-radius($custom-file-border-radius); + @include box-shadow($custom-file-box-shadow); + + @each $lang, $text in map-get($custom-file-text, placeholder) { + &:lang(#{$lang}):empty::after { + content: $text; + } + } + + &::before { + position: absolute; + top: -$custom-file-border-width; + right: -$custom-file-border-width; + bottom: -$custom-file-border-width; + z-index: 6; + display: block; + height: $custom-file-height; + padding: $custom-file-padding-y $custom-file-padding-x; + line-height: $custom-file-line-height; + color: $custom-file-button-color; + @include gradient-bg($custom-file-button-bg); + border: $custom-file-border-width solid $custom-file-border-color; + @include border-radius(0 $custom-file-border-radius $custom-file-border-radius 0); + } + + @each $lang, $text in map-get($custom-file-text, button-label) { + &:lang(#{$lang})::before { + content: $text; + } + } +} diff --git a/scss/placeholders/_dropdown.scss b/scss/placeholders/_dropdown.scss new file mode 100644 index 0000000000000000000000000000000000000000..daa867a573e5cc5e4d28959ac75fa08a41676f5e --- /dev/null +++ b/scss/placeholders/_dropdown.scss @@ -0,0 +1,103 @@ +// The dropdown wrapper (`<div>`) +.dropup, +.dropdown { + position: relative; +} + +.dropdown-toggle { + // Generate the caret automatically + @include caret; +} + +// The dropdown menu +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: $zindex-dropdown; + display: none; // none by default, but block on "open" of the menu + float: left; + min-width: $dropdown-min-width; + padding: $dropdown-padding-y 0; + margin: $dropdown-spacer 0 0; // override default ul + font-size: $font-size-base; // Redeclare because nesting can cause inheritance issues + color: $body-color; + text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer) + list-style: none; + background-color: $dropdown-bg; + background-clip: padding-box; + border: $dropdown-border-width solid $dropdown-border-color; + @include border-radius($border-radius); + @include box-shadow($dropdown-box-shadow); +} + +// Allow for dropdowns to go bottom up (aka, dropup-menu) +// Just add .dropup after the standard .dropdown class and you're set. +.dropup { + .dropdown-menu { + margin-top: 0; + margin-bottom: $dropdown-spacer; + } + + .dropdown-toggle { + @include caret(up); + } +} + +// Dividers (basically an `<hr>`) within the dropdown +.dropdown-divider { + @include nav-divider($dropdown-divider-bg); +} + +// Links, buttons, and more within the dropdown menu +// +// `<button>`-specific styles are denoted with `// For <button>s` +.dropdown-item { + display: block; + width: 100%; // For `<button>`s + padding: $dropdown-item-padding-y $dropdown-item-padding-x; + clear: both; + font-weight: $font-weight-normal; + color: $dropdown-link-color; + text-align: inherit; // For `<button>`s + white-space: nowrap; // prevent links from randomly breaking onto new lines + background: none; // For `<button>`s + border: 0; // For `<button>`s + + @include hover-focus { + color: $dropdown-link-hover-color; + text-decoration: none; + @include gradient-bg($dropdown-link-hover-bg); + } + + &.active, + &:active { + color: $dropdown-link-active-color; + text-decoration: none; + @include gradient-bg($dropdown-link-active-bg); + } + + &.disabled, + &:disabled { + color: $dropdown-link-disabled-color; + background-color: transparent; + // Remove CSS gradients if they're enabled + @if $enable-gradients { + background-image: none; + } + } +} + +.dropdown-menu.show { + display: block; +} + +// Dropdown section headers +.dropdown-header { + display: block; + padding: $dropdown-padding-y $dropdown-item-padding-x; + margin-bottom: 0; // for use with heading elements + font-size: $font-size-sm; + color: $dropdown-header-color; + white-space: nowrap; // as with > li > a +} diff --git a/scss/placeholders/_forms.scss b/scss/placeholders/_forms.scss new file mode 100644 index 0000000000000000000000000000000000000000..80bc7f3ba875f7ce222bff7ba42e074390b38d5b --- /dev/null +++ b/scss/placeholders/_forms.scss @@ -0,0 +1,358 @@ +// stylelint-disable selector-no-qualifying-type + +// +// Textual form controls +// + +.form-control { + display: block; + width: 100%; + padding: $input-btn-padding-y $input-btn-padding-x; + font-size: $font-size-base; + line-height: $input-btn-line-height; + color: $input-color; + background-color: $input-bg; + // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214. + background-image: none; + background-clip: padding-box; + border: $input-btn-border-width solid $input-border-color; + + // Note: This has no effect on <select>s in some browsers, due to the limited stylability of `<select>`s in CSS. + @if $enable-rounded { + // Manually use the if/else instead of the mixin to account for iOS override + border-radius: $input-border-radius; + } @else { + // Otherwise undo the iOS default + border-radius: 0; + } + + @include box-shadow($input-box-shadow); + @include transition($input-transition); + + // Unstyle the caret on `<select>`s in IE10+. + &::-ms-expand { + background-color: transparent; + border: 0; + } + + // Customize the `:focus` state to imitate native WebKit styles. + @include form-control-focus(); + + // Placeholder + &::placeholder { + color: $input-placeholder-color; + // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526. + opacity: 1; + } + + // 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] { + background-color: $input-disabled-bg; + // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655. + opacity: 1; + } +} + +select.form-control { + &:not([size]):not([multiple]) { + height: $input-height; + } + + &:focus::-ms-value { + // Suppress the nested default white text on blue background highlight given to + // the selected option text when the (still closed) <select> receives focus + // in IE and (under certain conditions) Edge, as it looks bad and cannot be made to + // match the appearance of the native widget. + // See https://github.com/twbs/bootstrap/issues/19398. + color: $input-color; + background-color: $input-bg; + } +} + +// Make file inputs better match text inputs by forcing them to new lines. +.form-control-file, +.form-control-range { + display: block; +} + + +// +// Labels +// + +// For use with horizontal and inline forms, when you need the label text to +// align with the form controls. +.col-form-label { + padding-top: calc(#{$input-btn-padding-y} + #{$input-btn-border-width}); + padding-bottom: calc(#{$input-btn-padding-y} + #{$input-btn-border-width}); + margin-bottom: 0; // Override the `<label>` default + line-height: $input-btn-line-height; +} + +.col-form-label-lg { + padding-top: calc(#{$input-btn-padding-y-lg} + #{$input-btn-border-width}); + padding-bottom: calc(#{$input-btn-padding-y-lg} + #{$input-btn-border-width}); + font-size: $font-size-lg; + line-height: $input-btn-line-height-lg; +} + +.col-form-label-sm { + padding-top: calc(#{$input-btn-padding-y-sm} + #{$input-btn-border-width}); + padding-bottom: calc(#{$input-btn-padding-y-sm} + #{$input-btn-border-width}); + font-size: $font-size-sm; + line-height: $input-btn-line-height-sm; +} + + +// +// Legends +// + +// For use with horizontal and inline forms, when you need the legend text to +// be the same size as regular labels, and to align with the form controls. +.col-form-legend { + padding-top: $input-btn-padding-y; + padding-bottom: $input-btn-padding-y; + margin-bottom: 0; + font-size: $font-size-base; +} + + +// Readonly controls as plain text +// +// Apply class to a readonly input to make it appear like regular plain +// text (without any border, background color, focus indicator) + +.form-control-plaintext { + padding-top: $input-btn-padding-y; + padding-bottom: $input-btn-padding-y; + margin-bottom: 0; // match inputs if this class comes on inputs with default margins + line-height: $input-btn-line-height; + background-color: transparent; + border: solid transparent; + border-width: $input-btn-border-width 0; + + &.form-control-sm, + &.form-control-lg { + padding-right: 0; + padding-left: 0; + } +} + + +// Form control sizing +// +// Build on `.form-control` with modifier classes to decrease or increase the +// height and font-size of form controls. +// +// The `.form-group-* form-control` variations are sadly duplicated to avoid the +// issue documented in https://github.com/twbs/bootstrap/issues/15074. + +.form-control-sm { + padding: $input-btn-padding-y-sm $input-btn-padding-x-sm; + font-size: $font-size-sm; + line-height: $input-btn-line-height-sm; + @include border-radius($input-border-radius-sm); +} + +select.form-control-sm { + &:not([size]):not([multiple]) { + height: $input-height-sm; + } +} + +.form-control-lg { + padding: $input-btn-padding-y-lg $input-btn-padding-x-lg; + font-size: $font-size-lg; + line-height: $input-btn-line-height-lg; + @include border-radius($input-border-radius-lg); +} + +select.form-control-lg { + &:not([size]):not([multiple]) { + height: $input-height-lg; + } +} + + +// 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; +} + +.form-text { + display: block; + margin-top: $form-text-margin-top; +} + + +// Form grid +// +// Special replacement for our grid system's `.row` for tighter form layouts. + +.form-row { + display: flex; + flex-wrap: wrap; + margin-right: -5px; + margin-left: -5px; + + > .col, + > [class*="col-"] { + padding-right: 5px; + padding-left: 5px; + } +} + + +// Checkboxes and radios +// +// Indent the labels to position radios/checkboxes as hanging controls. + +.form-check { + position: relative; + display: block; + margin-bottom: $form-check-margin-bottom; + + &.disabled { + .form-check-label { + color: $text-muted; + } + } +} + +.form-check-label { + padding-left: $form-check-input-gutter; + margin-bottom: 0; // Override default `<label>` bottom margin +} + +.form-check-input { + position: absolute; + margin-top: $form-check-input-margin-y; + margin-left: -$form-check-input-gutter; +} + +// Radios and checkboxes on same line +.form-check-inline { + display: inline-block; + margin-right: $form-check-inline-margin-x; + + .form-check-label { + vertical-align: middle; + } +} + + +// Form validation +// +// Provide feedback to users when form field values are valid or invalid. Works +// primarily for client-side validation via scoped `:invalid` and `:valid` +// pseudo-classes but also includes `.is-invalid` and `.is-valid` classes for +// server side validation. + +@include form-validation-state("valid", $form-feedback-valid-color); +@include form-validation-state("invalid", $form-feedback-invalid-color); + +// Inline forms +// +// Make forms appear inline(-block) by adding the `.form-inline` class. Inline +// forms begin stacked on extra small (mobile) devices and then go inline when +// viewports reach <768px. +// +// Requires wrapping inputs and labels with `.form-group` for proper display of +// default HTML form controls and our custom form controls (e.g., input groups). + +.form-inline { + display: flex; + flex-flow: row wrap; + align-items: center; // Prevent shorter elements from growing to same height as others (e.g., small buttons growing to normal sized button height) + + // Because we use flex, the initial sizing of checkboxes is collapsed and + // doesn't occupy the full-width (which is what we want for xs grid tier), + // so we force that here. + .form-check { + width: 100%; + } + + // Kick in the inline + @include media-breakpoint-up(sm) { + label { + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 0; + } + + // Inline-block all the things for "inline" + .form-group { + display: flex; + flex: 0 0 auto; + flex-flow: row wrap; + align-items: center; + margin-bottom: 0; + } + + // Allow folks to *not* use `.form-group` + .form-control { + display: inline-block; + width: auto; // Prevent labels from stacking above inputs in `.form-group` + vertical-align: middle; + } + + // Make static controls behave like regular ones + .form-control-plaintext { + display: inline-block; + } + + .input-group { + width: auto; + } + + // Remove default margin on radios/checkboxes that were used for stacking, and + // then undo the floating of radios and checkboxes to match. + .form-check { + display: flex; + align-items: center; + justify-content: center; + width: auto; + margin-top: 0; + margin-bottom: 0; + } + .form-check-label { + padding-left: 0; + } + .form-check-input { + position: relative; + margin-top: 0; + margin-right: $form-check-input-margin-x; + margin-left: 0; + } + + // Custom form controls + .custom-control { + display: flex; + align-items: center; + justify-content: center; + padding-left: 0; + } + .custom-control-indicator { + position: static; + display: inline-block; + margin-right: $form-check-input-margin-x; // Flexbox alignment means we lose our HTML space here, so we compensate. + vertical-align: text-bottom; + } + + // Re-override the feedback icon. + .has-feedback .form-control-feedback { + top: 0; + } + } +} diff --git a/scss/_grid.scss b/scss/placeholders/_grid.scss similarity index 87% rename from scss/_grid.scss rename to scss/placeholders/_grid.scss index a227515379c4bd9979039bc0e86ca3626123b96b..7173501e40979324620b9b4d2db7f83cb1c418ef 100644 --- a/scss/_grid.scss +++ b/scss/placeholders/_grid.scss @@ -3,7 +3,7 @@ // Set the container width, and override it for fixed navbars in media queries. @if $enable-grid-classes { - .container { + %container { @include make-container(); @include make-container-max-widths(); } @@ -15,7 +15,7 @@ // fluid, full width layouts. @if $enable-grid-classes { - .container-fluid { + %container-fluid { @include make-container(); } } @@ -25,18 +25,17 @@ // Rows contain and clear the floats of your columns. @if $enable-grid-classes { - .row { + %row { @include make-row(); } // Remove the negative margin from default .row, then the horizontal padding // from all immediate children columns (to prevent runaway style inheritance). - .no-gutters { + %no-gutters { margin-right: 0; margin-left: 0; - > .col, - > [class*="col-"] { + &_col { padding-right: 0; padding-left: 0; } @@ -48,5 +47,5 @@ // Common styles for small and large grid columns @if $enable-grid-classes { - @include make-grid-columns(); + @include make-grid-columns-placeholders(); } diff --git a/scss/_images.scss b/scss/placeholders/_images.scss similarity index 93% rename from scss/_images.scss rename to scss/placeholders/_images.scss index 50c56108a9174734a38ae9142dedb378d3739a56..ce410cc17a7a4019eb1f7a402fb6537b7a40b815 100644 --- a/scss/_images.scss +++ b/scss/placeholders/_images.scss @@ -5,13 +5,13 @@ // and abandoned it in Bootstrap v3 because it breaks lots of third-party widgets (including Google Maps) // which weren't expecting the images within themselves to be involuntarily resized. // See also https://github.com/twbs/bootstrap/issues/18178 -.img-fluid { +%img-fluid { @include img-fluid; } // Image thumbnails -.img-thumbnail { +%img-thumbnail { padding: $thumbnail-padding; background-color: $thumbnail-bg; border: $thumbnail-border-width solid $thumbnail-border-color; @@ -27,17 +27,17 @@ // Figures // -.figure { +%figure { // Ensures the caption's text aligns with the image. display: inline-block; } -.figure-img { +%figure-img { margin-bottom: ($spacer / 2); line-height: 1; } -.figure-caption { +%figure-caption { font-size: $figure-caption-font-size; color: $figure-caption-color; } diff --git a/scss/placeholders/_input-group.scss b/scss/placeholders/_input-group.scss new file mode 100644 index 0000000000000000000000000000000000000000..a1d16e3848e7fd773951d9a3f9753179dcb30eb1 --- /dev/null +++ b/scss/placeholders/_input-group.scss @@ -0,0 +1,186 @@ +// stylelint-disable selector-no-qualifying-type + +// +// Base styles +// + +.input-group { + position: relative; + display: flex; + align-items: stretch; + width: 100%; + + .form-control { + // Ensure that the input is always above the *appended* addon button for + // proper border colors. + position: relative; + z-index: 2; + flex: 1 1 auto; + // Add width 1% and flex-basis auto to ensure that button will not wrap out + // the column. Applies to IE Edge+ and Firefox. Chrome does not require this. + width: 1%; + margin-bottom: 0; + + // Bring the "active" form control to the front + @include hover-focus-active { + z-index: 3; + } + } +} + +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: flex; + align-items: center; + &:not(:first-child):not(:last-child) { + @include border-radius(0); + } +} + +.input-group-addon, +.input-group-btn { + white-space: nowrap; +} + + +// Sizing options +// +// Remix the default form control sizing classes into new ones for easier +// manipulation. + +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + @extend .form-control-lg; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + @extend .form-control-sm; +} + + +// +// Text input groups +// + +.input-group-addon { + padding: $input-btn-padding-y $input-btn-padding-x; + margin-bottom: 0; // Allow use of <label> elements by overriding our default margin-bottom + font-size: $font-size-base; // Match inputs + font-weight: $font-weight-normal; + line-height: $input-btn-line-height; + color: $input-group-addon-color; + text-align: center; + background-color: $input-group-addon-bg; + border: $input-btn-border-width solid $input-group-addon-border-color; + @include border-radius($input-border-radius); + + // Sizing + &.form-control-sm { + padding: $input-btn-padding-y-sm $input-btn-padding-x-sm; + font-size: $font-size-sm; + @include border-radius($input-border-radius-sm); + } + + &.form-control-lg { + padding: $input-btn-padding-y-lg $input-btn-padding-x-lg; + font-size: $font-size-lg; + @include border-radius($input-border-radius-lg); + } + + // Nuke default margins from checkboxes and radios to vertically center within. + input[type="radio"], + input[type="checkbox"] { + margin-top: 0; + } +} + + +// +// Reset rounded corners +// + +.input-group .form-control:not(:last-child), +.input-group-addon:not(:last-child), +.input-group-btn:not(:last-child) > .btn, +.input-group-btn:not(:last-child) > .btn-group > .btn, +.input-group-btn:not(:last-child) > .dropdown-toggle, +.input-group-btn:not(:first-child) > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:not(:first-child) > .btn-group:not(:last-child) > .btn { + @include border-right-radius(0); +} +.input-group-addon:not(:last-child) { + border-right: 0; +} +.input-group .form-control:not(:first-child), +.input-group-addon:not(:first-child), +.input-group-btn:not(:first-child) > .btn, +.input-group-btn:not(:first-child) > .btn-group > .btn, +.input-group-btn:not(:first-child) > .dropdown-toggle, +.input-group-btn:not(:last-child) > .btn:not(:first-child), +.input-group-btn:not(:last-child) > .btn-group:not(:first-child) > .btn { + @include border-left-radius(0); +} +.form-control + .input-group-addon:not(:first-child) { + border-left: 0; +} + +// +// Button input groups +// + +.input-group-btn { + position: relative; + align-items: stretch; + // Jankily prevent input button groups from wrapping with `white-space` and + // `font-size` in combination with `inline-block` on buttons. + font-size: 0; + white-space: nowrap; + + // Negative margin for spacing, position for bringing hovered/focused/actived + // element above the siblings. + > .btn { + position: relative; + + + .btn { + margin-left: (-$input-btn-border-width); + } + + // Bring the "active" button to the front + @include hover-focus-active { + z-index: 3; + } + } + + &:first-child > .btn + .btn { + margin-left: 0; + } + + // Negative margin to only have a single, shared border between the two + &:not(:last-child) { + > .btn, + > .btn-group { + margin-right: (-$input-btn-border-width); + } + } + &:not(:first-child) { + > .btn, + > .btn-group { + z-index: 2; + // remove nagative margin ($input-btn-border-width) to solve overlapping issue with button. + margin-left: 0; + + // When input is first, overlap the right side of it with the button(-group) + &:first-child { + margin-left: (-$input-btn-border-width); + } + + // Because specificity + @include hover-focus-active { + z-index: 3; + } + } + } +} diff --git a/scss/placeholders/_jumbotron.scss b/scss/placeholders/_jumbotron.scss new file mode 100644 index 0000000000000000000000000000000000000000..7966bba1e22a62689973b6cb377d97802e2c5bbb --- /dev/null +++ b/scss/placeholders/_jumbotron.scss @@ -0,0 +1,16 @@ +.jumbotron { + padding: $jumbotron-padding ($jumbotron-padding / 2); + margin-bottom: $jumbotron-padding; + background-color: $jumbotron-bg; + @include border-radius($border-radius-lg); + + @include media-breakpoint-up(sm) { + padding: ($jumbotron-padding * 2) $jumbotron-padding; + } +} + +.jumbotron-fluid { + padding-right: 0; + padding-left: 0; + @include border-radius(0); +} diff --git a/scss/placeholders/_list-group.scss b/scss/placeholders/_list-group.scss new file mode 100644 index 0000000000000000000000000000000000000000..7e0b19e01ea62dddbdc24199538675d0ee5a9b1c --- /dev/null +++ b/scss/placeholders/_list-group.scss @@ -0,0 +1,114 @@ +// Base class +// +// Easily usable on <ul>, <ol>, or <div>. + +.list-group { + display: flex; + flex-direction: column; + + // No need to set list-style: none; since .list-group-item is block level + padding-left: 0; // reset padding because ul and ol + margin-bottom: 0; +} + + +// Interactive list items +// +// Use anchor or button elements instead of `li`s or `div`s to create interactive +// list items. Includes an extra `.active` modifier class for selected items. + +.list-group-item-action { + width: 100%; // For `<button>`s (anchors become 100% by default though) + color: $list-group-action-color; + text-align: inherit; // For `<button>`s (anchors inherit) + + // Hover state + @include hover-focus { + color: $list-group-action-hover-color; + text-decoration: none; + background-color: $list-group-hover-bg; + } + + &:active { + color: $list-group-action-active-color; + background-color: $list-group-action-active-bg; + } +} + + +// Individual list items +// +// Use on `li`s or `div`s within the `.list-group` parent. + +.list-group-item { + position: relative; + display: block; + padding: $list-group-item-padding-y $list-group-item-padding-x; + // Place the border on the list items and negative margin up for better styling + margin-bottom: -$list-group-border-width; + background-color: $list-group-bg; + border: $list-group-border-width solid $list-group-border-color; + + &:first-child { + @include border-top-radius($list-group-border-radius); + } + + &:last-child { + margin-bottom: 0; + @include border-bottom-radius($list-group-border-radius); + } + + @include hover-focus { + text-decoration: none; + } + + &.disabled, + &:disabled { + color: $list-group-disabled-color; + background-color: $list-group-disabled-bg; + } + + // Include both here for `<a>`s and `<button>`s + &.active { + 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-color; + } +} + + +// Flush list items +// +// Remove borders and border-radius to keep list group items edge-to-edge. Most +// useful within other components (e.g., cards). + +.list-group-flush { + .list-group-item { + border-right: 0; + border-left: 0; + border-radius: 0; + } + + &:first-child { + .list-group-item:first-child { + border-top: 0; + } + } + + &:last-child { + .list-group-item:last-child { + border-bottom: 0; + } + } +} + + +// Contextual variants +// +// Add modifier classes to change text and background color on individual items. +// Organizationally, this must come after the `:hover` states. + +@each $color, $value in $theme-colors { + @include list-group-item-variant($color, theme-color-level($color, -9), theme-color-level($color, 6)); +} diff --git a/scss/placeholders/_media.scss b/scss/placeholders/_media.scss new file mode 100644 index 0000000000000000000000000000000000000000..b573052c14affa5bdca02ac9e3e7a4168768925b --- /dev/null +++ b/scss/placeholders/_media.scss @@ -0,0 +1,8 @@ +.media { + display: flex; + align-items: flex-start; +} + +.media-body { + flex: 1; +} diff --git a/scss/placeholders/_modal.scss b/scss/placeholders/_modal.scss new file mode 100644 index 0000000000000000000000000000000000000000..e655850e387366df7b3cc590229f7cf8621811d3 --- /dev/null +++ b/scss/placeholders/_modal.scss @@ -0,0 +1,153 @@ +// .modal-open - body class for killing the scroll +// .modal - container to scroll within +// .modal-dialog - positioning shell for the actual modal +// .modal-content - actual modal w/ bg and corners and stuff + + +// Kill the scroll on the body +.modal-open { + overflow: hidden; +} + +// Container that the modal scrolls within +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: $zindex-modal; + display: none; + overflow: hidden; + // Prevent Chrome on Windows from adding a focus outline. For details, see + // https://github.com/twbs/bootstrap/pull/10951. + outline: 0; + // We deliberately don't use `-webkit-overflow-scrolling: touch;` due to a + // gnarly iOS Safari bug: https://bugs.webkit.org/show_bug.cgi?id=158342 + // See also https://github.com/twbs/bootstrap/issues/17695 + + // When fading in the modal, animate it to slide down + &.fade .modal-dialog { + @include transition($modal-transition); + transform: translate(0, -25%); + } + &.show .modal-dialog { transform: translate(0, 0); } +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} + +// Shell div to position the modal with bottom padding +.modal-dialog { + position: relative; + width: auto; + margin: $modal-dialog-margin; + // allow clicks to pass through for custom click handling to close modal + pointer-events: none; +} + +// Actual modal +.modal-content { + position: relative; + display: flex; + flex-direction: column; + // counteract the pointer-events: none; in the .modal-dialog + pointer-events: auto; + background-color: $modal-content-bg; + background-clip: padding-box; + border: $modal-content-border-width solid $modal-content-border-color; + @include border-radius($border-radius-lg); + @include box-shadow($modal-content-box-shadow-xs); + // Remove focus outline from opened modal + outline: 0; +} + +// Modal background +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: $zindex-modal-backdrop; + background-color: $modal-backdrop-bg; + + // Fade for backdrop + &.fade { opacity: 0; } + &.show { opacity: $modal-backdrop-opacity; } +} + +// Modal header +// Top section of the modal w/ title and dismiss +.modal-header { + display: flex; + align-items: flex-start; // so the close btn always stays on the upper right corner + justify-content: space-between; // Put modal header elements (title and dismiss) on opposite ends + padding: $modal-header-padding; + border-bottom: $modal-header-border-width solid $modal-header-border-color; + @include border-top-radius($border-radius-lg); + + .close { + padding: $modal-header-padding; + // auto on the left force icon to the right even when there is no .modal-title + margin: (-$modal-header-padding) (-$modal-header-padding) (-$modal-header-padding) auto; + } +} + +// Title text within header +.modal-title { + margin-bottom: 0; + line-height: $modal-title-line-height; +} + +// Modal body +// Where all modal content resides (sibling of .modal-header and .modal-footer) +.modal-body { + position: relative; + // Enable `flex-grow: 1` so that the body take up as much space as possible + // when should there be a fixed height on `.modal-dialog`. + flex: 1 1 auto; + padding: $modal-inner-padding; +} + +// Footer (for actions) +.modal-footer { + display: flex; + align-items: center; // vertically center + justify-content: flex-end; // Right align buttons with flex property because text-align doesn't work on flex items + padding: $modal-inner-padding; + border-top: $modal-footer-border-width solid $modal-footer-border-color; + + // Easily place margin between footer elements + > :not(:first-child) { margin-left: .25rem; } + > :not(:last-child) { margin-right: .25rem; } +} + +// Measure scrollbar width for padding body during modal show/hide +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} + +// Scale up the modal +@include media-breakpoint-up(sm) { + // Automatically set modal's width for larger viewports + .modal-dialog { + max-width: $modal-md; + margin: $modal-dialog-margin-y-sm-up auto; + } + + .modal-content { + @include box-shadow($modal-content-box-shadow-sm-up); + } + + .modal-sm { max-width: $modal-sm; } +} + +@include media-breakpoint-up(lg) { + .modal-lg { max-width: $modal-lg; } +} diff --git a/scss/placeholders/_nav.scss b/scss/placeholders/_nav.scss new file mode 100644 index 0000000000000000000000000000000000000000..14e76c9acc48792a6083de6a03c200140e03c9cf --- /dev/null +++ b/scss/placeholders/_nav.scss @@ -0,0 +1,118 @@ +// Base class +// +// Kickstart any navigation component with a set of style resets. Works with +// `<nav>`s or `<ul>`s. + +.nav { + display: flex; + flex-wrap: wrap; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} + +.nav-link { + display: block; + padding: $nav-link-padding-y $nav-link-padding-x; + + @include hover-focus { + text-decoration: none; + } + + // Disabled state lightens text + &.disabled { + color: $nav-link-disabled-color; + } +} + +// +// Tabs +// + +.nav-tabs { + border-bottom: $nav-tabs-border-width solid $nav-tabs-border-color; + + .nav-item { + margin-bottom: -$nav-tabs-border-width; + } + + .nav-link { + border: $nav-tabs-border-width solid transparent; + @include border-top-radius($nav-tabs-border-radius); + + @include hover-focus { + border-color: $nav-tabs-link-hover-border-color $nav-tabs-link-hover-border-color $nav-tabs-border-color; + } + + &.disabled { + color: $nav-link-disabled-color; + background-color: transparent; + border-color: transparent; + } + } + + .nav-link.active, + .nav-item.show .nav-link { + color: $nav-tabs-link-active-color; + background-color: $nav-tabs-link-active-bg; + border-color: $nav-tabs-link-active-border-color $nav-tabs-link-active-border-color $nav-tabs-link-active-bg; + } + + .dropdown-menu { + // Make dropdown border overlap tab border + margin-top: -$nav-tabs-border-width; + // Remove the top rounded corners here since there is a hard edge above the menu + @include border-top-radius(0); + } +} + + +// +// Pills +// + +.nav-pills { + .nav-link { + @include border-radius($nav-pills-border-radius); + } + + .nav-link.active, + .show > .nav-link { + color: $nav-pills-link-active-color; + background-color: $nav-pills-link-active-bg; + } +} + + +// +// Justified variants +// + +.nav-fill { + .nav-item { + flex: 1 1 auto; + text-align: center; + } +} + +.nav-justified { + .nav-item { + flex-basis: 0; + flex-grow: 1; + text-align: center; + } +} + + +// Tabbable tabs +// +// Hide tabbable panes to start, show them when `.active` + +.tab-content { + > .tab-pane { + display: none; + } + > .active { + display: block; + } +} diff --git a/scss/placeholders/_navbar.scss b/scss/placeholders/_navbar.scss new file mode 100644 index 0000000000000000000000000000000000000000..6b023e82e4001979088b95a2f12366b0b80c3108 --- /dev/null +++ b/scss/placeholders/_navbar.scss @@ -0,0 +1,306 @@ +// Contents +// +// Navbar +// Navbar brand +// Navbar nav +// Navbar text +// Navbar divider +// Responsive navbar +// Navbar position +// Navbar themes + + +// Navbar +// +// Provide a static navbar from which we expand to create full-width, fixed, and +// other navbar variations. + +.navbar { + position: relative; + display: flex; + flex-wrap: wrap; // allow us to do the line break for collapsing content + align-items: center; + justify-content: space-between; // space out brand from logo + padding: $navbar-padding-y $navbar-padding-x; + + // Because flex properties aren't inherited, we need to redeclare these first + // few properities so that content nested within behave properly. + > .container, + > .container-fluid { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + } +} + + +// Navbar brand +// +// Used for brand, project, or site names. + +.navbar-brand { + display: inline-block; + padding-top: $navbar-brand-padding-y; + padding-bottom: $navbar-brand-padding-y; + margin-right: $navbar-padding-x; + font-size: $navbar-brand-font-size; + line-height: inherit; + white-space: nowrap; + + @include hover-focus { + text-decoration: none; + } +} + + +// Navbar nav +// +// Custom navbar navigation (doesn't require `.nav`, but does make use of `.nav-link`). + +.navbar-nav { + display: flex; + flex-direction: column; // cannot use `inherit` to get the `.navbar`s value + padding-left: 0; + margin-bottom: 0; + list-style: none; + + .nav-link { + padding-right: 0; + padding-left: 0; + } + + .dropdown-menu { + position: static; + float: none; + } +} + + +// Navbar text +// +// + +.navbar-text { + display: inline-block; + padding-top: $nav-link-padding-y; + padding-bottom: $nav-link-padding-y; +} + + +// Responsive navbar +// +// Custom styles for responsive collapsing and toggling of navbar contents. +// Powered by the collapse Bootstrap JavaScript plugin. + +// When collapsed, prevent the toggleable navbar contents from appearing in +// the default flexbox row orienation. Requires the use of `flex-wrap: wrap` +// on the `.navbar` parent. +.navbar-collapse { + flex-basis: 100%; + flex-grow: 1; + // For always expanded or extra full navbars, ensure content aligns itself + // properly vertically. Can be easily overridden with flex utilities. + align-items: center; +} + +// Button for toggling the navbar when in its collapsed state +.navbar-toggler { + padding: $navbar-toggler-padding-y $navbar-toggler-padding-x; + font-size: $navbar-toggler-font-size; + line-height: 1; + background: transparent; // remove default button style + border: $border-width solid transparent; // remove default button style + @include border-radius($navbar-toggler-border-radius); + + @include hover-focus { + text-decoration: none; + } +} + +// Keep as a separate element so folks can easily override it with another icon +// or image file as needed. +.navbar-toggler-icon { + display: inline-block; + width: 1.5em; + height: 1.5em; + vertical-align: middle; + content: ""; + background: no-repeat center center; + background-size: 100% 100%; +} + +// Generate series of `.navbar-expand-*` responsive classes for configuring +// where your navbar collapses. +.navbar-expand { + @each $breakpoint in map-keys($grid-breakpoints) { + $next: breakpoint-next($breakpoint, $grid-breakpoints); + $infix: breakpoint-infix($next, $grid-breakpoints); + + &#{$infix} { + @include media-breakpoint-down($breakpoint) { + > .container, + > .container-fluid { + padding-right: 0; + padding-left: 0; + } + } + + @include media-breakpoint-up($next) { + flex-flow: row nowrap; + justify-content: flex-start; + + .navbar-nav { + flex-direction: row; + + .dropdown-menu { + position: absolute; + } + + .dropdown-menu-right { + right: 0; + left: auto; // Reset the default from `.dropdown-menu` + } + + .nav-link { + padding-right: .5rem; + padding-left: .5rem; + } + } + + // For nesting containers, have to redeclare for alignment purposes + > .container, + > .container-fluid { + flex-wrap: nowrap; + } + + .navbar-collapse { + display: flex !important; // stylelint-disable-line declaration-no-important + + // Changes flex-bases to auto because of an IE10 bug + flex-basis: auto; + } + + .navbar-toggler { + display: none; + } + + .dropup { + .dropdown-menu { + top: auto; + bottom: 100%; + } + } + } + } + } +} + + +// Navbar themes +// +// Styles for switching between navbars with light or dark background. + +// Dark links against a light background +.navbar-light { + .navbar-brand { + color: $navbar-light-active-color; + + @include hover-focus { + color: $navbar-light-active-color; + } + } + + .navbar-nav { + .nav-link { + color: $navbar-light-color; + + @include hover-focus { + color: $navbar-light-hover-color; + } + + &.disabled { + color: $navbar-light-disabled-color; + } + } + + .show > .nav-link, + .active > .nav-link, + .nav-link.show, + .nav-link.active { + color: $navbar-light-active-color; + } + } + + .navbar-toggler { + color: $navbar-light-color; + border-color: $navbar-light-toggler-border-color; + } + + .navbar-toggler-icon { + background-image: $navbar-light-toggler-icon-bg; + } + + .navbar-text { + color: $navbar-light-color; + a { + color: $navbar-light-active-color; + + @include hover-focus { + color: $navbar-light-active-color; + } + } + } +} + +// White links against a dark background +.navbar-dark { + .navbar-brand { + color: $navbar-dark-active-color; + + @include hover-focus { + color: $navbar-dark-active-color; + } + } + + .navbar-nav { + .nav-link { + color: $navbar-dark-color; + + @include hover-focus { + color: $navbar-dark-hover-color; + } + + &.disabled { + color: $navbar-dark-disabled-color; + } + } + + .show > .nav-link, + .active > .nav-link, + .nav-link.show, + .nav-link.active { + color: $navbar-dark-active-color; + } + } + + .navbar-toggler { + color: $navbar-dark-color; + border-color: $navbar-dark-toggler-border-color; + } + + .navbar-toggler-icon { + background-image: $navbar-dark-toggler-icon-bg; + } + + .navbar-text { + color: $navbar-dark-color; + a { + color: $navbar-dark-active-color; + + @include hover-focus { + color: $navbar-dark-active-color; + } + } + } +} diff --git a/scss/placeholders/_pagination.scss b/scss/placeholders/_pagination.scss new file mode 100644 index 0000000000000000000000000000000000000000..69a36ffe53b820648d96c339ef5682d7e7501f01 --- /dev/null +++ b/scss/placeholders/_pagination.scss @@ -0,0 +1,64 @@ +.pagination { + display: flex; + @include list-unstyled(); + @include border-radius(); +} + +.page-item { + &:first-child { + .page-link { + margin-left: 0; + @include border-left-radius($border-radius); + } + } + &:last-child { + .page-link { + @include border-right-radius($border-radius); + } + } + + &.active .page-link { + z-index: 2; + color: $pagination-active-color; + background-color: $pagination-active-bg; + border-color: $pagination-active-border-color; + } + + &.disabled .page-link { + color: $pagination-disabled-color; + pointer-events: none; + background-color: $pagination-disabled-bg; + border-color: $pagination-disabled-border-color; + } +} + +.page-link { + position: relative; + display: block; + padding: $pagination-padding-y $pagination-padding-x; + margin-left: -$pagination-border-width; + line-height: $pagination-line-height; + color: $pagination-color; + background-color: $pagination-bg; + border: $pagination-border-width solid $pagination-border-color; + + @include hover-focus { + color: $pagination-hover-color; + text-decoration: none; + background-color: $pagination-hover-bg; + border-color: $pagination-hover-border-color; + } +} + + +// +// Sizing +// + +.pagination-lg { + @include pagination-size($pagination-padding-y-lg, $pagination-padding-x-lg, $font-size-lg, $line-height-lg, $border-radius-lg); +} + +.pagination-sm { + @include pagination-size($pagination-padding-y-sm, $pagination-padding-x-sm, $font-size-sm, $line-height-sm, $border-radius-sm); +} diff --git a/scss/placeholders/_popover.scss b/scss/placeholders/_popover.scss new file mode 100644 index 0000000000000000000000000000000000000000..450376752b495fade40c378a75c038fa306abee3 --- /dev/null +++ b/scss/placeholders/_popover.scss @@ -0,0 +1,194 @@ +.popover { + position: absolute; + top: 0; + left: 0; + z-index: $zindex-popover; + display: block; + max-width: $popover-max-width; + // Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element. + // So reset our font and text properties to avoid inheriting weird values. + @include reset-text(); + font-size: $font-size-sm; + // Allow breaking very long words so they don't overflow the popover's bounds + word-wrap: break-word; + background-color: $popover-bg; + background-clip: padding-box; + border: $popover-border-width solid $popover-border-color; + @include border-radius($border-radius-lg); + @include box-shadow($popover-box-shadow); + + // Arrows + // + // .arrow is outer, .arrow::after is inner + + .arrow { + position: absolute; + display: block; + width: $popover-arrow-width; + height: $popover-arrow-height; + } + + .arrow::before, + .arrow::after { + position: absolute; + display: block; + border-color: transparent; + border-style: solid; + } + + .arrow::before { + content: ""; + border-width: $popover-arrow-width; + } + .arrow::after { + content: ""; + border-width: $popover-arrow-width; + } + + // Popover directions + + &.bs-popover-top { + margin-bottom: $popover-arrow-width; + + .arrow { + bottom: 0; + } + + .arrow::before, + .arrow::after { + border-bottom-width: 0; + } + + .arrow::before { + bottom: -$popover-arrow-width; + margin-left: -$popover-arrow-width; + border-top-color: $popover-arrow-outer-color; + } + + .arrow::after { + bottom: calc((#{$popover-arrow-width} - #{$popover-border-width}) * -1); + margin-left: -$popover-arrow-width; + border-top-color: $popover-arrow-color; + } + } + + &.bs-popover-right { + margin-left: $popover-arrow-width; + + .arrow { + left: 0; + } + + .arrow::before, + .arrow::after { + margin-top: -$popover-arrow-width; + border-left-width: 0; + } + + .arrow::before { + left: -$popover-arrow-width; + border-right-color: $popover-arrow-outer-color; + } + + .arrow::after { + left: calc((#{$popover-arrow-width} - #{$popover-border-width}) * -1); + border-right-color: $popover-arrow-color; + } + } + + &.bs-popover-bottom { + margin-top: $popover-arrow-width; + + .arrow { + top: 0; + } + + .arrow::before, + .arrow::after { + margin-left: -$popover-arrow-width; + border-top-width: 0; + } + + .arrow::before { + top: -$popover-arrow-width; + border-bottom-color: $popover-arrow-outer-color; + } + + .arrow::after { + top: calc((#{$popover-arrow-width} - #{$popover-border-width}) * -1); + border-bottom-color: $popover-arrow-color; + } + + // This will remove the popover-header's border just below the arrow + .popover-header::before { + position: absolute; + top: 0; + left: 50%; + display: block; + width: 20px; + margin-left: -10px; + content: ""; + border-bottom: $popover-border-width solid $popover-header-bg; + } + } + + &.bs-popover-left { + margin-right: $popover-arrow-width; + + .arrow { + right: 0; + } + + .arrow::before, + .arrow::after { + margin-top: -$popover-arrow-width; + border-right-width: 0; + } + + .arrow::before { + right: -$popover-arrow-width; + border-left-color: $popover-arrow-outer-color; + } + + .arrow::after { + right: calc((#{$popover-arrow-width} - #{$popover-border-width}) * -1); + border-left-color: $popover-arrow-color; + } + } + &.bs-popover-auto { + &[x-placement^="top"] { + @extend .bs-popover-top; + } + &[x-placement^="right"] { + @extend .bs-popover-right; + } + &[x-placement^="bottom"] { + @extend .bs-popover-bottom; + } + &[x-placement^="left"] { + @extend .bs-popover-left; + } + } +} + + +// Offset the popover to account for the popover arrow +.popover-header { + padding: $popover-header-padding-y $popover-header-padding-x; + margin-bottom: 0; // Reset the default from Reboot + font-size: $font-size-base; + color: $popover-header-color; + background-color: $popover-header-bg; + border-bottom: $popover-border-width solid darken($popover-header-bg, 5%); + $offset-border-width: calc(#{$border-radius-lg} - #{$popover-border-width}); + @include border-top-radius($offset-border-width); + + &:empty { + display: none; + } +} + +.popover-body { + padding: $popover-body-padding-y $popover-body-padding-x; + color: $popover-body-color; +} diff --git a/scss/placeholders/_progress.scss b/scss/placeholders/_progress.scss new file mode 100644 index 0000000000000000000000000000000000000000..efbb4403407d239763fa5013fa257eecc63d30c2 --- /dev/null +++ b/scss/placeholders/_progress.scss @@ -0,0 +1,30 @@ +@keyframes progress-bar-stripes { + from { background-position: $progress-height 0; } + to { background-position: 0 0; } +} + +.progress { + display: flex; + height: $progress-height; + overflow: hidden; // force rounded corners by cropping it + font-size: $progress-font-size; + background-color: $progress-bg; + @include border-radius($progress-border-radius); +} + +.progress-bar { + display: flex; + align-items: center; + justify-content: center; + color: $progress-bar-color; + background-color: $progress-bar-bg; +} + +.progress-bar-striped { + @include gradient-striped(); + background-size: $progress-height $progress-height; +} + +.progress-bar-animated { + animation: progress-bar-stripes $progress-bar-animation-timing; +} diff --git a/scss/placeholders/_tables.scss b/scss/placeholders/_tables.scss new file mode 100644 index 0000000000000000000000000000000000000000..6bd0b91a43cdc2d345b7859d1e5c73bb7ca05681 --- /dev/null +++ b/scss/placeholders/_tables.scss @@ -0,0 +1,180 @@ +// +// Basic Bootstrap table +// + +.table { + width: 100%; + max-width: 100%; + margin-bottom: $spacer; + background-color: $table-bg; // Reset for nesting within parents with `background-color`. + + th, + td { + padding: $table-cell-padding; + vertical-align: top; + border-top: $table-border-width solid $table-border-color; + } + + thead th { + vertical-align: bottom; + border-bottom: (2 * $table-border-width) solid $table-border-color; + } + + tbody + tbody { + border-top: (2 * $table-border-width) solid $table-border-color; + } + + .table { + background-color: $body-bg; + } +} + + +// +// Condensed table w/ half padding +// + +.table-sm { + th, + td { + padding: $table-cell-padding-sm; + } +} + + +// Bordered version +// +// Add borders all around the table and between all the columns. + +.table-bordered { + border: $table-border-width solid $table-border-color; + + th, + td { + border: $table-border-width solid $table-border-color; + } + + thead { + th, + td { + border-bottom-width: (2 * $table-border-width); + } + } +} + + +// Zebra-striping +// +// Default zebra-stripe styles (alternating gray and transparent backgrounds) + +.table-striped { + tbody tr:nth-of-type(odd) { + background-color: $table-accent-bg; + } +} + + +// Hover effect +// +// Placed here since it has to come after the potential zebra striping + +.table-hover { + tbody tr { + @include hover { + background-color: $table-hover-bg; + } + } +} + + +// Table backgrounds +// +// Exact selectors below required to override `.table-striped` and prevent +// inheritance to nested tables. + +@each $color, $value in $theme-colors { + @include table-row-variant($color, theme-color-level($color, -9)); +} + +@include table-row-variant(active, $table-active-bg); + + +// Dark styles +// +// Same table markup, but inverted color scheme: dark background and light text. + +// stylelint-disable-next-line no-duplicate-selectors +.table { + .thead-dark { + th { + color: $table-dark-color; + background-color: $table-dark-bg; + border-color: $table-dark-border-color; + } + } + + .thead-light { + th { + color: $table-head-color; + background-color: $table-head-bg; + border-color: $table-border-color; + } + } +} + +.table-dark { + color: $table-dark-color; + background-color: $table-dark-bg; + + th, + td, + thead th { + border-color: $table-dark-border-color; + } + + &.table-bordered { + border: 0; + } + + &.table-striped { + tbody tr:nth-of-type(odd) { + background-color: $table-dark-accent-bg; + } + } + + &.table-hover { + tbody tr { + @include hover { + background-color: $table-dark-hover-bg; + } + } + } +} + + +// Responsive tables +// +// Generate series of `.table-responsive-*` classes for configuring the screen +// size of where your table will overflow. + +.table-responsive { + @each $breakpoint in map-keys($grid-breakpoints) { + $next: breakpoint-next($breakpoint, $grid-breakpoints); + $infix: breakpoint-infix($next, $grid-breakpoints); + + &#{$infix} { + @include media-breakpoint-down($breakpoint) { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar; // See https://github.com/twbs/bootstrap/pull/10057 + + // Prevent double border on horizontal scroll due to use of `display: block;` + &.table-bordered { + border: 0; + } + } + } + } +} diff --git a/scss/placeholders/_tooltip.scss b/scss/placeholders/_tooltip.scss new file mode 100644 index 0000000000000000000000000000000000000000..7b5db1cf2a5f2e97f5f1ca78bd593e028ab84ade --- /dev/null +++ b/scss/placeholders/_tooltip.scss @@ -0,0 +1,107 @@ +// Base class +.tooltip { + position: absolute; + z-index: $zindex-tooltip; + display: block; + margin: $tooltip-margin; + // Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element. + // So reset our font and text properties to avoid inheriting weird values. + @include reset-text(); + font-size: $font-size-sm; + // Allow breaking very long words so they don't overflow the tooltip's bounds + word-wrap: break-word; + opacity: 0; + + &.show { opacity: $tooltip-opacity; } + + .arrow { + position: absolute; + display: block; + width: $tooltip-arrow-width; + height: $tooltip-arrow-height; + } + + .arrow::before { + position: absolute; + border-color: transparent; + border-style: solid; + } + + &.bs-tooltip-top { + padding: $tooltip-arrow-width 0; + .arrow { + bottom: 0; + } + + .arrow::before { + margin-left: -($tooltip-arrow-width - 2); + content: ""; + border-width: $tooltip-arrow-width $tooltip-arrow-width 0; + border-top-color: $tooltip-arrow-color; + } + } + &.bs-tooltip-right { + padding: 0 $tooltip-arrow-width; + .arrow { + left: 0; + } + + .arrow::before { + margin-top: -($tooltip-arrow-width - 2); + content: ""; + border-width: $tooltip-arrow-width $tooltip-arrow-width $tooltip-arrow-width 0; + border-right-color: $tooltip-arrow-color; + } + } + &.bs-tooltip-bottom { + padding: $tooltip-arrow-width 0; + .arrow { + top: 0; + } + + .arrow::before { + margin-left: -($tooltip-arrow-width - 2); + content: ""; + border-width: 0 $tooltip-arrow-width $tooltip-arrow-width; + border-bottom-color: $tooltip-arrow-color; + } + } + &.bs-tooltip-left { + padding: 0 $tooltip-arrow-width; + .arrow { + right: 0; + } + + .arrow::before { + right: 0; + margin-top: -($tooltip-arrow-width - 2); + content: ""; + border-width: $tooltip-arrow-width 0 $tooltip-arrow-width $tooltip-arrow-width; + border-left-color: $tooltip-arrow-color; + } + } + &.bs-tooltip-auto { + &[x-placement^="top"] { + @extend .bs-tooltip-top; + } + &[x-placement^="right"] { + @extend .bs-tooltip-right; + } + &[x-placement^="bottom"] { + @extend .bs-tooltip-bottom; + } + &[x-placement^="left"] { + @extend .bs-tooltip-left; + } + } +} + +// Wrapper for the tooltip content +.tooltip-inner { + max-width: $tooltip-max-width; + padding: $tooltip-padding-y $tooltip-padding-x; + color: $tooltip-color; + text-align: center; + background-color: $tooltip-bg; + @include border-radius($border-radius); +} diff --git a/scss/placeholders/_transitions.scss b/scss/placeholders/_transitions.scss new file mode 100644 index 0000000000000000000000000000000000000000..df5744b25f5a297a93e2e25e1cd1efdcb620a7a1 --- /dev/null +++ b/scss/placeholders/_transitions.scss @@ -0,0 +1,36 @@ +// stylelint-disable selector-no-qualifying-type + +.fade { + opacity: 0; + @include transition($transition-fade); + + &.show { + opacity: 1; + } +} + +.collapse { + display: none; + &.show { + display: block; + } +} + +tr { + &.collapse.show { + display: table-row; + } +} + +tbody { + &.collapse.show { + display: table-row-group; + } +} + +.collapsing { + position: relative; + height: 0; + overflow: hidden; + @include transition($transition-collapse); +} diff --git a/scss/_type.scss b/scss/placeholders/_type.scss similarity index 77% rename from scss/_type.scss rename to scss/placeholders/_type.scss index b1b8f61cf5fcf0fa14ed049f573751ac527f96b8..14812045291cfad0890850236478bb8611dbd721 100644 --- a/scss/_type.scss +++ b/scss/placeholders/_type.scss @@ -4,8 +4,7 @@ // Headings // -h1, h2, h3, h4, h5, h6, -.h1, .h2, .h3, .h4, .h5, .h6 { +%h1, %h2, %h3, %h4, %h5, %h6 { margin-bottom: $headings-margin-bottom; font-family: $headings-font-family; font-weight: $headings-font-weight; @@ -13,35 +12,35 @@ h1, h2, h3, h4, h5, h6, color: $headings-color; } -h1, .h1 { font-size: $h1-font-size; } -h2, .h2 { font-size: $h2-font-size; } -h3, .h3 { font-size: $h3-font-size; } -h4, .h4 { font-size: $h4-font-size; } -h5, .h5 { font-size: $h5-font-size; } -h6, .h6 { font-size: $h6-font-size; } +%h1 { font-size: $h1-font-size; } +%h2 { font-size: $h2-font-size; } +%h3 { font-size: $h3-font-size; } +%h4 { font-size: $h4-font-size; } +%h5 { font-size: $h5-font-size; } +%h6 { font-size: $h6-font-size; } -.lead { +%lead { font-size: $lead-font-size; font-weight: $lead-font-weight; } // Type display classes -.display-1 { +%display-1 { font-size: $display1-size; font-weight: $display1-weight; line-height: $display-line-height; } -.display-2 { +%display-2 { font-size: $display2-size; font-weight: $display2-weight; line-height: $display-line-height; } -.display-3 { +%display-3 { font-size: $display3-size; font-weight: $display3-weight; line-height: $display-line-height; } -.display-4 { +%display-4 { font-size: $display4-size; font-weight: $display4-weight; line-height: $display-line-height; @@ -52,7 +51,7 @@ h6, .h6 { font-size: $h6-font-size; } // Horizontal rules // -hr { +%hr { margin-top: 1rem; margin-bottom: 1rem; border: 0; @@ -64,14 +63,12 @@ hr { // Emphasis // -small, -.small { +%small { font-size: $small-font-size; font-weight: $font-weight-normal; } -mark, -.mark { +%mark { padding: $mark-padding; background-color: $mark-bg; } @@ -81,15 +78,15 @@ mark, // Lists // -.list-unstyled { +%list-unstyled { @include list-unstyled; } // Inline turns list items into inline-block -.list-inline { +%list-inline { @include list-unstyled; } -.list-inline-item { +%list-inline-item { display: inline-block; &:not(:last-child) { @@ -103,18 +100,18 @@ mark, // // Builds on `abbr` -.initialism { +%initialism { font-size: 90%; text-transform: uppercase; } // Blockquotes -.blockquote { +%blockquote { margin-bottom: $spacer; font-size: $blockquote-font-size; } -.blockquote-footer { +%blockquote-footer { display: block; font-size: 80%; // back to default font-size color: $blockquote-small-color;