diff options
author | Gaƫl Poupard <gael.poupard@orange.com> | 2020-06-26 17:06:20 +0300 |
---|---|---|
committer | XhmikosR <xhmikosr@gmail.com> | 2020-12-04 08:52:03 +0300 |
commit | 9488978fb55286ba83e8193a871d1ff9815045b9 (patch) | |
tree | abb461d46722f107e54156709c88cf37ed9e24a6 | |
parent | 71ecc3323fb60ea05456470d10d17b614fe6dc04 (diff) |
feat(RTL): implement RTL
Using RTLCSS directives, renaming things to use logical names and following best practices.
37 files changed, 301 insertions, 200 deletions
diff --git a/.bundlewatch.config.json b/.bundlewatch.config.json index 525d29f6a0..8be4f8c7ab 100644 --- a/.bundlewatch.config.json +++ b/.bundlewatch.config.json @@ -10,7 +10,7 @@ }, { "path": "./dist/css/bootstrap-reboot.css", - "maxSize": "2 kB" + "maxSize": "2.25 kB" }, { "path": "./dist/css/bootstrap-reboot.min.css", @@ -54,7 +54,7 @@ }, { "path": "./dist/js/bootstrap.min.js", - "maxSize": "15.5 kB" + "maxSize": "15.75 kB" } ], "ci": { diff --git a/js/src/carousel.js b/js/src/carousel.js index 9c6fb53ee0..d8ad3a1354 100644 --- a/js/src/carousel.js +++ b/js/src/carousel.js @@ -79,8 +79,8 @@ const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}` const CLASS_NAME_CAROUSEL = 'carousel' const CLASS_NAME_ACTIVE = 'active' const CLASS_NAME_SLIDE = 'slide' -const CLASS_NAME_RIGHT = 'carousel-item-right' -const CLASS_NAME_LEFT = 'carousel-item-left' +const CLASS_NAME_END = 'carousel-item-end' +const CLASS_NAME_START = 'carousel-item-start' const CLASS_NAME_NEXT = 'carousel-item-next' const CLASS_NAME_PREV = 'carousel-item-prev' const CLASS_NAME_POINTER_EVENT = 'pointer-event' @@ -442,11 +442,11 @@ class Carousel extends BaseComponent { let eventDirectionName if (direction === DIRECTION_NEXT) { - directionalClassName = CLASS_NAME_LEFT + directionalClassName = CLASS_NAME_START orderClassName = CLASS_NAME_NEXT eventDirectionName = DIRECTION_LEFT } else { - directionalClassName = CLASS_NAME_RIGHT + directionalClassName = CLASS_NAME_END orderClassName = CLASS_NAME_PREV eventDirectionName = DIRECTION_RIGHT } diff --git a/js/src/dropdown.js b/js/src/dropdown.js index 7b3bf5b4ec..0ac108ab81 100644 --- a/js/src/dropdown.js +++ b/js/src/dropdown.js @@ -11,6 +11,7 @@ import { getElementFromSelector, isElement, isVisible, + isRTL, noop, typeCheckConfig } from './util/index' @@ -53,9 +54,9 @@ const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}` const CLASS_NAME_DISABLED = 'disabled' const CLASS_NAME_SHOW = 'show' const CLASS_NAME_DROPUP = 'dropup' -const CLASS_NAME_DROPRIGHT = 'dropright' -const CLASS_NAME_DROPLEFT = 'dropleft' -const CLASS_NAME_MENURIGHT = 'dropdown-menu-right' +const CLASS_NAME_DROPEND = 'dropend' +const CLASS_NAME_DROPSTART = 'dropstart' +const CLASS_NAME_MENUEND = 'dropdown-menu-end' const CLASS_NAME_NAVBAR = 'navbar' const CLASS_NAME_POSITION_STATIC = 'position-static' @@ -65,12 +66,12 @@ const SELECTOR_MENU = '.dropdown-menu' const SELECTOR_NAVBAR_NAV = '.navbar-nav' const SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)' -const PLACEMENT_TOP = 'top-start' -const PLACEMENT_TOPEND = 'top-end' -const PLACEMENT_BOTTOM = 'bottom-start' -const PLACEMENT_BOTTOMEND = 'bottom-end' -const PLACEMENT_RIGHT = 'right-start' -const PLACEMENT_LEFT = 'left-start' +const PLACEMENT_TOP = isRTL ? 'top-end' : 'top-start' +const PLACEMENT_TOPEND = isRTL ? 'top-start' : 'top-end' +const PLACEMENT_BOTTOM = isRTL ? 'bottom-end' : 'bottom-start' +const PLACEMENT_BOTTOMEND = isRTL ? 'bottom-start' : 'bottom-end' +const PLACEMENT_RIGHT = isRTL ? 'left-start' : 'right-start' +const PLACEMENT_LEFT = isRTL ? 'right-start' : 'left-start' const Default = { offset: 0, @@ -277,14 +278,14 @@ class Dropdown extends BaseComponent { // Handle dropup if (parentDropdown.classList.contains(CLASS_NAME_DROPUP)) { - placement = this._menu.classList.contains(CLASS_NAME_MENURIGHT) ? + placement = this._menu.classList.contains(CLASS_NAME_MENUEND) ? PLACEMENT_TOPEND : PLACEMENT_TOP - } else if (parentDropdown.classList.contains(CLASS_NAME_DROPRIGHT)) { + } else if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) { placement = PLACEMENT_RIGHT - } else if (parentDropdown.classList.contains(CLASS_NAME_DROPLEFT)) { + } else if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) { placement = PLACEMENT_LEFT - } else if (this._menu.classList.contains(CLASS_NAME_MENURIGHT)) { + } else if (this._menu.classList.contains(CLASS_NAME_MENUEND)) { placement = PLACEMENT_BOTTOMEND } diff --git a/js/src/modal.js b/js/src/modal.js index a9cf8ae6cf..94bf95f8ad 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -13,6 +13,7 @@ import { getElementFromSelector, getTransitionDurationFromElement, isVisible, + isRTL, reflow, typeCheckConfig } from './util/index' @@ -435,11 +436,11 @@ class Modal extends BaseComponent { const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight - if (!this._isBodyOverflowing && isModalOverflowing) { + if ((!this._isBodyOverflowing && isModalOverflowing && !isRTL) || (this._isBodyOverflowing && !isModalOverflowing && isRTL)) { this._element.style.paddingLeft = `${this._scrollbarWidth}px` } - if (this._isBodyOverflowing && !isModalOverflowing) { + if ((this._isBodyOverflowing && !isModalOverflowing && !isRTL) || (!this._isBodyOverflowing && isModalOverflowing && isRTL)) { this._element.style.paddingRight = `${this._scrollbarWidth}px` } } diff --git a/js/src/popover.js b/js/src/popover.js index 66dcb47b90..d8bd92eefb 100644 --- a/js/src/popover.js +++ b/js/src/popover.js @@ -115,7 +115,7 @@ class Popover extends Tooltip { // Private _addAttachmentClass(attachment) { - this.getTipElement().classList.add(`${CLASS_PREFIX}-${attachment}`) + this.getTipElement().classList.add(`${CLASS_PREFIX}-${this.updateAttachment(attachment)}`) } _getContent() { diff --git a/js/src/tooltip.js b/js/src/tooltip.js index 25599bb42f..17148ed9a6 100644 --- a/js/src/tooltip.js +++ b/js/src/tooltip.js @@ -14,6 +14,7 @@ import { getTransitionDurationFromElement, getUID, isElement, + isRTL, noop, typeCheckConfig } from './util/index' @@ -64,9 +65,9 @@ const DefaultType = { const AttachmentMap = { AUTO: 'auto', TOP: 'top', - RIGHT: 'right', + RIGHT: isRTL ? 'left' : 'right', BOTTOM: 'bottom', - LEFT: 'left' + LEFT: isRTL ? 'right' : 'left' } const Default = { @@ -453,6 +454,18 @@ class Tooltip extends BaseComponent { return title } + updateAttachment(attachment) { + if (attachment === 'right') { + return 'end' + } + + if (attachment === 'left') { + return 'start' + } + + return attachment + } + // Private _getPopperConfig(attachment) { @@ -485,7 +498,7 @@ class Tooltip extends BaseComponent { } _addAttachmentClass(attachment) { - this.getTipElement().classList.add(`${CLASS_PREFIX}-${attachment}`) + this.getTipElement().classList.add(`${CLASS_PREFIX}-${this.updateAttachment(attachment)}`) } _getOffset() { diff --git a/js/src/util/index.js b/js/src/util/index.js index 874827b168..96cadc65bc 100644 --- a/js/src/util/index.js +++ b/js/src/util/index.js @@ -186,6 +186,8 @@ const onDOMContentLoaded = callback => { } } +const isRTL = document.documentElement.dir === 'rtl' + export { TRANSITION_END, getUID, @@ -201,5 +203,6 @@ export { noop, reflow, getjQuery, - onDOMContentLoaded + onDOMContentLoaded, + isRTL } diff --git a/js/tests/unit/dropdown.spec.js b/js/tests/unit/dropdown.spec.js index 145763d20f..f6a5feb1b9 100644 --- a/js/tests/unit/dropdown.spec.js +++ b/js/tests/unit/dropdown.spec.js @@ -227,7 +227,7 @@ describe('Dropdown', () => { fixtureEl.innerHTML = [ '<div class="dropdown">', ' <button class="btn dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">Dropdown</button>', - ' <div class="dropdown-menu dropdown-menu-right">', + ' <div class="dropdown-menu dropdown-menu-end">', ' <a class="dropdown-item" href="#">Secondary link</a>', ' </div>', '</div>' @@ -273,7 +273,7 @@ describe('Dropdown', () => { fixtureEl.innerHTML = [ '<div class="dropup">', ' <button class="btn dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">Dropdown</button>', - ' <div class="dropdown-menu dropdown-menu-right">', + ' <div class="dropdown-menu dropdown-menu-end">', ' <a class="dropdown-item" href="#">Secondary link</a>', ' </div>', '</div>' @@ -292,9 +292,9 @@ describe('Dropdown', () => { dropdown.toggle() }) - it('should toggle a dropright', done => { + it('should toggle a dropend', done => { fixtureEl.innerHTML = [ - '<div class="dropright">', + '<div class="dropend">', ' <button class="btn dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">Dropdown</button>', ' <div class="dropdown-menu">', ' <a class="dropdown-item" href="#">Secondary link</a>', @@ -303,10 +303,10 @@ describe('Dropdown', () => { ].join('') const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') - const droprightEl = fixtureEl.querySelector('.dropright') + const dropendEl = fixtureEl.querySelector('.dropend') const dropdown = new Dropdown(btnDropdown) - droprightEl.addEventListener('shown.bs.dropdown', () => { + dropendEl.addEventListener('shown.bs.dropdown', () => { expect(btnDropdown.classList.contains('show')).toEqual(true) expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true') done() @@ -315,9 +315,9 @@ describe('Dropdown', () => { dropdown.toggle() }) - it('should toggle a dropleft', done => { + it('should toggle a dropstart', done => { fixtureEl.innerHTML = [ - '<div class="dropleft">', + '<div class="dropstart">', ' <button class="btn dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">Dropdown</button>', ' <div class="dropdown-menu">', ' <a class="dropdown-item" href="#">Secondary link</a>', @@ -326,10 +326,10 @@ describe('Dropdown', () => { ].join('') const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') - const dropleftEl = fixtureEl.querySelector('.dropleft') + const dropstartEl = fixtureEl.querySelector('.dropstart') const dropdown = new Dropdown(btnDropdown) - dropleftEl.addEventListener('shown.bs.dropdown', () => { + dropstartEl.addEventListener('shown.bs.dropdown', () => { expect(btnDropdown.classList.contains('show')).toEqual(true) expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true') done() diff --git a/js/tests/unit/toast.spec.js b/js/tests/unit/toast.spec.js index a4ab4f76cd..cc873d1fe6 100644 --- a/js/tests/unit/toast.spec.js +++ b/js/tests/unit/toast.spec.js @@ -46,7 +46,7 @@ describe('Toast', () => { it('should close toast when close element with data-bs-dismiss attribute is set', done => { fixtureEl.innerHTML = [ '<div class="toast" data-bs-delay="1" data-bs-autohide="false" data-bs-animation="false">', - ' <button type="button" class="ml-2 mb-1 btn-close" data-bs-dismiss="toast" aria-label="Close"></button>', + ' <button type="button" class="ms-2 mb-1 btn-close" data-bs-dismiss="toast" aria-label="Close"></button>', '</div>' ].join('') @@ -78,7 +78,7 @@ describe('Toast', () => { fixtureEl.innerHTML = [ '<div class="toast" data-bs-autohide="false" data-bs-animation="false">', - ' <button type="button" class="ml-2 mb-1 btn-close" data-bs-dismiss="toast" aria-label="Close"></button>', + ' <button type="button" class="ms-2 mb-1 btn-close" data-bs-dismiss="toast" aria-label="Close"></button>', '</div>' ].join('') diff --git a/js/tests/unit/tooltip.spec.js b/js/tests/unit/tooltip.spec.js index b119807511..9ea9096de9 100644 --- a/js/tests/unit/tooltip.spec.js +++ b/js/tests/unit/tooltip.spec.js @@ -886,6 +886,40 @@ describe('Tooltip', () => { }) }) + describe('updateAttachment', () => { + it('should use end class name when right placement specified', done => { + fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + placement: 'right' + }) + + tooltipEl.addEventListener('inserted.bs.tooltip', () => { + expect(tooltip.getTipElement().classList.contains('bs-tooltip-end')).toEqual(true) + done() + }) + + tooltip.show() + }) + + it('should use start class name when left placement specified', done => { + fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + placement: 'left' + }) + + tooltipEl.addEventListener('inserted.bs.tooltip', () => { + expect(tooltip.getTipElement().classList.contains('bs-tooltip-start')).toEqual(true) + done() + }) + + tooltip.show() + }) + }) + describe('setElementContent', () => { it('should do nothing if the element is null', () => { fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">' diff --git a/js/tests/visual/dropdown.html b/js/tests/visual/dropdown.html index 9dad43543e..930940a157 100644 --- a/js/tests/visual/dropdown.html +++ b/js/tests/visual/dropdown.html @@ -90,9 +90,9 @@ <div class="btn-group"> <button type="button" class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false"> - This dropdown's menu is right-aligned + This dropdown's menu is end-aligned </button> - <div class="dropdown-menu dropdown-menu-right"> + <div class="dropdown-menu dropdown-menu-end"> <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> @@ -102,19 +102,19 @@ <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> + <a href="#" class="btn btn-secondary">Dropup split align end</a> <button type="button" id="dropdown-page-subheader-button-3" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false"> <span class="visually-hidden">Product actions</span> </button> - <div class="dropdown-menu dropdown-menu-right"> + <div class="dropdown-menu dropdown-menu-end"> <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 dropup"> - <button type="button" class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">Dropup align right</button> - <div class="dropdown-menu dropdown-menu-right"> + <button type="button" class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">Dropup align end</button> + <div class="dropdown-menu dropdown-menu-end"> <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> @@ -123,8 +123,8 @@ </div> <div class="col-sm-12 mt-4"> - <div class="btn-group dropright" role="group"> - <a href="#" class="btn btn-secondary">Dropright split</a> + <div class="btn-group dropend" role="group"> + <a href="#" class="btn btn-secondary">Dropend split</a> <button type="button" id="dropdown-page-subheader-button-4" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false"> <span class="visually-hidden">Product actions</span> </button> @@ -134,9 +134,9 @@ <button class="dropdown-item" type="button">Something else here with a long text</button> </div> </div> - <div class="btn-group dropright"> + <div class="btn-group dropend"> <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuRight" data-bs-toggle="dropdown" aria-expanded="false"> - Dropright + Dropend </button> <div class="dropdown-menu" aria-labelledby="dropdownMenuRight"> <button class="dropdown-item" type="button">Action</button> @@ -144,9 +144,9 @@ <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> + <!-- dropstart --> + <div class="btn-group dropstart" role="group"> + <a href="#" class="btn btn-secondary">Dropstart split</a> <button type="button" id="dropdown-page-subheader-button-5" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false"> <span class="visually-hidden">Product actions</span> </button> @@ -156,11 +156,11 @@ <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-bs-toggle="dropdown" aria-expanded="false"> - Dropleft + <div class="btn-group dropstart"> + <button class="btn btn-secondary dropdown-toggle" type="button" id="dropstartMenu" data-bs-toggle="dropdown" aria-expanded="false"> + Dropstart </button> - <div class="dropdown-menu" aria-labelledby="dropleftMenu"> + <div class="dropdown-menu" aria-labelledby="dropstartMenu"> <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> diff --git a/js/tests/visual/popover.html b/js/tests/visual/popover.html index e33de5f0bd..c758253969 100644 --- a/js/tests/visual/popover.html +++ b/js/tests/visual/popover.html @@ -19,7 +19,7 @@ </button> <button type="button" class="btn btn-secondary" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="right" data-bs-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus."> - Popover on right + Popover on end </button> <button type="button" class="btn btn-secondary" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="bottom" data-bs-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus."> @@ -27,7 +27,7 @@ </button> <button type="button" class="btn btn-secondary" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="left" data-bs-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus."> - Popover on left + Popover on start </button> </div> diff --git a/js/tests/visual/scrollspy.html b/js/tests/visual/scrollspy.html index c86927d991..7b07932ebd 100644 --- a/js/tests/visual/scrollspy.html +++ b/js/tests/visual/scrollspy.html @@ -16,7 +16,7 @@ <span class="navbar-toggler-icon"></span> </button> <div class="navbar-collapse collapse" id="navbarSupportedContent"> - <ul class="navbar-nav mr-auto"> + <ul class="navbar-nav me-auto"> <li class="nav-item"> <a class="nav-link" href="#fat">@fat</a> </li> diff --git a/js/tests/visual/toast.html b/js/tests/visual/toast.html index c26278d948..4765026f33 100644 --- a/js/tests/visual/toast.html +++ b/js/tests/visual/toast.html @@ -28,8 +28,8 @@ <div class="notifications"> <div id="toastAutoHide" class="toast" role="alert" aria-live="assertive" aria-atomic="true" data-bs-delay="2000"> <div class="toast-header"> - <span class="d-block bg-primary rounded mr-2" style="width: 20px; height: 20px;"></span> - <strong class="mr-auto">Bootstrap</strong> + <span class="d-block bg-primary rounded me-2" style="width: 20px; height: 20px;"></span> + <strong class="me-auto">Bootstrap</strong> <small>11 mins ago</small> </div> <div class="toast-body"> @@ -39,10 +39,10 @@ <div class="toast" data-bs-autohide="false" role="alert" aria-live="assertive" aria-atomic="true"> <div class="toast-header"> - <span class="d-block bg-primary rounded mr-2" style="width: 20px; height: 20px;"></span> - <strong class="mr-auto">Bootstrap</strong> + <span class="d-block bg-primary rounded me-2" style="width: 20px; height: 20px;"></span> + <strong class="me-auto">Bootstrap</strong> <small class="text-muted">2 seconds ago</small> - <button type="button" class="ml-2 mb-1 btn-close" data-bs-dismiss="toast" aria-label="Close"></button> + <button type="button" class="ms-2 mb-1 btn-close" data-bs-dismiss="toast" aria-label="Close"></button> </div> <div class="toast-body"> Heads up, toasts will stack automatically diff --git a/js/tests/visual/tooltip.html b/js/tests/visual/tooltip.html index 93536a0443..bade26a6c0 100644 --- a/js/tests/visual/tooltip.html +++ b/js/tests/visual/tooltip.html @@ -10,7 +10,6 @@ border: 1px solid; width: 100px; height: 50px; - border: 1px solid; margin-left: 50px; transform: rotate(270deg); margin-top: 100px; @@ -34,13 +33,13 @@ Tooltip on top </button> <button type="button" class="btn btn-secondary" data-bs-toggle="tooltip" data-bs-placement="right" title="Tooltip on right"> - Tooltip on right + Tooltip on end </button> <button type="button" class="btn btn-secondary" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Tooltip on bottom"> Tooltip on bottom </button> <button type="button" class="btn btn-secondary" data-bs-toggle="tooltip" data-bs-placement="left" title="Tooltip on left"> - Tooltip on left + Tooltip on start </button> </p> </div> diff --git a/scss/_breadcrumb.scss b/scss/_breadcrumb.scss index f1ab3e8b9d..f7fafe743a 100644 --- a/scss/_breadcrumb.scss +++ b/scss/_breadcrumb.scss @@ -18,7 +18,7 @@ float: left; // Suppress inline spacings and underlining of the separator padding-right: $breadcrumb-item-padding-x; color: $breadcrumb-divider-color; - content: var(--#{$variable-prefix}breadcrumb-divider, escape-svg($breadcrumb-divider)); + content: var(--#{$variable-prefix}breadcrumb-divider, escape-svg($breadcrumb-divider)) #{"/* rtl:"} var(--#{$variable-prefix}breadcrumb-divider, escape-svg($breadcrumb-divider-flipped)) #{"*/"}; } } diff --git a/scss/_button-group.scss b/scss/_button-group.scss index abb363a840..13aa0569a5 100644 --- a/scss/_button-group.scss +++ b/scss/_button-group.scss @@ -43,7 +43,7 @@ // Reset rounded corners > .btn:not(:last-child):not(.dropdown-toggle), > .btn-group:not(:last-child) > .btn { - @include border-right-radius(0); + @include border-end-radius(0); } // The left radius should be 0 if the button is: @@ -53,7 +53,7 @@ > .btn:nth-child(n + 3), > :not(.btn-check) + .btn, > .btn-group:not(:first-child) > .btn { - @include border-left-radius(0); + @include border-start-radius(0); } } @@ -75,11 +75,11 @@ &::after, .dropup &::after, - .dropright &::after { + .dropend &::after { margin-left: 0; } - .dropleft &::before { + .dropstart &::before { margin-right: 0; } } diff --git a/scss/_card.scss b/scss/_card.scss index 9b0f4969a6..4b2eebf135 100644 --- a/scss/_card.scss +++ b/scss/_card.scss @@ -69,7 +69,7 @@ } + .card-link { - margin-left: $card-spacer-x; + margin-left: $card-spacer-x #{"/* rtl:ignore */"}; } } @@ -181,7 +181,7 @@ // Handle rounded corners @if $enable-rounded { &:not(:last-child) { - @include border-right-radius(0); + @include border-end-radius(0); .card-img-top, .card-header { @@ -196,7 +196,7 @@ } &:not(:first-child) { - @include border-left-radius(0); + @include border-start-radius(0); .card-img-top, .card-header { diff --git a/scss/_carousel.scss b/scss/_carousel.scss index ef77cbb618..d2e42bc10b 100644 --- a/scss/_carousel.scss +++ b/scss/_carousel.scss @@ -3,12 +3,12 @@ // 1. .carousel.pointer-event should ideally be pan-y (to allow for users to scroll vertically) // even when their scroll action started on a carousel, but for compatibility (with Firefox) // we're preventing all actions instead -// 2. The .carousel-item-left and .carousel-item-right is used to indicate where +// 2. The .carousel-item-start and .carousel-item-end is used to indicate where // the active slide is heading. // 3. .active.carousel-item is the current slide. -// 4. .active.carousel-item-left and .active.carousel-item-right is the current +// 4. .active.carousel-item-start and .active.carousel-item-end is the current // slide in its in-transition state. Only one of these occurs at a time. -// 5. .carousel-item-next.carousel-item-left and .carousel-item-prev.carousel-item-right +// 5. .carousel-item-next.carousel-item-start and .carousel-item-prev.carousel-item-end // is the upcoming slide in transition. .carousel { @@ -42,16 +42,19 @@ display: block; } -.carousel-item-next:not(.carousel-item-left), -.active.carousel-item-right { +/* rtl:begin:ignore */ +.carousel-item-next:not(.carousel-item-start), +.active.carousel-item-end { transform: translateX(100%); } -.carousel-item-prev:not(.carousel-item-right), -.active.carousel-item-left { +.carousel-item-prev:not(.carousel-item-end), +.active.carousel-item-start { transform: translateX(-100%); } +/* rtl:end:ignore */ + // // Alternate transitions @@ -65,14 +68,14 @@ } .carousel-item.active, - .carousel-item-next.carousel-item-left, - .carousel-item-prev.carousel-item-right { + .carousel-item-next.carousel-item-start, + .carousel-item-prev.carousel-item-end { z-index: 1; opacity: 1; } - .active.carousel-item-left, - .active.carousel-item-right { + .active.carousel-item-start, + .active.carousel-item-end { z-index: 0; opacity: 0; @include transition(opacity 0s $carousel-transition-duration); @@ -128,6 +131,15 @@ background-position: 50%; background-size: 100% 100%; } + +/* rtl:options: { + "autoRename": true, + "stringMap":[ { + "name" : "prev-next", + "search" : "prev", + "replace" : "next" + } ] +} */ .carousel-control-prev-icon { background-image: escape-svg($carousel-control-prev-icon-bg); } @@ -135,7 +147,6 @@ background-image: escape-svg($carousel-control-next-icon-bg); } - // Optional indicator pips // // Add an ordered list with the following class and add a list item for each diff --git a/scss/_dropdown.scss b/scss/_dropdown.scss index bff51db6c6..7cad640096 100644 --- a/scss/_dropdown.scss +++ b/scss/_dropdown.scss @@ -1,8 +1,8 @@ // The dropdown wrapper (`<div>`) .dropup, -.dropright, +.dropend, .dropdown, -.dropleft { +.dropstart { position: relative; } @@ -39,14 +39,14 @@ @include media-breakpoint-up($breakpoint) { $infix: breakpoint-infix($breakpoint, $grid-breakpoints); - .dropdown-menu#{$infix}-left { - right: auto; - left: 0; + .dropdown-menu#{$infix}-start { + right: auto #{"/* rtl:ignore */"}; + left: 0 #{"/* rtl:ignore */"}; } - .dropdown-menu#{$infix}-right { - right: 0; - left: auto; + .dropdown-menu#{$infix}-end { + right: 0 #{"/* rtl:ignore */"}; + left: auto #{"/* rtl:ignore */"}; } } } @@ -67,7 +67,7 @@ } } -.dropright { +.dropend { .dropdown-menu { top: 0; right: auto; @@ -77,14 +77,14 @@ } .dropdown-toggle { - @include caret(right); + @include caret(end); &::after { vertical-align: 0; } } } -.dropleft { +.dropstart { .dropdown-menu { top: 0; right: 100%; @@ -94,7 +94,7 @@ } .dropdown-toggle { - @include caret(left); + @include caret(start); &::before { vertical-align: 0; } @@ -110,9 +110,11 @@ &[x-placement^="left"] { right: auto; bottom: auto; + left: auto; } } + // Dividers (basically an `<hr>`) within the dropdown .dropdown-divider { height: 0; diff --git a/scss/_list-group.scss b/scss/_list-group.scss index 3d82f8f439..a95adc181c 100644 --- a/scss/_list-group.scss +++ b/scss/_list-group.scss @@ -99,13 +99,13 @@ > .list-group-item { &:first-child { - @include border-bottom-left-radius($list-group-border-radius); - @include border-top-right-radius(0); + @include border-bottom-start-radius($list-group-border-radius); + @include border-top-end-radius(0); } &:last-child { - @include border-top-right-radius($list-group-border-radius); - @include border-bottom-left-radius(0); + @include border-top-end-radius($list-group-border-radius); + @include border-bottom-start-radius(0); } &.active { diff --git a/scss/_navbar.scss b/scss/_navbar.scss index 607c3170c6..852328aca1 100644 --- a/scss/_navbar.scss +++ b/scss/_navbar.scss @@ -56,7 +56,7 @@ .navbar-brand { padding-top: $navbar-brand-padding-y; padding-bottom: $navbar-brand-padding-y; - margin-right: $navbar-brand-margin-right; + margin-right: $navbar-brand-margin-end; @include font-size($navbar-brand-font-size); text-decoration: if($link-decoration == none, null, none); white-space: nowrap; diff --git a/scss/_pagination.scss b/scss/_pagination.scss index 819f6d1eb0..04bf82536f 100644 --- a/scss/_pagination.scss +++ b/scss/_pagination.scss @@ -31,7 +31,7 @@ .page-item { &:not(:first-child) .page-link { - margin-left: $pagination-margin-left; + margin-left: $pagination-margin-start; } &.active .page-link { diff --git a/scss/_popover.scss b/scss/_popover.scss index 55bfe1f9ab..6688f729c2 100644 --- a/scss/_popover.scss +++ b/scss/_popover.scss @@ -1,7 +1,7 @@ .popover { position: absolute; top: 0; - left: 0; + left: 0 #{"/* rtl:ignore */"}; z-index: $zindex-popover; display: block; max-width: $popover-max-width; @@ -55,25 +55,25 @@ } } -.bs-popover-right { - margin-left: $popover-arrow-height; +.bs-popover-end { + margin-left: $popover-arrow-height #{"/* rtl:ignore */"}; > .popover-arrow { - left: subtract(-$popover-arrow-height, $popover-border-width); + left: subtract(-$popover-arrow-height, $popover-border-width) #{"/* rtl:ignore */"}; width: $popover-arrow-height; height: $popover-arrow-width; margin: $popover-border-radius 0; // make sure the arrow does not touch the popover's rounded corners &::before { - left: 0; - border-width: ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2) 0; - border-right-color: $popover-arrow-outer-color; + left: 0 #{"/* rtl:ignore */"}; + border-width: ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2) 0 #{"/* rtl:ignore */"}; + border-right-color: $popover-arrow-outer-color #{"/* rtl:ignore */"}; } &::after { - left: $popover-border-width; - border-width: ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2) 0; - border-right-color: $popover-arrow-color; + left: $popover-border-width #{"/* rtl:ignore */"}; + border-width: ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2) 0 #{"/* rtl:ignore */"}; + border-right-color: $popover-arrow-color #{"/* rtl:ignore */"}; } } } @@ -110,25 +110,25 @@ } } -.bs-popover-left { - margin-right: $popover-arrow-height; +.bs-popover-start { + margin-right: $popover-arrow-height #{"/* rtl:ignore */"}; > .popover-arrow { - right: subtract(-$popover-arrow-height, $popover-border-width); + right: subtract(-$popover-arrow-height, $popover-border-width) #{"/* rtl:ignore */"}; width: $popover-arrow-height; height: $popover-arrow-width; margin: $popover-border-radius 0; // make sure the arrow does not touch the popover's rounded corners &::before { - right: 0; - border-width: ($popover-arrow-width / 2) 0 ($popover-arrow-width / 2) $popover-arrow-height; - border-left-color: $popover-arrow-outer-color; + right: 0 #{"/* rtl:ignore */"}; + border-width: ($popover-arrow-width / 2) 0 ($popover-arrow-width / 2) $popover-arrow-height #{"/* rtl:ignore */"}; + border-left-color: $popover-arrow-outer-color #{"/* rtl:ignore */"}; } &::after { - right: $popover-border-width; - border-width: ($popover-arrow-width / 2) 0 ($popover-arrow-width / 2) $popover-arrow-height; - border-left-color: $popover-arrow-color; + right: $popover-border-width #{"/* rtl:ignore */"}; + border-width: ($popover-arrow-width / 2) 0 ($popover-arrow-width / 2) $popover-arrow-height #{"/* rtl:ignore */"}; + border-left-color: $popover-arrow-color #{"/* rtl:ignore */"}; } } } @@ -138,17 +138,16 @@ @extend .bs-popover-top; } &[x-placement^="right"] { - @extend .bs-popover-right; + @extend .bs-popover-end; } &[x-placement^="bottom"] { @extend .bs-popover-bottom; } &[x-placement^="left"] { - @extend .bs-popover-left; + @extend .bs-popover-start; } } - // Offset the popover to account for the popover arrow .popover-header { padding: $popover-header-padding-y $popover-header-padding-x; diff --git a/scss/_reboot.scss b/scss/_reboot.scss index 61e9c4af66..50ba7431b9 100644 --- a/scss/_reboot.scss +++ b/scss/_reboot.scss @@ -290,6 +290,8 @@ kbd, samp { font-family: $font-family-code; @include font-size(1em); // Correct the odd `em` font sizing in all browsers. + direction: ltr #{"/* rtl:ignore */"}; + unicode-bidi: bidi-override; } // 1. Remove browser default top margin @@ -551,6 +553,20 @@ legend { -webkit-appearance: textfield; // 2 } +// 1. A few input types should stay LTR +// See https://rtlstyling.com/posts/rtl-styling#form-inputs +// 2. RTL only output +// See https://rtlcss.com/learn/usage-guide/control-directives/#raw + +/* rtl:raw: +[type="tel"], +[type="url"], +[type="email"], +[type="number"] { + direction: ltr; +} +*/ + // Remove the inner padding in Chrome and Safari on macOS. ::-webkit-search-decoration { diff --git a/scss/_spinners.scss b/scss/_spinners.scss index e932aacd9a..7444ed1d12 100644 --- a/scss/_spinners.scss +++ b/scss/_spinners.scss @@ -3,7 +3,7 @@ // @keyframes spinner-border { - to { transform: rotate(360deg); } + to { transform: rotate(360deg) #{"/* rtl:ignore */"}; } } .spinner-border { diff --git a/scss/_tooltip.scss b/scss/_tooltip.scss index 4d405e0319..a98ff4db5f 100644 --- a/scss/_tooltip.scss +++ b/scss/_tooltip.scss @@ -43,18 +43,18 @@ } } -.bs-tooltip-right { +.bs-tooltip-end { padding: 0 $tooltip-arrow-height; .tooltip-arrow { - left: 0; + left: 0 #{"/* rtl:ignore */"}; width: $tooltip-arrow-height; height: $tooltip-arrow-width; &::before { - right: 0; - border-width: ($tooltip-arrow-width / 2) $tooltip-arrow-height ($tooltip-arrow-width / 2) 0; - border-right-color: $tooltip-arrow-color; + right: 0 #{"/* rtl:ignore */"}; + border-width: ($tooltip-arrow-width / 2) $tooltip-arrow-height ($tooltip-arrow-width / 2) 0 #{"/* rtl:ignore */"}; + border-right-color: $tooltip-arrow-color #{"/* rtl:ignore */"}; } } } @@ -73,18 +73,18 @@ } } -.bs-tooltip-left { +.bs-tooltip-start { padding: 0 $tooltip-arrow-height; .tooltip-arrow { - right: 0; + right: 0 #{"/* rtl:ignore */"}; width: $tooltip-arrow-height; height: $tooltip-arrow-width; &::before { - left: 0; - border-width: ($tooltip-arrow-width / 2) 0 ($tooltip-arrow-width / 2) $tooltip-arrow-height; - border-left-color: $tooltip-arrow-color; + left: 0 #{"/* rtl:ignore */"}; + border-width: ($tooltip-arrow-width / 2) 0 ($tooltip-arrow-width / 2) $tooltip-arrow-height #{"/* rtl:ignore */"}; + border-left-color: $tooltip-arrow-color #{"/* rtl:ignore */"}; } } } @@ -94,13 +94,13 @@ @extend .bs-tooltip-top; } &[x-placement^="right"] { - @extend .bs-tooltip-right; + @extend .bs-tooltip-end; } &[x-placement^="bottom"] { @extend .bs-tooltip-bottom; } &[x-placement^="left"] { - @extend .bs-tooltip-left; + @extend .bs-tooltip-start; } } diff --git a/scss/_utilities.scss b/scss/_utilities.scss index 03c71d1c24..dacd8b2891 100644 --- a/scss/_utilities.scss +++ b/scss/_utilities.scss @@ -12,7 +12,11 @@ $utilities: map-merge( "float": ( responsive: true, property: float, - values: left right none + values: ( + start: left, + end: right, + none: none, + ) ), "overflow": ( property: overflow, @@ -47,12 +51,14 @@ $utilities: map-merge( property: bottom, values: $position-values ), - "left": ( + "start": ( property: left, + class: start, values: $position-values ), - "right": ( + "end": ( property: right, + class: end, values: $position-values ), "translate-middle": ( @@ -76,8 +82,9 @@ $utilities: map-merge( 0: 0, ) ), - "border-right": ( + "border-end": ( property: border-right, + class: border-end, values: ( null: $border-width solid $border-color, 0: 0, @@ -90,8 +97,9 @@ $utilities: map-merge( 0: 0, ) ), - "border-left": ( + "border-start": ( property: border-left, + class: border-start, values: ( null: $border-width solid $border-color, 0: 0, @@ -288,10 +296,10 @@ $utilities: map-merge( class: mt, values: map-merge($spacers, (auto: auto)) ), - "margin-right": ( + "margin-end": ( responsive: true, property: margin-right, - class: mr, + class: me, values: map-merge($spacers, (auto: auto)) ), "margin-bottom": ( @@ -300,10 +308,10 @@ $utilities: map-merge( class: mb, values: map-merge($spacers, (auto: auto)) ), - "margin-left": ( + "margin-start": ( responsive: true, property: margin-left, - class: ml, + class: ms, values: map-merge($spacers, (auto: auto)) ), // Negative margin utilities @@ -331,10 +339,10 @@ $utilities: map-merge( class: mt, values: $negative-spacers ), - "negative-margin-right": ( + "negative-margin-end": ( responsive: true, property: margin-right, - class: mr, + class: me, values: $negative-spacers ), "negative-margin-bottom": ( @@ -343,10 +351,10 @@ $utilities: map-merge( class: mb, values: $negative-spacers ), - "negative-margin-left": ( + "negative-margin-start": ( responsive: true, property: margin-left, - class: ml, + class: ms, values: $negative-spacers ), // Padding utilities @@ -374,10 +382,10 @@ $utilities: map-merge( class: pt, values: $spacers ), - "padding-right": ( + "padding-end": ( responsive: true, property: padding-right, - class: pr, + class: pe, values: $spacers ), "padding-bottom": ( @@ -386,10 +394,10 @@ $utilities: map-merge( class: pb, values: $spacers ), - "padding-left": ( + "padding-start": ( responsive: true, property: padding-left, - class: pl, + class: ps, values: $spacers ), // Text @@ -424,7 +432,11 @@ $utilities: map-merge( responsive: true, property: text-align, class: text, - values: left right center + values: ( + start: left, + end: right, + center: center, + ) ), "color": ( property: color, @@ -483,7 +495,8 @@ $utilities: map-merge( "word-wrap": ( property: word-wrap word-break, class: text, - values: (break: break-word) + values: (break: break-word), + rtl: false ), "font-family": ( property: font-family, @@ -517,9 +530,9 @@ $utilities: map-merge( class: rounded-top, values: (null: $border-radius) ), - "rounded-right": ( + "rounded-end": ( property: border-top-right-radius border-bottom-right-radius, - class: rounded-right, + class: rounded-end, values: (null: $border-radius) ), "rounded-bottom": ( @@ -527,9 +540,9 @@ $utilities: map-merge( class: rounded-bottom, values: (null: $border-radius) ), - "rounded-left": ( + "rounded-start": ( property: border-bottom-left-radius border-top-left-radius, - class: rounded-left, + class: rounded-start, values: (null: $border-radius) ), "visibility": ( diff --git a/scss/_variables.scss b/scss/_variables.scss index 3a551ffb2b..b97e520d7c 100644 --- a/scss/_variables.scss +++ b/scss/_variables.scss @@ -679,7 +679,7 @@ $input-transition: border-color .15s ease-in-out, box-shado $form-check-input-width: 1em !default; $form-check-min-height: $font-size-base * $line-height-base !default; -$form-check-padding-left: $form-check-input-width + .5em !default; +$form-check-padding-start: $form-check-input-width + .5em !default; $form-check-margin-bottom: .125rem !default; $form-check-label-color: null !default; $form-check-label-cursor: null !default; @@ -711,7 +711,7 @@ $form-check-btn-check-disabled-opacity: $btn-disabled-opacity !default; $form-switch-color: rgba(0, 0, 0, .25) !default; $form-switch-width: 2em !default; -$form-switch-padding-left: $form-switch-width + .5em !default; +$form-switch-padding-start: $form-switch-width + .5em !default; $form-switch-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#{$form-switch-color}'/></svg>") !default; $form-switch-border-radius: $form-switch-width !default; @@ -722,7 +722,7 @@ $form-switch-checked-color: $component-active-color !default; $form-switch-checked-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#{$form-switch-checked-color}'/></svg>") !default; $form-switch-checked-bg-position: right center !default; -$form-check-inline-margin-right: 1rem !default; +$form-check-inline-margin-end: 1rem !default; $input-group-addon-padding-y: $input-padding-y !default; $input-group-addon-padding-x: $input-padding-x !default; @@ -748,9 +748,9 @@ $form-select-bg-size: 16px 12px !default; // In pixels because ima $form-select-indicator-color: $gray-800 !default; $form-select-indicator: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path fill='none' stroke='#{$form-select-indicator-color}' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/></svg>") !default; -$form-select-feedback-icon-padding-right: add(1em * .75, (2 * $form-select-padding-y * .75) + $form-select-padding-x + $form-select-indicator-padding) !default; -$form-select-feedback-icon-position: center right ($form-select-padding-x + $form-select-indicator-padding) !default; -$form-select-feedback-icon-size: $input-height-inner-half $input-height-inner-half !default; +$form-select-feedback-icon-padding-end: add(1em * .75, (2 * $form-select-padding-y * .75) + $form-select-padding-x + $form-select-indicator-padding) !default; +$form-select-feedback-icon-position: center right ($form-select-padding-x + $form-select-indicator-padding) !default; +$form-select-feedback-icon-size: $input-height-inner-half $input-height-inner-half !default; $form-select-border-width: $input-border-width !default; $form-select-border-color: $input-border-color !default; @@ -879,7 +879,7 @@ $navbar-brand-font-size: $font-size-lg !default; $nav-link-height: $font-size-base * $line-height-base + $nav-link-padding-y * 2 !default; $navbar-brand-height: $navbar-brand-font-size * $line-height-base !default; $navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default; -$navbar-brand-margin-right: 1rem !default; +$navbar-brand-margin-end: 1rem !default; $navbar-toggler-padding-y: .25rem !default; $navbar-toggler-padding-x: .75rem !default; @@ -969,7 +969,7 @@ $pagination-color: $link-color !default; $pagination-bg: $white !default; $pagination-border-width: $border-width !default; $pagination-border-radius: $border-radius !default; -$pagination-margin-left: -$pagination-border-width !default; +$pagination-margin-start: -$pagination-border-width !default; $pagination-border-color: $gray-300 !default; $pagination-focus-color: $link-hover-color !default; @@ -1253,6 +1253,7 @@ $breadcrumb-bg: null !default; $breadcrumb-divider-color: $gray-600 !default; $breadcrumb-active-color: $gray-600 !default; $breadcrumb-divider: quote("/") !default; +$breadcrumb-divider-flipped: $breadcrumb-divider !default; $breadcrumb-border-radius: null !default; // Carousel diff --git a/scss/bootstrap-grid.scss b/scss/bootstrap-grid.scss index 3314b57d7e..1c836bf2f5 100644 --- a/scss/bootstrap-grid.scss +++ b/scss/bootstrap-grid.scss @@ -42,23 +42,23 @@ $utilities: map-get-multiple( "margin-x", "margin-y", "margin-top", - "margin-right", + "margin-end", "margin-bottom", - "margin-left", + "margin-start", "negative-margin", "negative-margin-x", "negative-margin-y", "negative-margin-top", - "negative-margin-right", + "negative-margin-end", "negative-margin-bottom", - "negative-margin-left", + "negative-margin-start", "padding", "padding-x", "padding-y", "padding-top", - "padding-right", + "padding-end", "padding-bottom", - "padding-left", + "padding-start", ) ); diff --git a/scss/forms/_form-check.scss b/scss/forms/_form-check.scss index 77af825f5f..1d6d87363d 100644 --- a/scss/forms/_form-check.scss +++ b/scss/forms/_form-check.scss @@ -5,12 +5,12 @@ .form-check { display: block; min-height: $form-check-min-height; - padding-left: $form-check-padding-left; + padding-left: $form-check-padding-start; margin-bottom: $form-check-margin-bottom; .form-check-input { float: left; - margin-left: $form-check-padding-left * -1; + margin-left: $form-check-padding-start * -1; } } @@ -105,11 +105,11 @@ // .form-switch { - padding-left: $form-switch-padding-left; + padding-left: $form-switch-padding-start; .form-check-input { width: $form-switch-width; - margin-left: $form-switch-padding-left * -1; + margin-left: $form-switch-padding-start * -1; background-image: escape-svg($form-switch-bg-image); background-position: left center; @include border-radius($form-switch-border-radius); @@ -132,7 +132,7 @@ .form-check-inline { display: inline-block; - margin-right: $form-check-inline-margin-right; + margin-right: $form-check-inline-margin-end; } .btn-check { diff --git a/scss/forms/_input-group.scss b/scss/forms/_input-group.scss index 2729eccbd5..140052936c 100644 --- a/scss/forms/_input-group.scss +++ b/scss/forms/_input-group.scss @@ -98,14 +98,14 @@ &:not(.has-validation) { > :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu), > .dropdown-toggle:nth-last-child(n + 3) { - @include border-right-radius(0); + @include border-end-radius(0); } } &.has-validation { > :nth-last-child(n + 3):not(.dropdown-toggle):not(.dropdown-menu), > .dropdown-toggle:nth-last-child(n + 4) { - @include border-right-radius(0); + @include border-end-radius(0); } } @@ -116,6 +116,6 @@ > :not(:first-child):not(.dropdown-menu)#{$validation-messages} { margin-left: -$input-border-width; - @include border-left-radius(0); + @include border-start-radius(0); } } diff --git a/scss/mixins/_border-radius.scss b/scss/mixins/_border-radius.scss index 70f5720441..819b8abd4c 100644 --- a/scss/mixins/_border-radius.scss +++ b/scss/mixins/_border-radius.scss @@ -30,7 +30,7 @@ } } -@mixin border-right-radius($radius: $border-radius) { +@mixin border-end-radius($radius: $border-radius) { @if $enable-rounded { border-top-right-radius: valid-radius($radius); border-bottom-right-radius: valid-radius($radius); @@ -44,32 +44,32 @@ } } -@mixin border-left-radius($radius: $border-radius) { +@mixin border-start-radius($radius: $border-radius) { @if $enable-rounded { border-top-left-radius: valid-radius($radius); border-bottom-left-radius: valid-radius($radius); } } -@mixin border-top-left-radius($radius: $border-radius) { +@mixin border-top-start-radius($radius: $border-radius) { @if $enable-rounded { border-top-left-radius: valid-radius($radius); } } -@mixin border-top-right-radius($radius: $border-radius) { +@mixin border-top-end-radius($radius: $border-radius) { @if $enable-rounded { border-top-right-radius: valid-radius($radius); } } -@mixin border-bottom-right-radius($radius: $border-radius) { +@mixin border-bottom-end-radius($radius: $border-radius) { @if $enable-rounded { border-bottom-right-radius: valid-radius($radius); } } -@mixin border-bottom-left-radius($radius: $border-radius) { +@mixin border-bottom-start-radius($radius: $border-radius) { @if $enable-rounded { border-bottom-left-radius: valid-radius($radius); } diff --git a/scss/mixins/_caret.scss b/scss/mixins/_caret.scss index 07d72280ce..fc1066914d 100644 --- a/scss/mixins/_caret.scss +++ b/scss/mixins/_caret.scss @@ -12,14 +12,14 @@ border-left: $caret-width solid transparent; } -@mixin caret-right { +@mixin caret-end { border-top: $caret-width solid transparent; border-right: 0; border-bottom: $caret-width solid transparent; border-left: $caret-width solid; } -@mixin caret-left { +@mixin caret-start { border-top: $caret-width solid transparent; border-right: $caret-width solid; border-bottom: $caret-width solid transparent; @@ -36,12 +36,12 @@ @include caret-down(); } @else if $direction == up { @include caret-up(); - } @else if $direction == right { - @include caret-right(); + } @else if $direction == end { + @include caret-end(); } } - @if $direction == left { + @if $direction == start { &::after { display: none; } @@ -51,7 +51,7 @@ margin-right: $caret-spacing; vertical-align: $caret-vertical-align; content: ""; - @include caret-left(); + @include caret-start(); } } diff --git a/scss/mixins/_forms.scss b/scss/mixins/_forms.scss index 9adc0debee..5e4cfd4883 100644 --- a/scss/mixins/_forms.scss +++ b/scss/mixins/_forms.scss @@ -79,7 +79,7 @@ border-color: $color; @if $enable-validation-icons { - padding-right: $form-select-feedback-icon-padding-right; + padding-right: $form-select-feedback-icon-padding-end; background-image: escape-svg($form-select-indicator), escape-svg($icon); background-position: $form-select-bg-position, $form-select-feedback-icon-position; background-size: $form-select-bg-size, $form-select-feedback-icon-size; diff --git a/scss/mixins/_pagination.scss b/scss/mixins/_pagination.scss index 52ad1e1212..9cb7fd8bcd 100644 --- a/scss/mixins/_pagination.scss +++ b/scss/mixins/_pagination.scss @@ -7,16 +7,16 @@ } .page-item { - @if $pagination-margin-left == (-$pagination-border-width) { + @if $pagination-margin-start == (-$pagination-border-width) { &:first-child { .page-link { - @include border-left-radius($border-radius); + @include border-start-radius($border-radius); } } &:last-child { .page-link { - @include border-right-radius($border-radius); + @include border-end-radius($border-radius); } } } @else { diff --git a/scss/mixins/_utilities.scss b/scss/mixins/_utilities.scss index 145839a39f..4d2370a0bf 100644 --- a/scss/mixins/_utilities.scss +++ b/scss/mixins/_utilities.scss @@ -41,7 +41,12 @@ } } + $is-rtl: map-get($utility, rtl); + @if $value != null { + @if $is-rtl == false { + /* rtl:begin:remove */ + } .#{$property-class + $infix + $property-class-modifier} { @each $property in $properties { #{$property}: $value if($enable-important-utilities, !important, null); @@ -55,6 +60,9 @@ } } } + @if $is-rtl == false { + /* rtl:end:remove */ + } } } } |