Building Slack in Angular with Covalent

Kyle Ledbetter
Published in
6 min readMay 8, 2017

Simple steps to prototype an chat application in Angular Material

Material Design Slack built on Angular v4 with Covalent

What we’re building

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

What’s Covalent?

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.

Change the app color theme

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)

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

Choosing a layout

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.

Nav List

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="">

Here we have 3 components:

  • td-layout
  • td-navigation-drawer
  • td-layout-nav-list
This gives us an off-screen navigation drawer, toolbar, left nav and content area

Toolbar content

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.

<div td-sidenav-toolbar-content layout="row" flex>
<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>
A dropdown team menu

Notification settings 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>
<button md-menu-item>Settings for #channel</button>
<button md-menu-item>Notifications preferences...</button>
A notification settings menu

Channel & DM Navigation

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
<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>
<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>
<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>
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">
<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>
<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>
Good lord Slack has a lot of buttons in their toolbar

Chat Content

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]">
<img md-list-avatar src="{{i}}" />
<h3 md-line class="cursor-pointer"> Firstname Lastname </h3>
<p md-line>
<span class="text-wrap">
Farm-to-table poke distillery...
<md-divider *ngIf="!last" md-inset></md-divider>

Message bar

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.

<div layout="row" layout-align="start center">
<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-input-container class="push-left push-right" flex layout="row" floatPlaceholder="never">
<textarea flex mdInput placeholder="message"></textarea>
<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">
<div td-menu-header>
<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 td-menu-footer>
<div layout="row" layout-align="center center" class="push-sm">
<span class="md-subhead">Emoji Deluxe</span>
<span flex></span>
Atom Slack message bar design

Bonus: Add a right sidenav

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
main content
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!

Interested in a Part II?

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




Kyle Ledbetter

VP of Design at Credo AI — Former UX leader for Teradata, eBay, MicroStrategy and Sears Holdings.