Building Slack in Angular with Covalent

Kyle Ledbetter
May 8, 2017 · 6 min read

Simple steps to prototype an chat application in Angular Material

Image for post
Image for post
Material Design Slack built on Angular v4 with Covalent
Image for post
Image for post

We will quickly build a responsive layout with all the main UI elements and interactions of the Slack desktop app using Angular components from Angular Material and Covalent. Using atomic design we will build this layout all with existing UI elements and zero custom SCSS.

Check out the final prototype in plunker

At Teradata we created Covalent to fill the need for a rapid prototyping tool to serve a global organization and quickly flip mock applications to enterprise products.

Changing the entire application color scheme is simple with Angular Material’s theme. Edit /src/theme.scss and change the $primary and $accent colors (referring to the material color palette) to the class purple & teal Slack theme. (need more info? check out my theme tutorial)

Image for post
Image for post
Our theme (made using Material Design color tool)
$primary: mat-palette($mat-purple, 700);
$accent: mat-palette($mat-teal, A700, A100, A400);

Although Angular Material comes with a sidenav and toolbar, there is no premade layouts. Covalent has us covered with 4 responsive layouts following the Material Design spec.

Image for post
Image for post
Image for post
Image for post
Nav List Layout

The nav-list layout features a persistent left nav that will be perfect for Slack channels.

<td-layout #layout>
<td-navigation-drawer sidenavTitle="Angular Slack" name="Firstname Lastname" email="firstname.lastname@company.com">
</td-navigation-drawer>
<td-layout-nav-list>
content
</td-layout-nav-list>
</td-layout>
  • td-layout
  • td-navigation-drawer
  • td-layout-nav-list
Image for post
Image for post
Image for post
Image for post
This gives us an off-screen navigation drawer, toolbar, left nav and content area

Next let’s override the top sticky toolbars in the left nav and main content area to mimic Slack’s toolbars.

While we could use toolbarTitle=”Team Name” for a toolbar title, we want to mimic Slack’s team & notification options. For that we’ll use an override with a md-menu dropdown and an arrow_drop_down md-icon. Notice we’re using a flexbox layout as well.

<td-layout-nav-list>
<div td-sidenav-toolbar-content layout="row" flex>
<div>
<button md-button [mdMenuTriggerFor]="menu">Team Name <md-icon>arrow_drop_down</md-icon></button>
<md-menu #menu="mdMenu">
<button md-menu-item>Set a status</button>
...
</md-menu>
</div>
</div>
...
</td-layout-nav-list>
Image for post
Image for post
A dropdown team menu

Now we’ll add another md-menu to the right w/ a notification icon & dropdown. Notice we’re using a md-icon-button instead of md-button and on the md-menu we added a x-position=”before” so the menu opens to the left.

<button md-icon-button [mdMenuTriggerFor]="notifyMenu"><md-icon>notifications_off</md-icon></button><md-menu #notifyMenu="mdMenu" x-position="before">
<button md-menu-item>Do not disturb ON</button>
...
<md-divider></md-divider>
<button md-menu-item>Settings for #channel</button>
<button md-menu-item>Notifications preferences...</button>
</md-menu>
Image for post
Image for post
A notification settings menu

The channel & user left nav is populated using md-nav-list with md-list-item and md-list-icon. Notice the user of ng-template w/ an array for easy prototyping:

<md-nav-list td-sidenav-content>
<a md-list-item><md-icon md-list-icon>sort</md-icon> All Unreads</a
<a md-list-item><md-icon md-list-icon>chat</md-icon> All Threads</a
<md-divider></md-divider>
<h3 md-subheader>STARRED</h3>
<ng-template let-item let-i="index" let-last="last" ngFor [ngForOf]="[0,1]">
<a md-list-item><md-icon md-list-icon>#</md-icon> starred-channel-{{i}}</a>
</ng-template>
<md-divider></md-divider>
<h3 md-subheader>CHANNELS (5)</h3>
<ng-template let-item let-i="index" let-last="last" ngFor [ngForOf]="[0,1,2,3]">
<a md-list-item><md-icon md-list-icon>#</md-icon> channel-name-{{i}}</a>
</ng-template>
<md-divider></md-divider>
<h3 md-subheader>DIRECT MESSAGES</h3>
<ng-template let-item let-i="index" let-last="last" ngFor [ngForOf]="[0,1,2,3,4,5]">
<a md-list-item><md-icon color="accent" md-list-icon>lens</md-icon> username{{i}}</a>
</ng-template>
</md-nav-list>
Image for post
Image for post
A scrollable left nav with teams & direct messages

For the main toolbar we’re going to use a combo of Angular-Material and Covalent components with a slew of utility classes included with Covalent.

