Weitere ähnliche Inhalte Ähnlich wie EmberConf 2015 – Ambitious UX for Ambitious Apps (20) Kürzlich hochgeladen (20) EmberConf 2015 – Ambitious UX for Ambitious Apps4. DESIGN IS HOW IT WORKS
GOOD DESIGN IS REACTIVE
GOOD DESIGN IS PLAYFUL
GOOD DESIGN IS INFORMATIVE
GOOD DESIGN IS INTUITIVE
6. “Most people make the mistake of thinking
design is what it looks like. That’s not what we
think design is. It’s not just what it looks like
and feels like. Design is how it works.”
16. DESIGN IS HOW IT WORKS
GOOD DESIGN IS REACTIVE
GOOD DESIGN IS PLAYFUL
GOOD DESIGN IS INFORMATIVE
GOOD DESIGN IS INTUITIVE
37. export default function(separator, dependentKeys) {
let computedFunc = computed(function() {
let values = dependentKeys.map((dependentKey) => {
return getWithDefault(this, dependentKey, '');
});
return values.join(separator);
});
return computedFunc.property.apply(computedFunc, dependentKeys);
};
39. import joinWith from '...';
export default Ember.Object.extend({
fullName: joinWith(' ', [
'title',
'firstName',
'middleName',
'lastName',
'suffix'
])
});
get(this, 'fullName');
// Mr Harvey Reginald Specter Esq.
42. DESIGN IS HOW IT WORKS
GOOD DESIGN IS REACTIVE
GOOD DESIGN IS PLAYFUL
GOOD DESIGN IS INFORMATIVE
GOOD DESIGN IS INTUITIVE
47. The person who would proof read
Hitler's speeches was a grammar
Nazi.
48. If your shirt isn't tucked into your
pants, then your pants are tucked
into your shirt.
55. getPostsBy(subreddit, period) {
let url = `//www.reddit.com/r/${subreddit}/top.json?sort=top&t=${period}`;
return new RSVP.Promise((resolve, reject) => {
getJSON(url)
.then((res) => {
let titles = res.data.children.mapBy('data.title');
resolve(titles);
}).catch(/* ... */);
});
}
59. export default function(dependentKey) {
return computed(`${dependentKey}.@each`, () => {
let items = getWithDefault(this, dependentKey, Ember.A([]));
let randomItem = items[Math.floor(Math.random() * items.get('length'))];
return randomItem || '';
}).volatile().readOnly();
}
61. DESIGN IS HOW IT WORKS
GOOD DESIGN IS REACTIVE
GOOD DESIGN IS PLAYFUL
GOOD DESIGN IS INFORMATIVE
GOOD DESIGN IS INTUITIVE
68. SERVICE: PUBLIC API
success(message, timeout=get(this, 'defaultTimeout')) {
return this._addToQueue(message, 'success', timeout);
},
info(/* ... */) {
return ...;
},
warning(/* ... */) {
return ...;
},
danger(/* ... */) {
return ...;
},
addMessage(message, type='default', timeout=get(this, 'defaultTimeout')) {
return this._addToQueue(message, type, timeout);
}
71. SERVICE: PRIVATE API
_newFlashMessage(service, message, type='info', timeout=get(this, 'defaultTimeout')) {
Ember.assert('Must pass a valid flash service', service);
Ember.assert('Must pass a valid flash message', message);
return FlashMessage.create({
type : type,
message : message,
timeout : timeout,
flashService : service
});
}
73. FLASH MESSAGE: PROPS
isSuccess : computed.equal('type', 'success'),
isInfo : computed.equal('type', 'info'),
isWarning : computed.equal('type', 'warning'),
isDanger : computed.equal('type', 'danger'),
defaultTimeout : computed.alias('flashService.defaultTimeout'),
queue : computed.alias('flashService.queue'),
timer : null
74. FLASH MESSAGE: LIFECYCLE HOOK
_destroyLater() {
let defaultTimeout = get(this, 'defaultTimeout');
let timeout = getWithDefault(this, 'timeout', defaultTimeout);
let destroyTimer = run.later(this, '_destroyMessage', timeout);
set(this, 'timer', destroyTimer);
}.on('init')
75. FLASH MESSAGE: PRIVATE API
_destroyMessage() {
let queue = get(this, 'queue');
if (queue) {
queue.removeObject(this);
}
this.destroy();
}
76. FLASH MESSAGE: PUBLIC API & OVERRIDE
destroyMessage() {
this._destroyMessage();
},
willDestroy() {
this._super();
let timer = get(this, 'timer');
if (timer) {
run.cancel(timer);
set(this, 'timer', null);
}
}
78. import FlashMessagesService from '...';
export function initialize(_container, application) {
application.register('service:flash-messages', FlashMessagesService, { singleton: true });
application.inject('controller', 'flashes', 'service:flash-messages');
application.inject('route', 'flashes', 'service:flash-messages');
}
export default {
name: 'flash-messages-service',
initialize: initialize
};
81. COMPONENT: PUBLIC API
export default Ember.Component.extend({
classNames: [ 'alert', 'flashMessage' ],
classNameBindings: [ 'alertType' ],
alertType: computed('flash.type', function() {
let flashType = get(this, 'flash.type');
return `alert-${flashType}`;
}),
click() {
let flash = get(this, 'flash');
flash.destroyMessage();
}
});
84. {{#each flashes.queue as |flash|}}
{{#flash-message flash=flash}}
<h6>{{flash.type}}</h6>
<p>{{flash.message}}</p>
{{/flash-message}}
{{/each}}
87. DESIGN IS HOW IT WORKS
GOOD DESIGN IS REACTIVE
GOOD DESIGN IS PLAYFUL
GOOD DESIGN IS INFORMATIVE
GOOD DESIGN IS INTUITIVE
94. export default Ember.Component.extend({
classNames : [ 'draggableDropzone' ],
classNameBindings : [ 'dragClass' ],
dragClass : 'deactivated',
dragLeave(event) {
event.preventDefault();
set(this, 'dragClass', 'deactivated');
},
dragOver(event) {
event.preventDefault();
set(this, 'dragClass', 'activated');
},
drop(event) {
let data = event.dataTransfer.getData('text/data');
this.sendAction('dropped', data);
set(this, 'dragClass', 'deactivated');
}
});
99. <div class="selectedUsers">
{{#draggable-dropzone dropped="addUser"}}
<ul class="selected-users-list">
{{#each selectedUsers as |user|}}
<li>{{user.fullName}}</li>
{{/each}}
</ul>
{{/draggable-dropzone}}
</div>
<div class="availableUsers">
{{#each users as |user|}}
{{#draggable-item content=user.id}}
<span>{{user.fullName}}</span>
{{/draggable-item}}
{{/each}}
</div>
100. actions: {
addUser(userId) {
let selectedUsers = get(this, 'selectedUsers');
let user = get(this, 'model').findBy('id', parseInt(userId));
if (!selectedUsers.contains(user)) {
return selectedUsers.pushObject(user);
}
}
}
103. DESIGN IS HOW IT WORKS
GOOD DESIGN IS REACTIVE
GOOD DESIGN IS PLAYFUL
GOOD DESIGN IS INFORMATIVE
GOOD DESIGN IS INTUITIVE
104. DESIGN IS HOW IT WORKS
GOOD DESIGN IS REACTIVE
GOOD DESIGN IS PLAYFUL
GOOD DESIGN IS INFORMATIVE
GOOD DESIGN IS INTUITIVE
105. DESIGN IS HOW IT WORKS
GOOD DESIGN IS REACTIVE
GOOD DESIGN IS PLAYFUL
GOOD DESIGN IS INFORMATIVE
GOOD DESIGN IS INTUITIVE
106. DESIGN IS HOW IT WORKS
GOOD DESIGN IS REACTIVE
GOOD DESIGN IS PLAYFUL
GOOD DESIGN IS INFORMATIVE
GOOD DESIGN IS INTUITIVE
107. DESIGN IS HOW IT WORKS
GOOD DESIGN IS REACTIVE
GOOD DESIGN IS PLAYFUL
GOOD DESIGN IS INFORMATIVE
GOOD DESIGN IS INTUITIVE