Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

Commit

Permalink
fix(list): add ripple, inherit from .md-button
Browse files Browse the repository at this point in the history
Updates interaction styles of list controls to attach ripple on click of list items with proxy controls, and makes child primary & secondary icon buttons into md-button. This allows for correct dimensions and mouse/focus behavior to be extended to list controls.

Closes #2395.
  • Loading branch information
Marcy Sutton authored and ThomasBurleson committed Apr 17, 2015
1 parent 3c0ce9b commit 25cc5e8
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 15 deletions.
3 changes: 3 additions & 0 deletions src/components/button/button-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ a.md-button.md-THEME_NAME-theme,
&.md-focused {
background-color: '{{background-500-0.2}}';
}
&.md-icon-button:hover {
background-color: transparent;
}
}

&.md-fab {
Expand Down
7 changes: 5 additions & 2 deletions src/components/list/list-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ md-list.md-THEME_NAME-theme {
color: '{{foreground-2}}';
}
}
.md-proxy-focus.md-focused div.md-no-style,
.md-no-style:focus {
.md-proxy-focus.md-focused div.md-no-style {
background-color: '{{background-100}}';
}

Expand All @@ -25,5 +24,9 @@ md-list.md-THEME_NAME-theme {
}
md-list-item button {
background-color: '{{background-color}}';

&.md-button:not([disabled]):hover {
background-color: '{{background-color}}';
}
}
}
43 changes: 35 additions & 8 deletions src/components/list/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
angular.module('material.components.list', [
'material.core'
])
.controller('MdListController', MdListController)
.directive('mdList', mdListDirective)
.directive('mdListItem', mdListItemDirective);

Expand Down Expand Up @@ -46,7 +47,6 @@ function mdListDirective($mdTheming) {
}
};
}