<div td-toolbar-content layout="row" layout-align="start center" flex><div>
<div [mdMenuTriggerFor]="channelMenu" class="cursor-hover">#channel</div>
<md-menu #channelMenu="mdMenu">
...
</md-menu>
<div layout="row" layout-align="start center">
<md-icon class="md-caption">star</md-icon>
<md-icon class="md-caption push-left-sm">person</md-icon>
<span class="md-caption">94</span>
<md-icon class="md-caption push-left-sm">note</md-icon>
<span class="md-caption">12</span>
<span class="md-caption push-left-sm">channel description</span>
</div>
</div>
<span flex></span> <td-search-box placeholder="Search" [showUnderline]="false"></td-search-box> <button md-icon-button mdTooltip="Call"><md-icon>phone</md-icon></button>
<button md-icon-button mdTooltip="Conversation settings"><md-icon>settings</md-icon></button>
<button md-icon-button mdTooltip="Show conversation details"><md-icon>chrome_reader_mode</md-icon></button>
<button md-icon-button mdTooltip="Show activity"><md-icon>@</md-icon></button>
<button md-icon-button mdTooltip="Show starred items"><md-icon>star_border</md-icon></button>
<button md-icon-button mdTooltip="More items"><md-icon>more_vert</md-icon></button>
</div>
Image for post
Image for post
Good lord Slack has a lot of buttons in their toolbar

Now onto the main content area! We’ll use a md-card to hold a md-list and repeat some md-list-items with avatars and dummy text. Notice how we use the Covalent media query to add some margin to the md-card on browsers greater than xtra-small.

<md-card tdMediaToggle="gt-xs" [mediaClasses]="['push-sm']">  <md-list>
<ng-template let-item let-i="index" let-last="last" ngFor [ngForOf]="[0,1,2,3,4,5,6,7,8,9]">
<md-list-item>
<img md-list-avatar src="http://lorempixel.com/40/40/people/{{i}}" />
<h3 md-line class="cursor-pointer"> Firstname Lastname </h3>
<p md-line>
<span class="text-wrap">
Farm-to-table poke distillery...
</span>
</p>
</md-list-item>
<md-divider *ngIf="!last" md-inset></md-divider>
</ng-template>
</md-list>
</md-card>
Image for post
Image for post

Now for the message bar! We’ll use a fun blend of items to achieve a quasi-realistic Slack messaging toolbar, ranging from a textarea w/ mdInput to a td-menu component wrapper for md-menu.

<td-layout-footer-inner>
<div layout="row" layout-align="start center">
<div>
<button md-icon-button mdTooltip="Add content" mdTooltipPosition="after" [mdMenuTriggerFor]="chatMenu"><md-icon>add</md-icon></button> <md-menu #chatMenu="mdMenu">
<button md-menu-item>Code or text snippet</button>
...
</md-menu>
</div>
<md-input-container class="push-left push-right" flex layout="row" floatPlaceholder="never">
<textarea flex mdInput placeholder="message"></textarea>
</md-input-container>
<div> <button md-icon-button mdTooltip="Add emoji" mdTooltipPosition="before" [mdMenuTriggerFor]="emojiMenu"><md-icon>sentiment_very_satisfied</md-icon></button> <md-menu #emojiMenu="mdMenu" x-position="before">
<td-menu>
<div td-menu-header>
<md-button-toggle><md-icon>access_time</md-icon></md-button-toggle>
...
</div>
<div class="push">
<div layout="row" layout-wrap>
<button flex="20" md-icon-button><md-icon>mood</md-icon></button>
<button flex="20" md-icon-button><md-icon>mood_bad</md-icon></button>
...
</div>
</div>
<div td-menu-footer>
<div layout="row" layout-align="center center" class="push-sm">
<span class="md-subhead">Emoji Deluxe</span>
<span flex></span>
<span>:happy:</span>
<md-icon>sentiment_very_satisfied</md-icon>
</div>
</div>
</td-menu>
</md-menu>
</div>
</div>
</td-layout-footer-inner>
Image for post
Image for post
Atom Slack message bar design

In Slack you can toggle a right sidenav for channel info. We can easily achieve this with an Angular Material sidenav but wrapping our content area (toggle the sidenav with (click)=”channelInfo.toggle()”).

<md-sidenav-container fullscreen>
<md-sidenav #channelInfo mode="side" align="end">
sidenav content
</md-sidenav>
main content
</md-sidenav-container>
Image for post
Image for post
With a few lines of extra code we have an About channel sidenav!

That was easy right?

With some powerful tools and a little bit of creativity, you’ve got yourself a material design Slack clone built on Angular v4 in a matter of minutes! Feel free to fork the code and have fun with Covalent!

Would you like to take this a step further and build into a functional chat app? Let us know in comments!

Covalent-UI

Teradata open-source UI Platform built on Angular +…

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store