aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Otto <[email protected]>2017-10-29 16:13:37 -0700
committerMark Otto <[email protected]>2017-10-29 16:13:37 -0700
commitb5cd9b91b2f93418bcaa6cb081cc842a6e6ef58c (patch)
treed80b57010228641c23c2328120d894d901f2f4a2
parent136aefead43a231ec8fb4514c525da10ac30c497 (diff)
parent2232b6b4d140cf8a01314deb7e4779c7fde8ab05 (diff)
downloadbootstrap-b5cd9b91b2f93418bcaa6cb081cc842a6e6ef58c.tar.xz
bootstrap-b5cd9b91b2f93418bcaa6cb081cc842a6e6ef58c.zip
Merge branch 'v4-dev' of https://github.com/twbs/bootstrap into v4-dev
-rw-r--r--docs/4.0/components/dropdowns.md126
-rw-r--r--docs/4.0/components/modal.md58
-rw-r--r--js/src/dropdown.js30
-rw-r--r--js/src/tooltip.js16
-rw-r--r--js/tests/visual/dropdown.html48
-rw-r--r--scss/_dropdown.scss28
-rw-r--r--scss/_modal.scss15
-rw-r--r--scss/mixins/_caret.scss30
8 files changed, 332 insertions, 19 deletions
diff --git a/docs/4.0/components/dropdowns.md b/docs/4.0/components/dropdowns.md
index c4ada2b0f..cb307550d 100644
--- a/docs/4.0/components/dropdowns.md
+++ b/docs/4.0/components/dropdowns.md
@@ -410,6 +410,132 @@ Trigger dropdown menus above elements by adding `.dropup` to the parent element.
</div>
{% endhighlight %}
+## Dropright variation
+
+Trigger dropdown menus at the right of the elements by adding `.dropright` to the parent element.
+
+<div class="bd-example">
+ <div class="btn-group dropright">
+ <button type="button" class="btn btn-secondary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+ Dropright
+ </button>
+ <div class="dropdown-menu">
+ <a class="dropdown-item" href="#">Action</a>
+ <a class="dropdown-item" href="#">Another action</a>
+ <a class="dropdown-item" href="#">Something else here</a>
+ <div class="dropdown-divider"></div>
+ <a class="dropdown-item" href="#">Separated link</a>
+ </div>
+ </div>
+
+ <div class="btn-group dropright">
+ <button type="button" class="btn btn-secondary">
+ Split dropright
+ </button>
+ <button type="button" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+ <span class="sr-only">Toggle Dropdright</span>
+ </button>
+ <div class="dropdown-menu">
+ <a class="dropdown-item" href="#">Action</a>
+ <a class="dropdown-item" href="#">Another action</a>
+ <a class="dropdown-item" href="#">Something else here</a>
+ <div class="dropdown-divider"></div>
+ <a class="dropdown-item" href="#">Separated link</a>
+ </div>
+ </div>
+</div>
+
+{% highlight html %}
+<!-- Default dropright button -->
+<div class="btn-group dropright">
+ <button type="button" class="btn btn-secondary">Dropright</button>
+ <button type="button" class="btn btn-secondary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+ <span class="sr-only">Toggle Dropright</span>
+ </button>
+ <div class="dropdown-menu">
+ <!-- Dropdown menu links -->
+ </div>
+</div>
+
+<!-- Split dropright button -->
+<div class="btn-group dropright">
+ <button type="button" class="btn btn-secondary">
+ Split dropright
+ </button>
+ <button type="button" class="btn btn-secondary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+ <span class="sr-only">Toggle Dropright</span>
+ </button>
+ <div class="dropdown-menu">
+ <!-- Dropdown menu links -->
+ </div>
+</div>
+{% endhighlight %}
+
+## Dropleft variation
+
+Trigger dropdown menus at the left of the elements by adding `.dropleft` to the parent element.
+
+<div class="bd-example">
+ <div class="btn-group dropleft">
+ <button type="button" class="btn btn-secondary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+ Dropleft
+ </button>
+ <div class="dropdown-menu">
+ <a class="dropdown-item" href="#">Action</a>
+ <a class="dropdown-item" href="#">Another action</a>
+ <a class="dropdown-item" href="#">Something else here</a>
+ <div class="dropdown-divider"></div>
+ <a class="dropdown-item" href="#">Separated link</a>
+ </div>
+ </div>
+
+ <div class="btn-group">
+ <div class="btn-group dropleft" role="group">
+ <button type="button" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+ <span class="sr-only">Toggle Dropleft</span>
+ </button>
+ <div class="dropdown-menu">
+ <a class="dropdown-item" href="#">Action</a>
+ <a class="dropdown-item" href="#">Another action</a>
+ <a class="dropdown-item" href="#">Something else here</a>
+ <div class="dropdown-divider"></div>
+ <a class="dropdown-item" href="#">Separated link</a>
+ </div>
+ </div>
+ <button type="button" class="btn btn-secondary">
+ Split dropleft
+ </button>
+ </div>
+</div>
+
+{% highlight html %}
+<!-- Default dropleft button -->
+<div class="btn-group dropleft">
+ <button type="button" class="btn btn-secondary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+ Dropleft
+ </button>
+ <div class="dropdown-menu">
+ <!-- Dropdown menu links -->
+ </div>
+</div>
+
+<!-- Split dropleft button -->
+<div class="btn-group">
+ <div class="btn-group dropleft" role="group">
+ <button type="button" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+ <span class="sr-only">Toggle Dropleft</span>
+ </button>
+ <div class="dropdown-menu">
+ <!-- Dropdown menu links -->
+ </div>
+ </div>
+ <button type="button" class="btn btn-secondary">
+ Split dropleft
+ </button>
+</div>
+{% endhighlight %}
+
+
## Menu items
Historically dropdown menu contents *had* to be links, but that's no longer the case with v4. Now you can optionally use `<button>` elements in your dropdowns instead of just `<a>`s.
diff --git a/docs/4.0/components/modal.md b/docs/4.0/components/modal.md
index c4191b83d..b9ebc4ad4 100644
--- a/docs/4.0/components/modal.md
+++ b/docs/4.0/components/modal.md
@@ -208,6 +208,64 @@ When modals become too long for the user's viewport or device, they scroll indep
</div>
{% endhighlight %}
+### Vertically centered
+
+Add `.modal-dialog-centered` to `.modal-dialog` to vertically center the modal. **Do not use this with long modals**—it will overflow the viewport and potentially hide parts of your modal.
+
+<div id="exampleModalCenter" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
+ <div class="modal-dialog modal-dialog-centered" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h5 class="modal-title" id="exampleModalCenterTitle">Modal title</h5>
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+ <span aria-hidden="true">&times;</span>
+ </button>
+ </div>
+ <div class="modal-body">
+ <p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
+ <button type="button" class="btn btn-primary">Save changes</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+<div class="bd-example">
+ <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModalCenter">
+ Launch demo modal
+ </button>
+</div>
+
+{% highlight html %}
+<!-- Button trigger modal -->
+<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModalCenter">
+ Launch demo modal
+</button>
+
+<!-- Modal -->
+<div class="modal fade" id="exampleModalCenter" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
+ <div class="modal-dialog" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h5 class="modal-title" id="exampleModalLongTitle">Modal title</h5>
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+ <span aria-hidden="true">&times;</span>
+ </button>
+ </div>
+ <div class="modal-body">
+ ...
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
+ <button type="button" class="btn btn-primary">Save changes</button>
+ </div>
+ </div>
+ </div>
+</div>
+{% endhighlight %}
+
### Tooltips and popovers
[Tooltips]({{ site.baseurl }}/docs/{{ site.docs_version }}/components/tooltips/) and [popovers]({{ site.baseurl }}/docs/{{ site.docs_version }}/components/popovers/) can be placed within modals as needed. When modals are closed, any tooltips and popovers within are also automatically dismissed.
diff --git a/js/src/dropdown.js b/js/src/dropdown.js
index 18b051b89..a18f0c28a 100644
--- a/js/src/dropdown.js
+++ b/js/src/dropdown.js
@@ -13,14 +13,6 @@ import Util from './util'
const Dropdown = (($) => {
/**
- * Check for Popper dependency
- * Popper - https://popper.js.org
- */
- if (typeof Popper === 'undefined') {
- throw new Error('Bootstrap dropdown require Popper.js (https://popper.js.org)')
- }
-
- /**
* ------------------------------------------------------------------------
* Constants
* ------------------------------------------------------------------------
@@ -55,6 +47,8 @@ const Dropdown = (($) => {
DISABLED : 'disabled',
SHOW : 'show',
DROPUP : 'dropup',
+ DROPRIGHT : 'dropright',
+ DROPLEFT : 'dropleft',
MENURIGHT : 'dropdown-menu-right',
MENULEFT : 'dropdown-menu-left'
}
@@ -71,7 +65,11 @@ const Dropdown = (($) => {
TOP : 'top-start',
TOPEND : 'top-end',
BOTTOM : 'bottom-start',
- BOTTOMEND : 'bottom-end'
+ BOTTOMEND : 'bottom-end',
+ RIGHT : 'right-start',
+ RIGHTEND : 'right-end',
+ LEFT : 'left-start',
+ LEFTEND : 'left-end'
}
const Default = {
@@ -145,6 +143,14 @@ const Dropdown = (($) => {
return
}
+ /**
+ * Check for Popper dependency
+ * Popper - https://popper.js.org
+ */
+ if (typeof Popper === 'undefined') {
+ throw new Error('Bootstrap dropdown require Popper.js (https://popper.js.org)')
+ }
+
let element = this._element
// for dropup with alignment we use the parent as popper container
if ($(parent).hasClass(ClassName.DROPUP)) {
@@ -227,7 +233,7 @@ const Dropdown = (($) => {
_getPlacement() {
const $parentDropdown = $(this._element).parent()
- let placement = AttachmentMap.BOTTOM
+ let placement = AttachmentMap.BOTTOM
// Handle dropup
if ($parentDropdown.hasClass(ClassName.DROPUP)) {
@@ -235,6 +241,10 @@ const Dropdown = (($) => {
if ($(this._menu).hasClass(ClassName.MENURIGHT)) {
placement = AttachmentMap.TOPEND
}
+ } else if ($parentDropdown.hasClass(ClassName.DROPRIGHT)) {
+ placement = AttachmentMap.RIGHT
+ } else if ($parentDropdown.hasClass(ClassName.DROPLEFT)) {
+ placement = AttachmentMap.LEFT
} else if ($(this._menu).hasClass(ClassName.MENURIGHT)) {
placement = AttachmentMap.BOTTOMEND
}
diff --git a/js/src/tooltip.js b/js/src/tooltip.js
index a3fc93c91..7cefd0be6 100644
--- a/js/src/tooltip.js
+++ b/js/src/tooltip.js
@@ -13,15 +13,6 @@ import Util from './util'
const Tooltip = (($) => {
/**
- * Check for Popper dependency
- * Popper - https://popper.js.org
- */
- if (typeof Popper === 'undefined') {
- throw new Error('Bootstrap tooltips require Popper.js (https://popper.js.org)')
- }
-
-
- /**
* ------------------------------------------------------------------------
* Constants
* ------------------------------------------------------------------------
@@ -120,6 +111,13 @@ const Tooltip = (($) => {
class Tooltip {
constructor(element, config) {
+ /**
+ * Check for Popper dependency
+ * Popper - https://popper.js.org
+ */
+ if (typeof Popper === 'undefined') {
+ throw new Error('Bootstrap tooltips require Popper.js (https://popper.js.org)')
+ }
// private
this._isEnabled = true
diff --git a/js/tests/visual/dropdown.html b/js/tests/visual/dropdown.html
index 11b89b0f2..b2e588677 100644
--- a/js/tests/visual/dropdown.html
+++ b/js/tests/visual/dropdown.html
@@ -93,6 +93,7 @@
</div>
</div>
</div>
+
<div class="col-sm-12 mt-4">
<div class="btn-group dropup" role="group">
<a href="#" class="btn btn-secondary">Dropup split align right</a>
@@ -114,8 +115,55 @@
</div>
</div>
</div>
+
+ <div class="col-sm-12 mt-4">
+ <div class="btn-group dropright" role="group">
+ <a href="#" class="btn btn-secondary">Dropright split</a>
+ <button type="button" id="dropdown-page-subheader-button-4" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+ <span class="sr-only">Product actions</span>
+ </button>
+ <div class="dropdown-menu">
+ <button class="dropdown-item" type="button">Action</button>
+ <button class="dropdown-item" type="button">Another action</button>
+ <button class="dropdown-item" type="button">Something else here with a long text</button>
+ </div>
+ </div>
+ <div class="btn-group dropright">
+ <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuRight" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+ Dropright
+ </button>
+ <div class="dropdown-menu" aria-labelledby="dropdownMenuRight">
+ <button class="dropdown-item" type="button">Action</button>
+ <button class="dropdown-item" type="button">Another action</button>
+ <button class="dropdown-item" type="button">Something else here</button>
+ </div>
+ </div>
+ <!-- dropleft -->
+ <div class="btn-group dropleft" role="group">
+ <a href="#" class="btn btn-secondary">Dropleft split</a>
+ <button type="button" id="dropdown-page-subheader-button-5" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+ <span class="sr-only">Product actions</span>
+ </button>
+ <div class="dropdown-menu">
+ <button class="dropdown-item" type="button">Action</button>
+ <button class="dropdown-item" type="button">Another action</button>
+ <button class="dropdown-item" type="button">Something else here with a long text</button>
+ </div>
+ </div>
+ <div class="btn-group dropleft">
+ <button class="btn btn-secondary dropdown-toggle" type="button" id="dropleftMenu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+ Dropleft
+ </button>
+ <div class="dropdown-menu" aria-labelledby="dropleftMenu">
+ <button class="dropdown-item" type="button">Action</button>
+ <button class="dropdown-item" type="button">Another action</button>
+ <button class="dropdown-item" type="button">Something else here</button>
+ </div>
+ </div>
</div>
+
</div>
+ </div>
<script src="../../../assets/js/vendor/jquery-slim.min.js"></script>
<script src="../../../assets/js/vendor/popper.min.js"></script>
diff --git a/scss/_dropdown.scss b/scss/_dropdown.scss
index 271764188..19edfca7a 100644
--- a/scss/_dropdown.scss
+++ b/scss/_dropdown.scss
@@ -44,6 +44,34 @@
}
}
+.dropright {
+ .dropdown-menu {
+ margin-top: 0;
+ margin-left: $dropdown-spacer;
+ }
+
+ .dropdown-toggle {
+ @include caret(right);
+ &::after {
+ vertical-align: 0;
+ }
+ }
+}
+
+.dropleft {
+ .dropdown-menu {
+ margin-top: 0;
+ margin-right: $dropdown-spacer;
+ }
+
+ .dropdown-toggle {
+ @include caret(left);
+ &::before {
+ vertical-align: 0;
+ }
+ }
+}
+
// Dividers (basically an `<hr>`) within the dropdown
.dropdown-divider {
@include nav-divider($dropdown-divider-bg);
diff --git a/scss/_modal.scss b/scss/_modal.scss
index 5fabc83f4..bd4abc7c6 100644
--- a/scss/_modal.scss
+++ b/scss/_modal.scss
@@ -50,11 +50,20 @@
}
}
+.modal-dialog-centered {
+ display: flex;
+ align-items: center;
+ height: 100%;
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
// Actual modal
.modal-content {
position: relative;
display: flex;
flex-direction: column;
+ width: 100%; // Ensure `.modal-content` extends the full width of the parent `.modal-dialog`
// counteract the pointer-events: none; in the .modal-dialog
pointer-events: auto;
background-color: $modal-content-bg;
@@ -144,11 +153,17 @@
margin: $modal-dialog-margin-y-sm-up auto;
}
+ .modal-dialog-centered {
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+
.modal-content {
@include box-shadow($modal-content-box-shadow-sm-up);
}
.modal-sm { max-width: $modal-sm; }
+
}
@include media-breakpoint-up(lg) {
diff --git a/scss/mixins/_caret.scss b/scss/mixins/_caret.scss
index daab9d03c..40478e492 100644
--- a/scss/mixins/_caret.scss
+++ b/scss/mixins/_caret.scss
@@ -12,6 +12,18 @@
border-left: $caret-width solid transparent;
}
+@mixin caret-right {
+ border-top: $caret-width solid transparent;
+ border-bottom: $caret-width solid transparent;
+ border-left: $caret-width solid;
+}
+
+@mixin caret-left {
+ border-top: $caret-width solid transparent;
+ border-right: $caret-width solid;
+ border-bottom: $caret-width solid transparent;
+}
+
@mixin caret($direction: down) {
@if $enable-caret {
&::after {
@@ -25,6 +37,24 @@
@include caret-down;
} @else if $direction == up {
@include caret-up;
+ } @else if $direction == right {
+ @include caret-right;
+ }
+ }
+
+ @if $direction == left {
+ &::after {
+ display: none;
+ }
+
+ &::before {
+ display: inline-block;
+ width: 0;
+ height: 0;
+ margin-right: $caret-width * .85;
+ vertical-align: $caret-width * .85;
+ content: "";
+ @include caret-left;
}
}