/**
* @ngdoc directive
* @name mdListItem
Expand All @@ -67,10 +67,11 @@ function mdListDirective($mdTheming) {
* </hljs>
*
*/
function mdListItemDirective($mdAria, $mdConstant) {
function mdListItemDirective($mdAria, $mdConstant, $timeout) {
var proxiedTypes = ['md-checkbox', 'md-switch'];
return {
restrict: 'E',
controller: 'MdListController',
compile: function(tEl, tAttrs) {
// Check for proxy controls (no ng-click on parent, and a control inside)
var secondaryItem = tEl[0].querySelector('.md-secondary');
Expand Down Expand Up @@ -120,7 +121,7 @@ function mdListItemDirective($mdAria, $mdConstant) {
container.append(tEl.contents());
tEl.addClass('md-proxy-focus');
} else {
container = angular.element('<button tabindex="0" class="md-no-style"><div class="md-list-item-inner"></div></button>');
container = angular.element('<md-button class="md-no-style"><div class="md-list-item-inner"></div></md-button>');
container[0].setAttribute('ng-click', tEl[0].getAttribute('ng-click'));
tEl[0].removeAttribute('ng-click');
container.children().eq(0).append(tEl.contents());
Expand All @@ -131,7 +132,7 @@ function mdListItemDirective($mdAria, $mdConstant) {

if (secondaryItem && secondaryItem.hasAttribute('ng-click')) {
$mdAria.expect(secondaryItem, 'aria-label');
var buttonWrapper = angular.element('<md-button class="md-secondary-container">');
var buttonWrapper = angular.element('<md-button class="md-secondary-container md-icon-button">');
buttonWrapper.attr('ng-click', secondaryItem.getAttribute('ng-click'));
secondaryItem.removeAttribute('ng-click');
secondaryItem.setAttribute('tabindex', '-1');
Expand All @@ -157,7 +158,7 @@ function mdListItemDirective($mdAria, $mdConstant) {

return postLink;

function postLink($scope, $element, $attr) {
function postLink($scope, $element, $attr, ctrl) {

var proxies = [];

Expand All @@ -167,8 +168,16 @@ function mdListItemDirective($mdAria, $mdConstant) {
if ($element.hasClass('md-proxy-focus') && proxies.length) {
angular.forEach(proxies, function(proxy) {
proxy = angular.element(proxy);
proxy.on('focus', function() {
$element.addClass('md-focused');

$scope.mouseActive = false;
proxy.on('mousedown', function() {
$scope.mouseActive = true;
$timeout(function(){
$scope.mouseActive = false;
}, 100);
})
.on('focus', function() {
if ($scope.mouseActive === false) { $element.addClass('md-focused'); }
proxy.on('blur', function proxyOnBlur() {
$element.removeClass('md-focused');
proxy.off('blur', proxyOnBlur);
Expand All @@ -189,6 +198,8 @@ function mdListItemDirective($mdAria, $mdConstant) {
function computeClickable() {
if (proxies.length || $element[0].firstElementChild.hasAttribute('ng-click')) {
$element.addClass('md-clickable');

ctrl.attachRipple($scope, angular.element($element[0].querySelector('.md-no-style')));
}
}

Expand All @@ -213,7 +224,6 @@ function mdListItemDirective($mdAria, $mdConstant) {
angular.forEach(proxies, function(proxy) {
if (e.target !== proxy && !proxy.contains(e.target)) {
angular.element(proxy).triggerHandler('click');
proxy.focus();
}
});
}
Expand All @@ -223,4 +233,21 @@ function mdListItemDirective($mdAria, $mdConstant) {
}
};
}

/*
* @private
* @ngdoc controller
* @name MdListController
* @module material.components.list
*
*/
function MdListController($scope, $element, $mdInkRipple) {
var ctrl = this;
ctrl.attachRipple = attachRipple;

function attachRipple (scope, element) {
var options = {};
$mdInkRipple.attachListControlBehavior(scope, element, options);
}
}
})();
14 changes: 11 additions & 3 deletions src/components/list/list.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ $list-item-primary-width: $baseline-grid * 7 !default;
$list-item-primary-avatar-width: $baseline-grid * 5 !default;
$list-item-primary-icon-width: $baseline-grid * 3 !default;
$list-item-secondary-left-margin: $baseline-grid * 2 !default;
$list-item-secondary-button-width: $baseline-grid * 6 !default;
$list-item-text-padding-top: $baseline-grid * 2 !default;
$list-item-text-padding-bottom: $baseline-grid * 2.5 !default;
$list-item-inset-divider-offset: 12 * $baseline-grid !default;
Expand All @@ -40,6 +41,14 @@ md-list-item {
position: relative;
padding: $list-item-padding-vertical $list-item-padding-horizontal;
flex: 1;
transition: background-color 0.15s linear;

&.md-button {
height: inherit;
text-align: left;
text-transform: none;
width: 100%;
}
&:focus {
outline: none
}
Expand Down Expand Up @@ -130,11 +139,10 @@ md-list-item, md-list-item .md-list-item-inner {
}

button.md-button.md-secondary-container {
width: $list-item-primary-icon-width;
background-color: transparent;
align-self: center;
margin-right: 0px;
box-sizing: content-box;
border-radius: 50%;
margin: 0px;
min-width: 0px;
.md-ripple,
.md-ripple-container {
Expand Down
4 changes: 2 additions & 2 deletions src/components/list/list.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ describe('mdListItem directive', function() {
it('creates buttons when used with ng-click', function() {
var listItem = setup('<md-list-item ng-click="sayHello()"><p>Hello world</p></md-list-item>');
var firstChild = listItem.children()[0];
expect(firstChild.nodeName).toBe('BUTTON');
expect(firstChild.nodeName).toBe('MD-BUTTON');
expect(firstChild.childNodes[0].nodeName).toBe('DIV');
expect(firstChild.childNodes[0].childNodes[0].nodeName).toBe('P');
});

it('moves md-secondary items outside of the button', function() {
var listItem = setup('<md-list-item ng-click="sayHello()"><p>Hello World</p><md-icon class="md-secondary" ng-click="goWild()"></md-icon></md-list-item>');
var firstChild = listItem.children()[0];
expect(firstChild.nodeName).toBe('BUTTON');
expect(firstChild.nodeName).toBe('MD-BUTTON');
expect(firstChild.childNodes.length).toBe(1);
var secondChild = listItem.children()[1];
expect(secondChild.nodeName).toBe('MD-BUTTON');
Expand Down
10 changes: 10 additions & 0 deletions src/core/services/ripple/ripple.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ function InkRippleService($window, $timeout) {
attachButtonBehavior: attachButtonBehavior,
attachCheckboxBehavior: attachCheckboxBehavior,
attachTabBehavior: attachTabBehavior,
attachListControlBehavior: attachListControlBehavior,
attach: attach
};

Expand Down Expand Up @@ -56,6 +57,15 @@ function InkRippleService($window, $timeout) {
}, options));
}

function attachListControlBehavior(scope, element, options) {
return attach(scope, element, angular.extend({
center: false,
dimBackground: true,
outline: false,
rippleSize: 'full'
}, options));
}

function attach(scope, element, options) {
if (element.controller('mdNoInk')) return angular.noop;

Expand Down

0 comments on commit 25cc5e8

Please sign in to comment.