Styling and Refinements
We just have a few things to finish up in this lesson to polish off the application, these are:
- Supplying the active user as an input to the message list component so we can provide different styles for the user’s own messages
- Adding
CdkScrollable
from the Angular CDK to provide a better UX - General styling
Let’s get into it!
Active User Input
If you create a second account and add some more messages to the chat, you will notice that all of the messages have the same styling. Typically in a chat application you would have the users own messages appear on a different side of the screen.
Add the following input to the
MessageListComponent
:
activeUser = input.required<AuthUser>();
Modify the
<li>
in the template to reflect the following:
<ul class="gradient-bg">
@for (message of messages(); track message.created){
<li
[style.flex-direction]="
message.author === activeUser()?.email ? 'row-reverse' : 'row'
"
>
Now we are using the activeUser
value to determine the flex-direction
for
the item. If the currently authenticated user matches the author of the message
we will use row-reverse
, otherwise we will use row
. This will swap which
side of the screen the message is aligned to.
Pass the
activeUser
into the component:
<app-message-list
[messages]="messageService.messages()"
[activeUser]="authService.user()"
/>
General Styling
Things are generally functional now, but they don’t look good and there are still aspects that make the application awkward to use — the message input bar for example will go off the bottom of the screen if there are too many messages.
We are going to create a custom Angular Material theme for our application now — which will make things look nicer — and we will also add some styling to deal with the message bar situation.
When we first created the application we installed Angular Material and we
chose the Custom
theme option. If you take a look at your src/styles.scss
file you might notice some interesting code like this:
// Custom Theming for Angular Material
// For more information: https://material.angular.io/guide/theming
@use '@angular/material' as mat;
// Plus imports for other components in your app.
// Include the common styles for Angular Material. We include this here so that you only
// have to load a single css file for Angular Material in your app.
// Be sure that you only ever include this mixin once!
@include mat.core();
// Define the palettes for your theme using the Material Design palettes available in palette.scss
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
// hue. Available color palettes: https://material.io/design/color/
$chat-test-primary: mat.define-palette(mat.$indigo-palette);
$chat-test-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);
// The warn palette is optional (defaults to red).
$chat-test-warn: mat.define-palette(mat.$red-palette);
// Create the theme object. A theme consists of configurations for individual
// theming systems such as "color" or "typography".
$chat-test-theme: mat.define-light-theme((
color: (
primary: $chat-test-primary,
accent: $chat-test-accent,
warn: $chat-test-warn,
)
));
// Include theme styles for core and each component used in your app.
// Alternatively, you can import and @include the theme mixins for each component
// that you are using.
@include mat.all-component-themes($chat-test-theme);
The default comments here are actually quite helpful, but let’s talk through
a few things here. One of the key aspects we are going to configure here are our
“palettes”. You can see we have a primary
, accent
, and warn
palette by
default. The general role of these are:
primary
: the “main” colour of the applicationaccent
: a secondary colour to contrast the primary colourwarn
: a colour to attract attention to warnings etc.
For each of these palettes we can also configure a default
, lighter
, and
darker
version of the colour we are using.
You can see that the palettes are being defined like this:
$chat-test-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);
We supply one of the default Angular Material palettes, and then to configure
our default
, lighter
, and darker
values we supply three additional
parameters: A200
, A100
, A400
. Those are quite meaningless, but you can see
what these values actually are by inspecting the palette in the
documentation.
We are going to replace these with our own colours:
Modify your
src/styles.scss
file to reflect the following:
// Custom Theming for Angular Material
// For more information: https://material.angular.io/guide/theming
@use "@angular/material" as mat;
// Plus imports for other components in your app.
// Include the common styles for Angular Material. We include this here so that you only
// have to load a single css file for Angular Material in your app.
// Be sure that you only ever include this mixin once!
@include mat.core();
// Define the palettes for your theme using the Material Design palettes available in palette.scss
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
// hue. Available color palettes: https://material.io/design/color/
$angularstart-chat-primary: mat.m2-define-palette(mat.$m2-orange-palette);
$angularstart-chat-accent: mat.m2-define-palette(
mat.$m2-blue-gray-palette,
700,
800,
900
);
// The warn palette is optional (defaults to red).
$angularstart-chat-warn: mat.m2-define-palette(mat.$m2-red-palette);
// Create the theme object. A theme consists of configurations for individual
// theming systems such as "color" or "typography".
$angularstart-chat-theme: mat.m2-define-light-theme(
(
color: (
primary: $angularstart-chat-primary,
accent: $angularstart-chat-accent,
warn: $angularstart-chat-warn,
),
)
);
// Include theme styles for core and each component used in your app.
// Alternatively, you can import and @include the theme mixins for each component
// that you are using.
@include mat.all-component-themes($angularstart-chat-theme);
/* You can add global styles to this file, and also import other style files */
html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }