From a2c5961909b4362203d540913ffe1b28bef13679 Mon Sep 17 00:00:00 2001 From: Robert Messerle Date: Thu, 4 Dec 2014 13:30:42 -0800 Subject: [PATCH] refactor(ripple): adds support for non-fixed tabs Closes #825. Closes #460. --- src/components/tabs/demoDynamicTabs/style.css | 16 +- src/components/tabs/js/inkBarDirective.js | 46 ++--- src/components/tabs/js/paginationDirective.js | 187 +++++++++++------- src/components/tabs/js/tabItemDirective.js | 11 +- src/components/tabs/js/tabsController.js | 27 +-- src/components/tabs/js/tabsDirective.js | 29 ++- src/components/tabs/tabs.scss | 24 ++- src/core/services/ripple/ripple.js | 8 +- src/core/style/structure.scss | 6 +- 9 files changed, 200 insertions(+), 154 deletions(-) diff --git a/src/components/tabs/demoDynamicTabs/style.css b/src/components/tabs/demoDynamicTabs/style.css index a10c59d632f..10cd0ba7ce0 100644 --- a/src/components/tabs/demoDynamicTabs/style.css +++ b/src/components/tabs/demoDynamicTabs/style.css @@ -11,17 +11,15 @@ height: 300px; text-align: center; } -.tab0 { - background-color: #E3F2FD; +.tab0, .tab1, .tab2, .tab3 { + background-color: #bbdefb; } -.tab1 { - background-color: #E1F5FE; -} -.tab2 { - background-color: #E0F7FA; + +.md-header { + background-color: #1976D2 !important; } -.tab3 { - background-color: #E0F2F1; +md-tabs-ink-bar { + background-color: #FFFF8D !important; } .title { diff --git a/src/components/tabs/js/inkBarDirective.js b/src/components/tabs/js/inkBarDirective.js index d595053b0cc..886b17ee4e8 100644 --- a/src/components/tabs/js/inkBarDirective.js +++ b/src/components/tabs/js/inkBarDirective.js @@ -9,7 +9,9 @@ angular.module('material.components.tabs') .directive('mdTabsInkBar', MdTabInkDirective); -function MdTabInkDirective($mdConstant, $window, $$rAF, $timeout) { +function MdTabInkDirective($$rAF) { + + var lastIndex = 0; return { restrict: 'E', @@ -18,40 +20,38 @@ function MdTabInkDirective($mdConstant, $window, $$rAF, $timeout) { }; function postLink(scope, element, attr, ctrls) { - var nobar = ctrls[0], - tabsCtrl = ctrls[1], - timeout; + if (ctrls[0]) return; - if (nobar) return; + var tabsCtrl = ctrls[1], + debouncedUpdateBar = $$rAF.debounce(updateBar); tabsCtrl.inkBarElement = element; - scope.$watch(tabsCtrl.selected, updateBar); - scope.$on('$mdTabsChanged', updateBar); + scope.$on('$mdTabsPaginationChanged', debouncedUpdateBar); function updateBar() { - var selected = tabsCtrl.selected(); + var selected = tabsCtrl.getSelectedItem(); + var hideInkBar = !selected || tabsCtrl.count() < 2; - var hideInkBar = !selected || tabsCtrl.count() < 2 || - (scope.pagination || {}).itemsPerPage === 1; element.css('display', hideInkBar ? 'none' : 'block'); - if (!hideInkBar) { - var count = tabsCtrl.count(); - var scale = 1 / count; - var left = tabsCtrl.indexOf(selected); - element.css($mdConstant.CSS.TRANSFORM, 'scaleX(' + scale + ') ' + - 'translate3d(' + left * 100 + '%,0,0)'); - element.addClass('md-ink-bar-grow'); - if (timeout) $timeout.cancel(timeout); - timeout = $timeout(function () { - element.removeClass('md-ink-bar-grow'); - }, 250, false); + if (hideInkBar) return; + + if (scope.pagination && scope.pagination.tabData) { + var index = tabsCtrl.getSelectedIndex(); + var data = scope.pagination.tabData.tabs[index] || { left: 0, right: 0, width: 0 }; + var right = element.parent().prop('offsetWidth') - data.right; + var classNames = ['md-transition-left', 'md-transition-right', 'md-no-transition']; + var classIndex = lastIndex > index ? 0 : lastIndex < index ? 1 : 2; + + element + .removeClass(classNames.join(' ')) + .addClass(classNames[classIndex]) + .css({ left: data.left + 'px', right: right + 'px' }); + lastIndex = index; } } - } - } })(); diff --git a/src/components/tabs/js/paginationDirective.js b/src/components/tabs/js/paginationDirective.js index cef795c101d..286ced6617c 100644 --- a/src/components/tabs/js/paginationDirective.js +++ b/src/components/tabs/js/paginationDirective.js @@ -1,15 +1,11 @@ (function() { 'use strict'; - angular.module('material.components.tabs') - .directive('mdTabsPagination', TabPaginationDirective); + .directive('mdTabsPagination', TabPaginationDirective); -function TabPaginationDirective($mdConstant, $window, $$rAF, $$q, $timeout) { +function TabPaginationDirective($mdConstant, $window, $$rAF, $$q) { - // TODO allow configuration of TAB_MIN_WIDTH - // Must match tab min-width rule in _tabs.scss - var TAB_MIN_WIDTH = 8 * 12; // Must match (2 * width of paginators) in scss var PAGINATORS_WIDTH = (8 * 4) * 2; @@ -21,6 +17,7 @@ function TabPaginationDirective($mdConstant, $window, $$rAF, $$q, $timeout) { function postLink(scope, element, attr, tabsCtrl) { + var debouncedUpdatePagination = $$rAF.debounce(updatePagination); var tabsParent = element.children(); var state = scope.pagination = { page: -1, @@ -29,9 +26,6 @@ function TabPaginationDirective($mdConstant, $window, $$rAF, $$q, $timeout) { clickPrevious: function() { userChangePage(-1); } }; - updatePagination(); - var debouncedUpdatePagination = $$rAF.debounce(updatePagination); - scope.$on('$mdTabsChanged', debouncedUpdatePagination); angular.element($window).on('resize', debouncedUpdatePagination); @@ -39,10 +33,8 @@ function TabPaginationDirective($mdConstant, $window, $$rAF, $$q, $timeout) { angular.element($window).off('resize', debouncedUpdatePagination); }); - scope.$watch(tabsCtrl.selected, onSelectedTabChange); - scope.$watch(function() { - return tabsCtrl.tabToFocus; - }, onTabFocus); + scope.$watch(tabsCtrl.getSelectedItem, onSelectedTabChange); + scope.$watch(function() { return tabsCtrl.tabToFocus; }, onTabFocus); // Make sure we don't focus an element on the next page // before it's in view @@ -55,9 +47,7 @@ function TabPaginationDirective($mdConstant, $window, $$rAF, $$q, $timeout) { } else { // Go to the new page, wait for the page transition to end, then focus. oldTab && oldTab.element.blur(); - setPage(pageIndex).then(function() { - tab.element.focus(); - }); + setPage(pageIndex).then(function() { tab.element.focus(); }); } } @@ -67,73 +57,52 @@ function TabPaginationDirective($mdConstant, $window, $$rAF, $$q, $timeout) { if (state.active) { var selectedTabPage = getPageForTab(selectedTab); setPage(selectedTabPage); - } else { - debouncedUpdatePagination(); } } // Called when page is changed by a user action (click) function userChangePage(increment) { - var newPage = state.page + increment; - var newTab; - if (!tabsCtrl.selected() || getPageForTab(tabsCtrl.selected()) !== newPage) { - var startIndex; - if (increment < 0) { - // If going backward, select the previous available tab, starting from - // the first item on the page after newPage. - startIndex = (newPage + 1) * state.itemsPerPage; - newTab = tabsCtrl.previous( tabsCtrl.itemAt(startIndex) ); - } else { - // If going forward, select the next available tab, starting with the - // last item before newPage. - startIndex = (newPage * state.itemsPerPage) - 1; - newTab = tabsCtrl.next( tabsCtrl.itemAt(startIndex) ); - } - } - setPage(newPage).then(function() { - newTab && newTab.element.focus(); - }); - newTab && tabsCtrl.select(newTab); + var sizeData = state.tabData; + var newPage = Math.max(0, Math.min(sizeData.pages.length - 1, state.page + increment)); + var newTabIndex = sizeData.pages[newPage][ increment > 0 ? 'firstTabIndex' : 'lastTabIndex' ]; + var newTab = tabsCtrl.itemAt(newTabIndex); + + setPage(newPage).then(function() { newTab.element.focus(); }); + tabsCtrl.select(newTab); } function updatePagination() { var tabs = element.find('md-tab'); - var tabsWidth = element.parent().prop('clientWidth') - PAGINATORS_WIDTH; - var needPagination = tabsWidth && TAB_MIN_WIDTH * tabsCtrl.count() > tabsWidth; - var paginationToggled = needPagination !== state.active; + disablePagination(); - // If the md-tabs element is not displayed, then do nothing. - if ( tabsWidth <= 0 ) { - needPagination = false; - paginationToggled = true; - } + var sizeData = state.tabData = calculateTabData(); + var needPagination = state.active = sizeData.pages.length > 1; - state.active = needPagination; + if (needPagination) { enablePagination(); } - if (needPagination) { + scope.$evalAsync(function () { scope.$broadcast('$mdTabsPaginationChanged'); }); - state.pagesCount = Math.ceil((TAB_MIN_WIDTH * tabsCtrl.count()) / tabsWidth); - state.itemsPerPage = Math.max(1, Math.floor(tabsCtrl.count() / state.pagesCount)); - state.tabWidth = tabsWidth / state.itemsPerPage; + function enablePagination() { + tabsParent.css('width', '9999px'); + state.pagesCount = sizeData.pages.length; - tabsParent.css('width', state.tabWidth * tabsCtrl.count() + 'px'); - tabs.css('width', state.tabWidth + 'px'); + //-- apply filler margins + angular.forEach(sizeData.tabs, function (tab) { + angular.element(tab.element).css('margin-left', tab.filler + 'px'); + }); - var selectedTabPage = getPageForTab(tabsCtrl.selected()); + var selectedTabPage = getPageForTab(tabsCtrl.getSelectedItem()); setPage(selectedTabPage); + } - } else { - - if (paginationToggled) { - $timeout(function() { - tabsParent.css('width', ''); - tabs.css('width', ''); - slideTabButtons(0); - state.page = -1; - }); - } - + function disablePagination() { + slideTabButtons(0); + tabsParent.css('width', ''); + tabs.css('width', ''); + tabs.css('margin-left', ''); + state.page = -1; + state.active = false; } } @@ -160,11 +129,89 @@ function TabPaginationDirective($mdConstant, $window, $$rAF, $$q, $timeout) { } } + function stretchTabs() { + switch (scope.stretchTabs) { + case 'no': return false; + case 'yes': return true; + default: return window.innerWidth <= 600; + } + } + + function calculateTabData() { + var clientWidth = element.parent().prop('offsetWidth'); + var tabsWidth = clientWidth - PAGINATORS_WIDTH - 1; + var tabs = element[0].querySelectorAll('md-tab'); + var totalWidth = 0; + var max = 0; + var tabData = []; + var pages = []; + var currentPage; + + angular.element(tabs).css('max-width', ''); + angular.forEach(tabs, function (tab, index) { + var tabWidth = Math.min(tabsWidth, tab.offsetWidth); + var data = { + element: tab, + left: totalWidth, + width: tabWidth, + right: totalWidth + tabWidth, + filler: 0 + }; + //-- store 1-based page number + data.page = pages.length === 1 && index === tabs.length - 1 + ? Math.ceil(data.right / clientWidth) + : Math.ceil(data.right / tabsWidth); + if (data.page > pages.length) { + data.filler = (tabsWidth * (data.page - 1)) - data.left; + data.right += data.filler; + data.left += data.filler; + currentPage = { + left: data.left, + firstTabIndex: index, + lastTabIndex: index, + tabs: [ tab ] + }; + pages.push(currentPage); + } else { + currentPage.lastTabIndex = index; + currentPage.tabs.push(tab); + } + totalWidth = data.right; + max = Math.max(max, tabWidth); + tabData.push(data); + }); + angular.element(tabs).css('max-width', tabsWidth + 'px'); + + if (pages.length === 1 && stretchTabs()) { + var tabWidth = Math.ceil(clientWidth / tabData.length); + if (tabWidth >= max) { + angular.element(tabs).css('width', tabWidth + 'px'); + angular.forEach(tabData, function (tab, index) { + tab.width = tabWidth; + tab.left = tabWidth * index; + tab.right = tab.left + tab.width; + tab.filler = 0; + }); + totalWidth = tabsWidth; + } + } + + return { + width: totalWidth, + max: max, + tabs: tabData, + pages: pages, + tabElements: tabs + }; + } + function getPageForTab(tab) { var tabIndex = tabsCtrl.indexOf(tab); if (tabIndex === -1) return 0; - return Math.floor(tabIndex / state.itemsPerPage); + var sizeData = state.tabData; + + return sizeData ? sizeData.tabs[tabIndex].page - 1 : -1; } function setPage(page) { @@ -176,15 +223,13 @@ function TabPaginationDirective($mdConstant, $window, $$rAF, $$q, $timeout) { if (page > lastPage) page = lastPage; state.hasPrev = page > 0; - state.hasNext = ((page + 1) * state.itemsPerPage) < tabsCtrl.count(); + state.hasNext = page < state.tabData.pages.length - 1; state.page = page; - $timeout(function() { - scope.$broadcast('$mdTabsPaginationChanged'); - }); + scope.$broadcast('$mdTabsPaginationChanged'); - return slideTabButtons(-page * state.itemsPerPage * state.tabWidth); + return slideTabButtons(-state.tabData.pages[page].left); } } diff --git a/src/components/tabs/js/tabItemDirective.js b/src/components/tabs/js/tabItemDirective.js index 2df1e931795..36d3d4088ad 100644 --- a/src/components/tabs/js/tabItemDirective.js +++ b/src/components/tabs/js/tabItemDirective.js @@ -53,7 +53,7 @@ angular.module('material.components.tabs') * * */ -function MdTabDirective($mdInkRipple, $compile, $mdAria, $mdUtil, $mdConstant) { +function MdTabDirective($mdInkRipple, $compile, $mdUtil, $mdConstant, $rootScope) { return { restrict: 'E', require: ['mdTab', '^mdTabs'], @@ -88,6 +88,11 @@ function MdTabDirective($mdInkRipple, $compile, $mdAria, $mdUtil, $mdConstant) { return function postLink(scope, element, attr, ctrls) { + scope.$watch( + function () { return element.html(); }, + function () { $rootScope.$broadcast('$mdTabsChanged'); } + ); + var tabItemCtrl = ctrls[0]; // Controller for THIS tabItemCtrl var tabsCtrl = ctrls[1]; // Controller for ALL tabs @@ -175,7 +180,7 @@ function MdTabDirective($mdInkRipple, $compile, $mdAria, $mdUtil, $mdConstant) { scope.$on('$destroy', unwatch); function activeWatchAction(isActive) { - var isSelected = tabsCtrl.selected() === tabItemCtrl; + var isSelected = tabsCtrl.getSelectedItem() === tabItemCtrl; if (isActive && !isSelected) { tabsCtrl.select(tabItemCtrl); @@ -192,7 +197,7 @@ function MdTabDirective($mdInkRipple, $compile, $mdAria, $mdUtil, $mdConstant) { element.attr('aria-disabled', isDisabled); // Auto select `next` tab when disabled - var isSelected = (tabsCtrl.selected() === tabItemCtrl); + var isSelected = (tabsCtrl.getSelectedItem() === tabItemCtrl); if (isSelected && isDisabled) { tabsCtrl.select(tabsCtrl.next() || tabsCtrl.previous()); } diff --git a/src/components/tabs/js/tabsController.js b/src/components/tabs/js/tabsController.js index 44cd3faaa49..cd47c3855dd 100644 --- a/src/components/tabs/js/tabsController.js +++ b/src/components/tabs/js/tabsController.js @@ -4,7 +4,7 @@ angular.module('material.components.tabs') .controller('$mdTabs', MdTabsController); -function MdTabsController($scope, $element, $mdUtil) { +function MdTabsController($scope, $element, $mdUtil, $$rAF) { var tabsList = $mdUtil.iterator([], false); var self = this; @@ -21,7 +21,8 @@ function MdTabsController($scope, $element, $mdUtil) { self.itemAt = tabsList.itemAt; self.count = tabsList.count; - self.selected = selected; + self.getSelectedItem = getSelectedItem; + self.getSelectedIndex = getSelectedIndex; self.add = add; self.remove = remove; self.move = move; @@ -33,21 +34,24 @@ function MdTabsController($scope, $element, $mdUtil) { self.previous = previous; $scope.$on('$destroy', function() { - self.deselect(self.selected()); + self.deselect(self.getSelectedItem()); for (var i = tabsList.count() - 1; i >= 0; i--) { self.remove(tabsList[i], true); } }); // Get the selected tab - function selected() { + function getSelectedItem() { return self.itemAt($scope.selectedIndex); } + function getSelectedIndex() { + return $scope.selectedIndex; + } + // Add a new tab. // Returns a method to remove the tab from the list. function add(tab, index) { - tabsList.add(tab, index); tab.onAdd(self.contentArea); @@ -57,6 +61,7 @@ function MdTabsController($scope, $element, $mdUtil) { $scope.selectedIndex === self.indexOf(tab)) { self.select(tab); } + $scope.$broadcast('$mdTabsChanged'); } @@ -65,7 +70,7 @@ function MdTabsController($scope, $element, $mdUtil) { if (noReselect) { // do nothing - } else if (self.selected() === tab) { + } else if (self.getSelectedItem() === tab) { if (tabsList.count() > 1) { self.select(self.previous() || self.next()); } else { @@ -81,7 +86,7 @@ function MdTabsController($scope, $element, $mdUtil) { // Move a tab (used when ng-repeat order changes) function move(tab, toIndex) { - var isSelected = self.selected() === tab; + var isSelected = self.getSelectedItem() === tab; tabsList.remove(tab); tabsList.add(tab, toIndex); @@ -94,7 +99,7 @@ function MdTabsController($scope, $element, $mdUtil) { if (!tab || tab.isSelected || tab.isDisabled()) return; if (!tabsList.contains(tab)) return; - self.deselect(self.selected()); + self.deselect(self.getSelectedItem()); $scope.selectedIndex = self.indexOf(tab); tab.isSelected = true; @@ -102,7 +107,7 @@ function MdTabsController($scope, $element, $mdUtil) { } function focus(tab) { - // this variable is $watch'd by pagination + // this variable is watched by pagination self.tabToFocus = tab; } @@ -116,10 +121,10 @@ function MdTabsController($scope, $element, $mdUtil) { } function next(tab, filterFn) { - return tabsList.next(tab || self.selected(), filterFn || isTabEnabled); + return tabsList.next(tab || self.getSelectedItem(), filterFn || isTabEnabled); } function previous(tab, filterFn) { - return tabsList.previous(tab || self.selected(), filterFn || isTabEnabled); + return tabsList.previous(tab || self.getSelectedItem(), filterFn || isTabEnabled); } function isTabEnabled(tab) { diff --git a/src/components/tabs/js/tabsDirective.js b/src/components/tabs/js/tabsDirective.js index d9b8c496cee..6e10642e993 100644 --- a/src/components/tabs/js/tabsDirective.js +++ b/src/components/tabs/js/tabsDirective.js @@ -48,7 +48,8 @@ angular.module('material.components.tabs') * @param {integer=} md-selected Index of the active/selected tab * @param {boolean=} md-no-ink If present, disables ink ripple effects. * @param {boolean=} md-no-bar If present, disables the selection ink bar. - * @param {string=} md-align-tabs Attribute to indicate position of tab buttons: bottom or top; default is `top` + * @param {string=} md-align-tabs Attribute to indicate position of tab buttons: `bottom` or `top`; default is `top` + * @param {boolean=} md-stretch-tabs Attribute to indicate whether or not to stretch tabs: `auto`, `yes`, or `no`; default is `auto` * * @usage * @@ -76,7 +77,7 @@ angular.module('material.components.tabs') * * */ -function TabsDirective($parse, $mdTheming) { +function TabsDirective($mdTheming) { return { restrict: 'E', controller: '$mdTabs', @@ -100,7 +101,6 @@ function TabsDirective($parse, $mdTheming) { // flex container for elements '
' + '' + - '' + '
' + '' + @@ -116,6 +116,9 @@ function TabsDirective($parse, $mdTheming) { }; function postLink(scope, element, attr, tabsCtrl, transclude) { + + scope.stretchTabs = attr.hasOwnProperty('mdStretchTabs') ? attr.mdStretchTabs : 'auto'; + $mdTheming(element); configureAria(); watchSelected(); @@ -125,32 +128,24 @@ function TabsDirective($parse, $mdTheming) { }); function configureAria() { - element.attr({ - role: 'tablist' - }); + element.attr('role', 'tablist'); } function watchSelected() { scope.$watch('selectedIndex', function watchSelectedIndex(newIndex, oldIndex) { - // Note: if the user provides an invalid newIndex, all tabs will be deselected - // and the associated view will be hidden. - tabsCtrl.deselect( tabsCtrl.itemAt(oldIndex) ); + tabsCtrl.deselect(tabsCtrl.itemAt(oldIndex)); if (tabsCtrl.inRange(newIndex)) { var newTab = tabsCtrl.itemAt(newIndex); - - // If the newTab is disabled, find an enabled one to go to. - if (newTab && newTab.isDisabled()) { - newTab = newIndex > oldIndex ? - tabsCtrl.next(newTab) : - tabsCtrl.previous(newTab); + while (newTab && newTab.isDisabled()) { + newTab = newIndex > oldIndex + ? tabsCtrl.next(newTab) + : tabsCtrl.previous(newTab); } tabsCtrl.select(newTab); - } }); } - } } })(); diff --git a/src/components/tabs/tabs.scss b/src/components/tabs/tabs.scss index 821b919ff0c..9fe3d1acd7f 100644 --- a/src/components/tabs/tabs.scss +++ b/src/components/tabs/tabs.scss @@ -71,10 +71,10 @@ md-tabs[center] .md-header:not(.md-paginating) .md-header-items { .md-header-items { display: flex; box-sizing: border-box; - transition: $swift-ease-in-out; + transition: transform $swift-ease-in-out-duration $swift-ease-in-out-timing-function; transform: translate3d(0, 0, 0); - width: 100%; height: 100%; + width: 99999px; } } @@ -88,37 +88,42 @@ md-tabs[center] .md-header:not(.md-paginating) .md-header-items { } md-tabs-ink-bar { + $time: 0.25s; + $delay: $time * 0.3; + $shortTime: $time; z-index: 1; display: none; position: absolute; left: 0; bottom: 0; - width: 100%; box-sizing: border-box; height: 2px; margin-top: -2px; transform: scaleX(1); - transition: transform 0.5s $swift-ease-in-out-timing-function; transform-origin: 0 0; - &.md-ink-bar-delayed { - transition: transform 0.5s cubic-bezier(0.45, 0, 0.15, 1); + &.md-transition-right { + transition: right $time $swift-ease-in-out-timing-function, + left $shortTime $swift-ease-in-out-timing-function $delay; + } + &.md-transition-left { + transition: right $shortTime $swift-ease-in-out-timing-function $delay, + left $time $swift-ease-in-out-timing-function; } } md-tab { display: flex; - flex: 1; align-items: center; justify-content: center; - box-sizing: border-box; position: relative; z-index: 0; overflow: hidden; height: 100%; text-align: center; cursor: pointer; - min-width: $tabs-tab-width; border: 1px dotted transparent; + padding: 20px 24px; + box-sizing: border-box; &[disabled] { pointer-events: none; @@ -136,7 +141,6 @@ md-tab { z-index: 100; opacity: 1; overflow: hidden; - text-overflow: ellipsis; } } diff --git a/src/core/services/ripple/ripple.js b/src/core/services/ripple/ripple.js index 1834f20d8d8..376b81a0fe6 100644 --- a/src/core/services/ripple/ripple.js +++ b/src/core/services/ripple/ripple.js @@ -90,9 +90,7 @@ function InkRippleService($window, $timeout) { scope.$watch(isActiveExpr, function watchActive(newValue) { isActive = newValue; if (isActive && !ripples.length) { - $timeout(function () { - createRipple(0, 0); - }, 0, false); + $timeout(function () { createRipple(0, 0); }, 0, false); } angular.forEach(ripples, updateElement); }); @@ -335,9 +333,7 @@ function InkRippleService($window, $timeout) { isHeld = false; index = ripples.length - 1; ripple = ripples[index]; - $timeout(function () { - updateElement(ripple); - }, 0, false); + $timeout(function () { updateElement(ripple); }, 0, false); } /** diff --git a/src/core/style/structure.scss b/src/core/style/structure.scss index 6a01778d87c..e8dabf22ed9 100644 --- a/src/core/style/structure.scss +++ b/src/core/style/structure.scss @@ -217,10 +217,8 @@ md-tab { border-style: solid; opacity: 0.20; transform: none !important; - &.md-ripple-placed { - } - &.md-ripple-scaled { - } + &.md-ripple-placed {} + &.md-ripple-scaled {} &.md-ripple-active, &.md-ripple-full, &.md-ripple-visible { opacity: 0.20; }