Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save amitkhare/5ea6d2917a304497f8702b6431a4b35f to your computer and use it in GitHub Desktop.
Save amitkhare/5ea6d2917a304497f8702b6431a4b35f to your computer and use it in GitHub Desktop.
Angular Material Design Starter App
<html lang="en" ng-app="StarterApp">
<head>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/angular_material/0.10.0/angular-material.min.css">
</head>
<body layout="row" ng-controller="AppCtrl">
<md-sidenav layout="column" class="md-sidenav-left md-whiteframe-z2" md-component-id="left" md-is-locked-open="$mdMedia('gt-md')">
<md-toolbar class="md-hue-2">
<span flex></span>
<div layout="row" layout-align="start center">
<md-icon class="md-avatar" md-svg-icon="avatars:svg-1"></md-icon>
<span flex></span>
</div>
<span flex></span>
<div class="md-body-2">Firstname Lastname</div>
<div class="md-body-1">email@domainname.com</div>
</md-toolbar>
<md-list>
<md-list-item class="md-2-line" ng-repeat="item in menu" role="link" md-ink-ripple>
<md-icon md-svg-icon="{{item.icon}}" aria-label="{{item.title}}"></md-icon>
<div class="md-list-item-text">
<span class="md-body-2">{{item.title}}</span>
</div>
</md-list-item>
<md-divider></md-divider>
<md-subheader class="md-no-sticky">Management</md-subheader>
<md-list-item class="md-2-line" ng-repeat="item in admin" role="link" md-ink-ripple>
<md-icon md-svg-icon="{{item.icon}}" aria-label="{{item.title}}"></md-icon>
<div class="md-list-item-text">
<span class="md-body-2">{{item.title}}</span>
</div>
</md-list-item>
</md-list>
</md-sidenav>
<div layout="column" class="relative" layout-fill role="main">
<md-button class="md-fab md-fab-bottom-right" aria-label="Add" ng-click="showAdd($event)">
<md-icon md-svg-icon="content:ic_add_24px" aria-label="Plus"></md-icon>
</md-button>
<md-toolbar class="animate-show md-tall md-whiteframe-z1" ng-show="!showSearch">
<div class="md-toolbar-tools">
<md-button class="md-icon-button" ng-click="toggleSidenav('left')" hide-gt-md aria-label="Menu">
<md-icon md-svg-icon="navigation:ic_menu_24px" aria-label="Menu"></md-icon>
</md-button>
<h3>
Dashboard
</h3>
<span flex></span>
<md-button class="md-icon-button" aria-label="Search" ng-click="toggleSearch()">
<md-icon md-svg-icon="action:ic_search_24px" aria-label="Search"></md-icon>
</md-button>
<md-button class="md-icon-button" aria-label="Open Settings" ng-click="showListBottomSheet($event)">
<md-icon md-svg-icon="navigation:ic_more_vert_24px" aria-label="More"></md-icon>
</md-button>
</div>
<span flex></span>
<md-tabs md-stretch-tabs="always" md-selected="data.selectedIndex">
<md-tab id="tab1" aria-controls="tab1-content">
Latest
</md-tab>
<md-tab id="tab2" aria-controls="tab2-content">
Favorites
</md-tab>
</md-tabs>
</md-toolbar>
<md-toolbar ng-show="showSearch" class="animate-show md-hue-1 md-whiteframe-z1">
<div class="md-toolbar-tools">
<md-button class="md-icon-button" ng-click="toggleSearch()" aria-label="Menu">
<md-icon md-svg-icon="navigation:ic_arrow_back_24px" aria-label="Back"></md-icon>
</md-button>
<h3 role="button" ng-click="toggleSearch()">
Back
</h3>
<span flex="5"></span>
<span ng-controller="DemoCtrl as ctrl" flex>
<md-autocomplete md-theme="input"
md-input-name="autocompleteField"
md-no-cache="ctrl.noCache"
md-selected-item="ctrl.selectedItem"
md-search-text="ctrl.searchText"
md-items="item in ctrl.querySearch(ctrl.searchText)"
md-item-text="item.display"
placeholder="Search">
<md-item-template>
<span md-highlight-text="ctrl.searchText">{{item.display}}</span>
</md-item-template>
<div ng-messages="searchForm.autocompleteField.$error" ng-if="searchForm.autocompleteField.$touched">
<div ng-message="required">You <b>must</b> have a favorite state.</div>
<div ng-message="minlength">Your entry is not long enough.</div>
<div ng-message="maxlength">Your entry is too long.</div>
</div>
</md-autocomplete>
</span>
</div>
</md-toolbar>
<md-content flex>
<ui-view layout="column" layout-fill layout-padding>
<div class="inset" hide-sm></div>
<ng-switch on="data.selectedIndex" class="tabpanel-container">
<div role="tabpanel"
id="tab1-content"
aria-labelledby="tab1"
ng-switch-when="0"
md-swipe-left="next()"
md-swipe-right="previous()"
layout="row" layout-align="center center">
<div flex-gt-sm="90" flex-gt-md="80">
<h2 class="md-title inset">Latest Activity</h2>
<md-card>
<md-list>
<md-list-item class="md-3-line" ng-repeat="item in activity | filter:search">
<md-icon class="md-avatar" hide-sm md-svg-icon="avatars:{{item.avatar}}"></md-icon>
<div class="md-list-item-text">
<h3>{{item.what}}</h3>
<h4>{{item.who}}</h4>
<p>{{item.notes}}</p>
</div>
<md-divider md-inset hide-sm ng-if="!$last"></md-divider>
<md-divider hide-gt-sm ng-if="!$last"></md-divider>
</md-list-item>
<md-divider></md-divider>
<md-list-item>
<md-button class="md-primary">
<md-icon md-svg-icon="navigation:ic_arrow_forward_24px" aria-label="Forward"></md-icon>
<span>More</span>
</md-button>
</md-list-item>
</md-list>
</md-card>
</div>
</div>
<div role="tabpanel"
id="tab2-content"
aria-labelledby="tab2"
ng-switch-when="1"
md-swipe-left="next()"
md-swipe-right="previous()"
layout="row" layout-align="center center">
<div flex-gt-sm="90" flex-gt-md="80">
<h2 class="md-title inset">Favorites</h2>
<md-card>
<md-list>
<md-list-item class="md-3-line" ng-repeat="item in activity | filter:search | orderBy:'-what'">
<md-icon class="md-avatar" hide-sm md-svg-icon="avatars:{{item.avatar}}"></md-icon>
<div class="md-list-item-text">
<h3>{{item.what}}</h3>
<h4>{{item.who}}</h4>
<p>{{item.notes}}</p>
</div>
<md-divider md-inset hide-sm ng-if="!$last"></md-divider>
<md-divider hide-gt-sm ng-if="!$last"></md-divider>
</md-list-item>
<md-divider></md-divider>
<md-list-item>
<md-button class="md-primary">
<md-icon md-svg-icon="navigation:ic_arrow_forward_24px" aria-label="Forward"></md-icon>
<span>More</span>
</md-button>
</md-list-item>
</md-list>
</md-card>
</div>
</div>
</ng-switch>
</ui-view>
</md-content>
</div>
<!-- Angular Material Dependencies -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-animate.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-aria.js"></script>
<!-- Angular Material -->
<script src="//ajax.googleapis.com/ajax/libs/angular_material/0.10.0/angular-material.min.js"></script>
</body>
</html>
var app = angular.module('StarterApp', ['ngMaterial']);
app.controller('AppCtrl', ['$scope', '$mdBottomSheet','$mdSidenav', '$mdDialog', function($scope, $mdBottomSheet, $mdSidenav, $mdDialog){
// Toolbar search toggle
$scope.toggleSearch = function(element) {
$scope.showSearch = !$scope.showSearch;
};
// Sidenav toggle
$scope.toggleSidenav = function(menuId) {
$mdSidenav(menuId).toggle();
};
// Menu items
$scope.menu = [
{
link : '',
title: 'Dashboard',
icon: 'action:ic_dashboard_24px' // we have to use Google's naming convention for the IDs of the SVGs in the spritesheet
},
{
link : '',
title: 'Friends',
icon: 'social:ic_group_24px'
},
{
link : '',
title: 'Messages',
icon: 'communication:ic_message_24px'
}
];
$scope.admin = [
{
link : '',
title: 'Trash',
icon: 'action:ic_delete_24px'
},
{
link : 'showListBottomSheet($event)',
title: 'Settings',
icon: 'action:ic_settings_24px'
}
];
// Mock activity
$scope.activity = [
{
what: 'Brunch this weekend?',
who: 'Ali Conners',
avatar: 'svg-1',
when: '3:08PM',
notes: " I'll be in your neighborhood doing errands"
},
{
what: 'Summer BBQ',
who: 'to Alex, Scott, Jennifer',
avatar: 'svg-2',
when: '3:08PM',
notes: "Wish I could come out but I'm out of town this weekend"
},
{
what: 'Oui Oui',
who: 'Sandra Adams',
avatar: 'svg-3',
when: '3:08PM',
notes: "Do you have Paris recommendations? Have you ever been?"
},
{
what: 'Birthday Gift',
who: 'Trevor Hansen',
avatar: 'svg-4',
when: '3:08PM',
notes: "Have any ideas of what we should get Heidi for her birthday?"
},
{
what: 'Recipe to try',
who: 'Brian Holt',
avatar: 'svg-5',
when: '3:08PM',
notes: "We should eat this: Grapefruit, Squash, Corn, and Tomatillo tacos"
},
];
// Bottomsheet & Modal Dialogs
$scope.alert = '';
$scope.showListBottomSheet = function($event) {
$scope.alert = '';
$mdBottomSheet.show({
template: '<md-bottom-sheet class="md-list md-has-header"><md-list><md-list-item class="md-2-line" ng-repeat="item in items" role="link" md-ink-ripple><md-icon md-svg-icon="{{item.icon}}" aria-label="{{item.name}}"></md-icon><div class="md-list-item-text"><h3>{{item.name}}</h3></div></md-list-item> </md-list></md-bottom-sheet>',
controller: 'ListBottomSheetCtrl',
targetEvent: $event
}).then(function(clickedItem) {
$scope.alert = clickedItem.name + ' clicked!';
});
};
$scope.showAdd = function(ev) {
$mdDialog.show({
controller: DialogController,
template: '<md-dialog aria-label="Form"> <md-content class="md-padding"> <form name="userForm"> <div layout layout-sm="column"> <md-input-container flex> <label>First Name</label> <input ng-model="user.firstName"> </md-input-container> <md-input-container flex> <label>Last Name</label> <input ng-model="user.lastName"> </md-input-container> </div> <md-input-container flex> <label>Message</label> <textarea ng-model="user.biography" columns="1" md-maxlength="150"></textarea> </md-input-container> </form> </md-content> <div class="md-actions" layout="row"> <span flex></span> <md-button ng-click="answer(\'not useful\')"> Cancel </md-button> <md-button ng-click="answer(\'useful\')" class="md-primary"> Save </md-button> </div></md-dialog>',
targetEvent: ev,
})
.then(function(answer) {
$scope.alert = 'You said the information was "' + answer + '".';
}, function() {
$scope.alert = 'You cancelled the dialog.';
});
};
}]);
app.controller('ListBottomSheetCtrl', function($scope, $mdBottomSheet) {
$scope.items = [
{ name: 'Share', icon: 'social:ic_share_24px' },
{ name: 'Upload', icon: 'file:ic_cloud_upload_24px' },
{ name: 'Copy', icon: 'content:ic_content_copy_24px' },
{ name: 'Print this page', icon: 'action:ic_print_24px' },
];
$scope.listItemClick = function($index) {
var clickedItem = $scope.items[$index];
$mdBottomSheet.hide(clickedItem);
};
});
function DialogController($scope, $mdDialog) {
$scope.hide = function() {
$mdDialog.hide();
};
$scope.cancel = function() {
$mdDialog.cancel();
};
$scope.answer = function(answer) {
$mdDialog.hide(answer);
};
};
app.controller('DemoCtrl', DemoCtrl);
function DemoCtrl ($timeout, $q) {
var self = this;
// list of `state` value/display objects
self.states = loadAll();
self.selectedItem = null;
self.searchText = null;
self.querySearch = querySearch;
// ******************************
// Internal methods
// ******************************
/**
* Search for states... use $timeout to simulate
* remote dataservice call.
*/
function querySearch (query) {
var results = query ? self.states.filter( createFilterFor(query) ) : [];
return results;
}
/**
* Build `states` list of key/value pairs
*/
function loadAll() {
var allStates = 'Ali Conners, Alex, Scott, Jennifer, \
Sandra Adams, Brian Holt, \
Trevor Hansen';
return allStates.split(/, +/g).map( function (state) {
return {
value: state.toLowerCase(),
display: state
};
});
}
/**
* Create filter function for a query string
*/
function createFilterFor(query) {
var lowercaseQuery = angular.lowercase(query);
return function filterFn(state) {
return (state.value.indexOf(lowercaseQuery) === 0);
};
}
};
app.config(function($mdThemingProvider) {
var customBlueMap = $mdThemingProvider.extendPalette('light-blue', {
'contrastDefaultColor': 'light',
'contrastDarkColors': ['50'],
'50': 'ffffff'
});
$mdThemingProvider.definePalette('customBlue', customBlueMap);
$mdThemingProvider.theme('default')
.primaryPalette('customBlue', {
'default': '500',
'hue-1': '50'
})
.accentPalette('pink');
$mdThemingProvider.theme('input', 'default')
.primaryPalette('grey')
});
app.config(function($mdIconProvider) {
$mdIconProvider
// linking to https://github.com/google/material-design-icons/tree/master/sprites/svg-sprite
//
.iconSet('action', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-action.svg', 24)
.iconSet('alert', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-alert.svg', 24)
.iconSet('av', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-av.svg', 24)
.iconSet('communication', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-communication.svg', 24)
.iconSet('content', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-content.svg', 24)
.iconSet('device', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-device.svg', 24)
.iconSet('editor', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-editor.svg', 24)
.iconSet('file', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-file.svg', 24)
.iconSet('hardware', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-hardware.svg', 24)
.iconSet('image', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-image.svg', 24)
.iconSet('maps', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-maps.svg', 24)
.iconSet('navigation', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-navigation.svg', 24)
.iconSet('notification', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-notification.svg', 24)
.iconSet('social', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-social.svg', 24)
.iconSet('toggle', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-toggle.svg', 24)
// Illustrated user icons used in the docs https://material.angularjs.org/latest/#/demo/material.components.gridList
.iconSet('avatars', 'https://raw.githubusercontent.com/angular/material/master/docs/app/icons/avatar-icons.svg', 24)
.defaultIconSet('https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-action.svg', 24);
});
// Colors
$gray: #eee;
// Angular
[ng-click] {
&:hover {
cursor: pointer;
}
}
// Main content bg color
md-content.md-default-theme {
background-color: $gray;
}
// Navigation drawer pattern: https://www.google.com/design/spec/patterns/navigation-drawer.html#navigation-drawer-specs
md-sidenav {
& > md-toolbar {
padding: 15px;
height: 150px;
max-height: 150px;
}
& md-list-item.md-2-line .md-list-item-text {
padding-top: 14px;
padding-bottom: 12px;
}
& md-divider {
margin-top: 4px;
margin-bottom: 4px;
}
}
// White svg icons in toolbar and fab
md-sidenav {
md-icon {
fill: #737373;
position: relative;
}
.md-avatar {
height: 64px;
width: 64px;
}
}
/* More closely matches https://www.google.com/design/spec/components/lists.html#lists-specs */
md-list-item.md-3-line {
md-divider {
&[md-inset] {
left: 70px;
}
}
}
// Round avatar
.md-avatar {
& > svg {
border-radius: 50%;
}
}
/* fade animation */
.animate-show {
transition: 0.75s ease-out opacity;
opacity: 1;
&.ng-hide {
height: 0;
min-height: 0;
opacity: 0;
overflow: hidden;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment