Improve lists by compacting items

pull/105/head
Francis Lachapelle 2015-09-25 16:07:56 -04:00
parent 31f2e4b549
commit 5496dd97d9
12 changed files with 205 additions and 138 deletions

View File

@ -366,12 +366,13 @@
ng-click="addressbook.selectCard(currentCard)"
ui-sref="app.addressbook.card.view({addressbookId: addressbook.selectedFolder.id, cardId: currentCard.id})"
ui-sref-active="md-default-theme md-background md-bg md-hue-1">
<div class="sg-selected-avatar" ng-show="currentCard.selected"
<div class="md-avatar sg-avatar-selected"
ng-if="currentCard.selected"
ng-click="addressbook.toggleCardSelection($event, currentCard)">
<!-- selected avatar -->
</div>
<sg-avatar-image class="md-tile-left"
ng-show="addressbook.notSelectedComponent(currentCard, 'vcard')"
<sg-avatar-image class="md-avatar"
ng-if="addressbook.notSelectedComponent(currentCard, 'vcard')"
ng-click="addressbook.toggleCardSelection($event, currentCard)"
sg-email="currentCard.$preferredEmail(addressbook.selectedFolder.constructor.$query)"
size="40">
@ -383,8 +384,12 @@
<!-- list avatar -->
</div>
<div class="sg-tile-content">
<div class="sg-md-subhead-multi" ng-bind-html="currentCard.$fullname()"><!-- cn --></div>
<div class="sg-md-body-multi">{{currentCard.$preferredEmail(addressbook.selectedFolder.constructor.$query)}}</div>
<div class="sg-md-subhead">
<div ng-bind-html="currentCard.$fullname()"><!-- cn --></div>
</div>
<div class="sg-md-body">
<div>{{currentCard.$preferredEmail(addressbook.selectedFolder.constructor.$query)}}</div>
</div>
</div>
</md-list-item>
</div>

View File

@ -30,15 +30,15 @@
<div layout="row" layout-align="start center" class="md-flex">
<span class="card-picture" ng-switch="user.isGroup">
<div ng-switch-when="0">
<sg-avatar-image class="md-tile-left"
<sg-avatar-image class="md-avatar"
sg-email="user.c_email"
size="48"><!-- avatar --></sg-avatar-image>
size="40"><!-- avatar --></sg-avatar-image>
</div>
<div ng-switch-when="1" class="sg-list-avatar"><!-- normal-group --></div>
</span>
<div class="sg-tile-content">
<div class="sg-md-subhead-multi">{{user.cn}} {{user.userClass}}</div>
<div class="sg-md-body-multi">{{user.c_email}}</div>
<div class="sg-md-subhead"><div>{{user.cn}}</div></div>
<div class="sg-md-body"><div>{{user.c_email}}</div></div>
</div>
<md-icon ng-class="{'md-rotate-180': user.uid == subscribe.selectedUser.uid}">expand_more</md-icon>
</div>

View File

@ -214,26 +214,29 @@
ng-class="{'md-bg': mailbox.selectedFolder.isSelectedMessage(currentMessage.uid, currentMessage.$mailbox.path),
unread: !currentMessage.isread}"
ng-click="mailbox.selectMessage(currentMessage)">
<div class="sg-selected-avatar"
ng-show="currentMessage.selected"
ng-click="mailbox.toggleMessageSelection($event, currentMessage)"><!-- selected avatar --></div>
<sg-avatar-image class="md-tile-left"
ng-show="!currentMessage.selected"
<sg-avatar-image class="md-avatar"
ng-if="!currentMessage.selected"
ng-click="mailbox.toggleMessageSelection($event, currentMessage)"
sg-email="::currentMessage.from[0].email"
size="40"><!-- avatar --></sg-avatar-image>
<div class="md-avatar sg-avatar-selected"
ng-if="currentMessage.selected"
ng-click="mailbox.toggleMessageSelection($event, currentMessage)"><!-- selected avatar --></div>
<div class="sg-tile-content">
<span class="msg-date"
ng-bind-html="currentMessage.relativedate"><!-- date --></span>
<div class="sg-md-subhead-multi">
<span class="sg-label-outline"
ng-show="mailbox.service.$virtualMode">{{currentMessage.$mailbox.name}}</span>
{{currentMessage.$shortAddress('from')}}
<div class="sg-md-subhead">
<div>
<span class="sg-label-outline"
ng-show="mailbox.service.$virtualMode">{{currentMessage.$mailbox.name}}</span>
{{currentMessage.$shortAddress('from')}}
<md-icon ng-show="currentMessage.priority.level == 1 || currentMessage.priority.level == 2">warning</md-icon>
</div>
<div class="sg-tile-date" ng-bind="currentMessage.relativedate"><!-- date --></div>
</div>
<div class="sg-md-body">
<div>{{currentMessage.subject}}</div>
</div>
<div class="sg-md-body-multi">{{currentMessage.subject}}</div>
</div>
<div class="sg-tile-icons">
<md-icon ng-show="currentMessage.priority.level == 1 || currentMessage.priority.level == 2">warning</md-icon>
<md-icon ng-show="currentMessage.isflagged">star</md-icon>
<md-icon ng-show="currentMessage.isanswered">reply</md-icon>
<md-icon ng-show="currentMessage.isforwarded">forward</md-icon>

View File

@ -23,13 +23,13 @@
<md-dialog-content>
<md-list>
<md-list-item ng-repeat="user in delegate.users | orderBy:['userClass', 'displayName']">
<div layout="row" layout-align="start center" class="md-flex">
<sg-avatar-image class="md-tile-left"
<div layout="row" layout-align="start center" class="md-flex card-picture">
<sg-avatar-image class="md-avatar"
sg-email="user.c_email"
size="40"><!-- avatar --></sg-avatar-image>
<div class="sg-tile-content">
<div class="sg-md-subhead-multi">{{user.cn}}</div>
<div class="sg-md-body-multi">{{user.c_email}}</div>
<div class="sg-md-subhead"><div>{{user.cn}}</div></div>
<div class="sg-md-body"><div>{{user.c_email}}</div></div>
</div>
<md-button class="sg-icon-button" ng-click="delegate.removeUser(user)">
<md-icon>delete</md-icon>

View File

@ -14,15 +14,15 @@
<!-- attendees -->
<md-list>
<md-list-item>
<div><!-- empty --></div>
<div class="md-tile-left"><!-- empty --></div>
</md-list-item>
<md-list-item ng-repeat="currentAttendee in editor.component.attendees track by currentAttendee.email">
<sg-avatar-image class="md-tile-left"
<sg-avatar-image class="md-avatar"
sg-email="currentAttendee.email"
size="40"><!-- avatar --></sg-avatar-image>
<div class="sg-tile-content">
<div class="sg-md-subhead-multi">{{currentAttendee.name}}</div>
<div class="sg-md-body-multi">{{currentAttendee.email}}</div>
<div class="sg-md-subhead"><div>{{currentAttendee.name}}</div></div>
<div class="sg-md-body"><div>{{currentAttendee.email}}</div></div>
</div>
</md-list-item>
</md-list>

View File

@ -591,26 +591,27 @@
<md-tab label:label="Events"
md-on-select="list.selectComponentType('events')">
<md-list class="sg-section-list">
<md-list-item class="md-2-line"
ng-repeat="event in list.component.$events"
<md-list-item ng-repeat="event in list.component.$events"
ng-click="list.openEvent($event, event)">
<div class="sg-selected-avatar" ng-show="event.selected"
<div class="md-avatar sg-avatar-selected" ng-show="event.selected"
ng-click="list.toggleComponentSelection($event, event)">
<!-- selected avatar -->
</div>
<i class="md-tile-left" ng-class="event.getClassName('bg')"
<div class="sg-color-chip" ng-class="event.getClassName('bg')"
ng-show="!event.selected"
ng-click="list.toggleComponentSelection($event, event)"><!-- calendar color --></i>
<div class="md-list-item-text">
<h3>{{event.c_title}}</h3>
<p>{{event.c_location}}</p>
<p class="md-secondary" layout="row">
{{event.formatted_startdate}}
<i class="sg-tile-icons">
<md-icon ng-show="event.c_iscycle">repeat</md-icon>
<md-icon ng-show="event.c_nextalarm">alarm</md-icon>
</i>
</p>
ng-click="list.toggleComponentSelection($event, event)"><!-- calendar color --></div>
<div class="sg-tile-content">
<div class="sg-md-subhead">
<div>{{event.c_title}}</div>
</div>
<div class="sg-md-body">
<div>{{event.c_location}}</div>
<div class="sg-tile-date" ng-bind="event.formatted_startdate"><!-- start --></div>
</div>
</div>
<div class="sg-tile-icons">
<md-icon ng-show="event.c_iscycle">repeat</md-icon>
<md-icon ng-show="event.c_nextalarm">alarm</md-icon>
</div>
</md-list-item>
<md-list-item disabled="disabled" ng-if="list.component.$events.length == 0">
@ -622,25 +623,27 @@
<md-tab label:label="Tasks"
md-on-select="list.selectComponentType('tasks')">
<md-list class="sg-section-list">
<md-list-item class="md-2-line"
ng-repeat="task in list.component.$tasks"
<md-list-item ng-repeat="task in list.component.$tasks"
ng-click="list.openTask($event, task)">
<div class="sg-selected-avatar" ng-show="task.selected"
<div class="md-avatar sg-selected-avatar" ng-show="task.selected"
ng-click="list.toggleComponentSelection($event, task)">
<!-- selected avatar -->
</div>
<i class="md-tile-left" ng-class="task.getClassName('bg')"
ng-show="!task.selected"
ng-click="list.toggleComponentSelection($event, task)"><!-- calendar color --></i>
<div class="md-list-item-text">
<h3>{{task.c_title}}</h3>
<p class="md-secondary" layout="row">
{{task.formatted_enddate}}
<span class="sg-tile-icons">
<md-icon ng-show="task.c_iscycle">repeat</md-icon>
<md-icon ng-show="event.c_nextalarm">alarm</md-icon>
</span>
</p>
<div class="sg-color-chip" ng-class="task.getClassName('bg')"
ng-show="!task.selected"
ng-click="list.toggleComponentSelection($event, task)"><!-- calendar color --></div>
<div class="sg-tile-content">
<div class="sg-md-subhead">
<div>{{task.c_title}}</div>
</div>
<div class="sg-md-body">
<div><!-- spacer --></div>
<div>{{task.formatted_enddate}}</div>
</div>
</div>
<div class="sg-tile-icons">
<md-icon ng-show="task.c_iscycle">repeat</md-icon>
<md-icon ng-show="event.c_nextalarm">alarm</md-icon>
</div>
</md-list-item>
<md-list-item disabled="disabled" ng-if="list.component.$tasks.length == 0">

View File

@ -26,16 +26,16 @@
<div layout="row" layout-align="start center" class="md-flex">
<span class="card-picture" ng-switch="user.userClass">
<div ng-switch-when="normal-user">
<sg-avatar-image class="md-tile-left"
<sg-avatar-image class="md-avatar"
sg-email="user.c_email"
size="40"><!-- avatar --></sg-avatar-image>
</div>
<div ng-switch-when="normal-group" class="sg-list-avatar"><!-- normal-group --></div>
<div ng-switch-when="public-user" class="sg-list-avatar"><!-- public-user --></div>
<div ng-switch-when="normal-group" class="md-avatar sg-avatar-list"><!-- normal-group --></div>
<div ng-switch-when="public-user" class="md-avatar sg-avatar-list"><!-- public-user --></div>
</span>
<div class="sg-tile-content">
<div class="sg-md-subhead-multi">{{user.cn}}</div>
<div class="sg-md-body-multi">{{user.c_email}}</div>
<div class="sg-md-subhead"><div>{{user.cn}}</div></div>
<div class="sg-md-body"><div>{{user.c_email}}</div></div>
</div>
<md-button class="sg-icon-button" type="button"
ng-click="acl.removeUser(user)"

View File

@ -12,7 +12,7 @@
// ------------------------------------
.view-list md-list .md-button {
// Gain some space in lists
padding: 0;
padding-right: 0;
}
// Expandable button for a collapsable list

View File

@ -1,7 +1,22 @@
/// list.scss -*- Mode: scss; indent-tabs-mode: nil; basic-offset: 2 -*-
$list-item-height: 6 * $baseline-grid;
// Increase header line height
$list-header-line-height: 1em;
// Decrease the margin of H3 to counter the larger line height
$list-h3-margin: 0;
// Decrease default list item height
$list-item-height: 6 * $baseline-grid; // 48px
@import 'extends';
// Circle diameter of avatars
$sg-avatar-width: 40px;
// Circle diamter of color chips
$sg-color-chip-width: $subhead-font-size-base;
// List item label
md-list-item {
.md-list-item-inner {
@ -25,14 +40,25 @@ md-list-item {
}
}
// Remove padding of input fields in the sidenav for better transitions between read and edit mode of a folder
md-sidenav {
.md-sidenav-left {
// Remove padding of input fields in the sidenav for better transitions between read and edit mode of a folder
md-input-container {
padding: 0;
.md-input {
padding-left: 0;
}
}
md-list-item {
.md-button {
transition: background-color $swift-ease-in-duration $swift-ease-in-timing-function;
}
// Gain some space on the right side of the folder icon
.md-list-item-inner > md-icon:first-child,
.md-list-item-inner > md-checkbox:first-child {
margin-right: $bl * 2;
}
}
}
// Add some padding to the first icon in a list item
@ -53,10 +79,12 @@ md-sidenav {
.md-tile-left,
.md-tile-right {
display: block;
border-radius: 100%;
border-radius: 50%;
padding: $layout-gutter-width;
width: $sg-md-grid-pitch + $baseline-grid;
height: $sg-md-grid-pitch + $baseline-grid;
padding: $baseline-grid * 1.5;
padding: ($sg-md-grid-pitch - $sg-avatar-width) / 2;
width: $sg-md-grid-pitch;
height: $sg-md-grid-pitch;
//line-height: $sg-md-grid-pitch + $baseline-grid;
background-clip: content-box;
md-icon {
@ -83,51 +111,55 @@ div.md-tile-left {
}
.sg {
&-color-chip {
display: block;
border-radius: 50%;
margin-right: $bl;
margin-left: -($bl);
border-width: ($sg-avatar-width - $sg-color-chip-width) / 2;
border-color: white;
border-style: solid;
width: $sg-color-chip-width;
height: $sg-color-chip-width;
width: $sg-avatar-width;
height: $sg-avatar-width;
}
&-tile-content {
align-items: baseline;
flex-direction: row;
flex-wrap: wrap;
flex: 1;
justify-content: space-between;
p {
margin: $list-p-margin;
font-size: sg-size(body);
}
.msg-date {
float: right;
.sg-tile-date {
font-size: sg-size(body);
font-weight: $sg-font-light;
line-height: $sg-line-height-2;
margin-left: 1em;
flex-shrink: 0;
}
.#{$md}-subhead-multi,
.#{$md}-subhead-solo,
.#{$md}-body-multi {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.#{$md}-subhead-multi {
.#{$md}-subhead {
@extend .#{$md}-body-1;
font-size: initial;
}
.#{$md}-body-multi {
.#{$md}-body {
@extend .#{$md}-caption;
}
.#{$md}-subhead,
.#{$md}-body {
display: flex;
justify-content: space-between;
align-items: center;
> * {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
// Small tile of vertically-aligned icons
&-tile-icons {
md-icon {
font-size: $sg-font-size-1;
color: $colorGray;
margin: 2px;
}
display: flex;
flex-direction: column;
align-items: center;
justify-content: start;
width: (2 * $mg);
height:(7 * $line);
height:(2 + $sg-font-size-1) * 4; // (vertical padding + icon size) * max number of icons
}
&-counter-badge {
@ -140,37 +172,59 @@ div.md-tile-left {
font-weight: $sg-font-medium;
text-transform: uppercase;
}
&-tile-content,
&-tile-icons {
md-icon {
font-size: $sg-font-size-1;
color: $colorGray;
margin: 1px 2px;
}
}
}
.sg-avatars {
margin: ($mg / 2) 0 0 ($mg / 2);
.card-picture {
.md-avatar {
display: block;
// From md-list-item > .md-avatar:first-child
width: $list-item-primary-avatar-width;
height: $list-item-primary-avatar-width;
margin-top: $baseline-grid;
margin-bottom: $baseline-grid;
margin-right: $list-item-primary-width - $list-item-primary-avatar-width;
border-radius: 50%;
box-sizing: content-box;
img {
width: initial !important;
}
}
}
sg-avatar-image {
img {
border-radius: 100%;
margin-right: ($mg / 2);
border-radius: 50%;
}
}
// Avatar placeholder
// ------------------------------------
.md-tile-left:before,
.md-tile-left md-icon {
.md-avatar:before,
.md-avatar md-icon {
font-family: 'Material Icons';
font-size: 40px;
font-size: $sg-avatar-width;
color: rgba(0, 0, 0, 0.26);
}
//.md-tile-left-card {
// @extend .md-tile-left;
// &:before {
// content: "\e7fd"; // person
// }
//}
.md-tile-left-list {
@extend .md-tile-left;
.sg-avatar-list {
&:before {
content: "\e7ef"; // group
}
}
.md-tile-left-selected {
@extend .md-tile-left;
.sg-avatar-public {
&:before {
content: "\e80b"; // public
}
}
.sg-avatar-selected {
&:before {
content: "\e5ca"; // check
}
@ -203,21 +257,21 @@ div.md-tile-left {
// background-color: rgba(255, 255, 0, 0.3) !important;
// content: "\e7fd"; // person
//}
.sg-avatar {
//.sg-avatar {
// @extend .md-tile-left-card;
// margin-right: 0;
// margin-left: 0;
}
.sg-list-avatar {
@extend .md-tile-left-list;
margin-right: 0;
margin-left: 0;
}
.sg-selected-avatar {
@extend .md-tile-left-selected;
margin-right: 0;
margin-left: 0;
}
//}
//.sg-list-avatar {
// @extend .md-tile-left-list;
// margin-right: 0;
// margin-left: 0;
//}
//.sg-selected-avatar {
// @extend .md-tile-left-selected;
// margin-right: 0;
// margin-left: 0;
//}
//.sg-accepted {
// @extend .md-tile-left-accepted;
// margin-right: 0;

View File

@ -37,11 +37,3 @@ $i: 1;
.sg-active i.md-icon-folder:before {
@extend .md-icon-folder-open:before;
}
.md-sidenav-left {
md-list-item {
.md-button {
transition: background-color $swift-ease-in-duration $swift-ease-in-timing-function;
}
}
}

View File

@ -12,11 +12,11 @@
}
.unread {
.#{$md}-subhead-multi,
.#{$md}-body-multi {
.#{$md}-subhead,
.#{$md}-body {
font-weight: $sg-font-medium;
}
.msg-date {
.sg-tile-date {
color: sg-color($sogoBlue, 600);
}
}

View File

@ -25,6 +25,16 @@ $scrollbar_width: 16px;
@include from(lg) {
@include flex-col(lg, 5, 1, 0);
}
// The color chip is smaller; adjust the "selected" icon accordingly
.sg-avatar-selected {
&:before {
margin-left: -($bl);
}
&.md-avatar:first-child {
margin-right: 0;
}
}
}
.view-detail {