Skip to content
This repository has been archived by the owner on Aug 29, 2023. It is now read-only.

Commit

Permalink
refactor(button): replace with an anchor or button
Browse files Browse the repository at this point in the history
Closes #423. Closes #508. Closes #230. Closes #558.

BREAKING CHANGE: When using the `<md-button>` directive, the compiled
element will now be a normal `<a> or `<button>` element with the class
`md-button` on it. There will no longer be `<md-button>` elements in
your final DOM.

This means that any css referencing the `md-button` element selector
should now reference the `.md-button` class selector.

Change your code from this:

```css
md-button {
  color: red;
}
```

To this:

```css
.md-button {
  color: red;
}
```
  • Loading branch information
ajoslin committed Nov 6, 2014
1 parent 05a45fb commit d835f9e
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 180 deletions.
67 changes: 20 additions & 47 deletions src/components/button/_button.scss
Expand Up @@ -20,16 +20,18 @@ $button-fab-toast-offset: $toast-height + $toast-margin;
}
}

md-button {
.md-button {

user-select: none;
position: relative; //for child absolute-positioned <canvas>
display: inline-block;

outline: none;
border: 0;
padding: 0;
padding: 6px;
margin: 0;
background: transparent;
white-space: nowrap;

text-align: center;

Expand All @@ -41,44 +43,11 @@ md-button {
font-size: inherit;
font-family: inherit;
line-height: inherit;
text-decoration: none;

cursor: pointer;
overflow: hidden; // for ink containment

// reserved for inner buttons and inner hrefs
.md-button-inner {
display: block;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: transparent;
border: none;
color: inherit;
outline: none;
text-transform: inherit;
font-weight: inherit;
font-style: inherit;
font-variant: inherit;
font-size: inherit;
font-family: inherit;
line-height: inherit;
white-space: nowrap;
padding: 6px;
}
a {
text-decoration: none;
}

// If we have a href and an inner anchor, let the clicks pass through to the anchor
&[href] {
pointer-events: none;
.md-button-inner {
pointer-events: auto;
}
}


&.md-cornered {
border-radius: 0;
}
Expand Down Expand Up @@ -126,7 +95,7 @@ md-button {
&:not([disabled]) {
&.md-raised,
&.md-fab {
&.focus,
&:focus,
&:hover {
transform: translate3d(0, -1px, 0);
@extend .md-shadow-bottom-z-2;
Expand All @@ -136,22 +105,26 @@ md-button {
}

.md-toast-open-top {
md-button.md-fab-top-left,
md-button.md-fab-top-right {
.md-button.md-fab-top-left,
.md-button.md-fab-top-right {
transform: translate3d(0, $button-fab-toast-offset, 0);
&.focus,
&:hover:not([disabled]) {
transform: translate3d(0, $button-fab-toast-offset - 1, 0);
&:not([disabled]) {
&:focus,
&:hover {
transform: translate3d(0, $button-fab-toast-offset - 1, 0);
}
}
}
}
.md-toast-open-bottom {
md-button.md-fab-bottom-left,
md-button.md-fab-bottom-right {
.md-button.md-fab-bottom-left,
.md-button.md-fab-bottom-right {
transform: translate3d(0, -$button-fab-toast-offset, 0);
&.focus,
&:hover {
transform: translate3d(0, -$button-fab-toast-offset - 1, 0);
&:not([disabled]) {
&:focus,
&:hover {
transform: translate3d(0, -$button-fab-toast-offset - 1, 0);
}
}
}
}
Expand Down
37 changes: 22 additions & 15 deletions src/components/button/button-theme.scss
Expand Up @@ -14,26 +14,20 @@ $button-warn-raised-background-color: map-get($button-warn-color-palette, '500')
$button-warn-raised-hover-background-color: map-get($button-warn-color-palette, '700') !default;

$button-flat-color-palette: $background-color-palette !default;
$button-disabled-color: map-get($button-flat-color-palette, '500') !default;
$button-disabled-background-color: rgba(map-get($button-flat-color-palette, '500'), 0.145) !default;
$button-disabled-color: $foreground-tertiary-color !default;
$button-disabled-background-color: transparent !default;
$button-hover-background-color: rgba(map-get($button-flat-color-palette, '500'), 0.20) !default;

$button-raised-color-palette: $button-flat-color-palette !default;
$button-raised-background-color: rgba(map-get($button-raised-color-palette, '500'), 0.185) !default;
$button-raised-hover-background-color: rgba(map-get($button-raised-color-palette, '500'), 0.30) !default;

md-button.md-#{$theme-name}-theme {
.md-button.md-#{$theme-name}-theme {
border-radius: $button-border-radius;

&[disabled] {
background-color: $button-disabled-background-color !important;
color: $button-disabled-color !important;
fill: $button-disabled-color !important;
cursor: auto;
}

&:not([disabled]) {
&:hover, &.focus {
&:hover,
&:focus {
background-color: $button-hover-background-color;
}
}
Expand All @@ -52,11 +46,13 @@ md-button.md-#{$theme-name}-theme {
fill: $button-warn-color;
}

&.md-raised, &.md-fab {
&.md-raised,
&.md-fab {
background-color: $button-raised-background-color;

&:not([disabled]) {
&:hover, &.focus {
&:hover,
&:focus {
background-color: $button-raised-hover-background-color;
}
}
Expand All @@ -65,7 +61,8 @@ md-button.md-#{$theme-name}-theme {
color: $button-primary-raised-color;
background-color: $button-primary-raised-background-color;
&:not([disabled]) {
&:hover, &.focus {
&:hover,
&:focus {
background-color: $button-primary-raised-hover-background-color;
}
}
Expand All @@ -75,10 +72,20 @@ md-button.md-#{$theme-name}-theme {
color: $button-warn-raised-color;
background-color: $button-warn-raised-background-color;
&:not([disabled]) {
&:hover, &.focus {
&:hover,
&:focus {
background-color: $button-warn-raised-hover-background-color;
}
}
}
}

&[disabled],
&.md-raised[disabled],
&.md-fab[disabled] {
color: $button-disabled-color;
fill: $button-disabled-color;
background-color: $button-disabled-background-color;
cursor: not-allowed;
}
}
111 changes: 48 additions & 63 deletions src/components/button/button.js
Expand Up @@ -9,14 +9,12 @@ angular.module('material.components.button', [
'material.core',
'material.animations',
'material.services.aria',
'material.services.theming'
'material.services.theming',
])
.directive('mdButton', [
'ngHrefDirective',
'$mdInkRipple',
'$mdAria',
'$mdUtil',
'$mdTheming',
'$mdAria',
MdButtonDirective
]);

Expand All @@ -30,81 +28,68 @@ angular.module('material.components.button', [
* @description
* `<md-button>` is a button directive with optional ink ripples (default enabled).
*
* If you supply a `href` or `ng-href` attribute, it will become an `<a>` element. Otherwise, it will
* become a `<button>` element.
*
* @param {boolean=} noink If present, disable ripple ink effects.
* @param {boolean=} disabled If present, disable tab selection.
* @param {string=} type Optional attribute to specific button types (useful for forms); such as 'submit', etc.
* @param {string=} ng-href Optional attribute to support both ARIA and link navigation
* @param {string=} href Optional attribute to support both ARIA and link navigation
* @param {string=} ariaLabel Publish the button label used by screen-readers for accessibility. Defaults to the button's text.
* @param {boolean=} disabled If present, disable selection.
* @param {string=} aria-label Publish the button label used by screen-readers for accessibility. Defaults to the button's text.
*
* @usage
* <hljs lang="html">
* <md-button>Button</md-button>
* <br/>
* <md-button noink class="md-button-colored">
* Button (noInk)
* <md-button>
* Button
* </md-button>
* <br/>
* <md-button disabled class="md-button-colored">
* Colored (disabled)
* <md-button href="http://google.com" class="md-button-colored">
* I'm a link
* </md-button>
* <md-button disabled class="md-colored">
* I'm a disabled button
* </md-button>
* </hljs>
*/
function MdButtonDirective(ngHrefDirectives, $mdInkRipple, $mdAria, $mdUtil, $mdTheming ) {
var ngHrefDirective = ngHrefDirectives[0];
function MdButtonDirective($mdInkRipple, $mdTheming, $mdAria) {

return {
restrict: 'E',
compile: function(element, attr) {
var innerElement;
var attributesToCopy;

replace: true,
transclude: true,
template: getTemplate,
link: postLink
};

// Add an inner anchor if the element has a `href` or `ngHref` attribute,
// so this element can be clicked like a normal `<a>`.
if (attr.ngHref || attr.href) {
innerElement = angular.element('<a>');
attributesToCopy = ['ng-href', 'href', 'rel', 'target', 'title', 'aria-label'];
// Otherwise, just add an inner button element (for form submission etc)
} else {
innerElement = angular.element('<button>');
attributesToCopy = ['type', 'disabled', 'ng-disabled', 'form', 'aria-label'];
}
function isAnchor(attr) {
return angular.isDefined(attr.href) || angular.isDefined(attr.ngHref);
}

function getTemplate(element, attr) {
var tag = isAnchor(attr) ? 'a' : 'button';
//We need to manually pass disabled to the replaced element because
//of a bug where it isn't always passed.
var disabled = element[0].hasAttribute('disabled') ? ' disabled ' : ' ';

angular.forEach(attributesToCopy, function(name) {
var camelCaseName = $mdUtil.camelCase(name);
if (attr.hasOwnProperty(camelCaseName)) {
innerElement.attr(name, attr[camelCaseName]);
}
});
return '<' + tag + disabled + 'class="md-button" ng-transclude></' + tag + '>';
}

innerElement
.addClass('md-button-inner')
.append(element.contents())
// Since we're always passing focus to the inner element,
// add a focus class to the outer element so we can still style
// it with focus.
.on('focus', function() {
element.addClass('focus');
})
.on('blur', function() {
element.removeClass('focus');
});
function postLink(scope, element, attr) {
var node = element[0];
$mdTheming(element);
$mdInkRipple.attachButtonBehavior(element);

element.
append(innerElement)
.attr('tabIndex', -1)
//Always pass focus to innerElement
.on('focus', function() {
innerElement.focus();
});
var elementHasText = node.textContent.trim();
if (!elementHasText) {
$mdAria.expect(element, 'aria-label');
}

return function postLink(scope, element, attr) {
$mdTheming(element);
$mdAria.expect(element, 'aria-label', true);
$mdInkRipple.attachButtonBehavior(element);
};
// For anchor elements, we have to set tabindex manually when the
// element is disabled
if (isAnchor(attr)) {
scope.$watch(function() {
return node.hasAttribute('disabled');
}, function(isDisabled) {
element.attr('tabindex', isDisabled ? -1 : 0);
});
}
};
}

}

0 comments on commit d835f9e

Please sign in to comment.