Skip to content

Instantly share code, notes, and snippets.

@zakmac
Last active December 9, 2020 19:47
Show Gist options
  • Save zakmac/67efd8aa3628e3c7d3af83855d6d83f6 to your computer and use it in GitHub Desktop.
Save zakmac/67efd8aa3628e3c7d3af83855d6d83f6 to your computer and use it in GitHub Desktop.
Angular Material List Density Generator Mixin -- Based on Official Material Styles
@import '~@angular/material/theming';
@import '~@angular/material/divider/divider-offset';
@import '~@angular/material/list/list-theme';
@import './angular-material-list-density.variables';
@function _list-density-values(
$density-config,
$density-scale: default
) {
@return (
avatar-height: _mat-density-prop-value(
$density-config,
$density-scale,
avatar-height,
),
avatar-size: _mat-density-prop-value(
$density-config,
$density-scale,
avatar-size,
),
base-height: _mat-density-prop-value(
$density-config,
$density-scale,
base-height,
),
inset-divider-offset: _mat-density-prop-value(
$density-config,
$density-scale,
inset-divider-offset,
),
icon-size: _mat-density-prop-value(
$density-config,
$density-scale,
icon-size,
),
three-line-height: _mat-density-prop-value(
$density-config,
$density-scale,
three-line-height,
),
two-line-height: _mat-density-prop-value(
$density-config,
$density-scale,
two-line-height,
),
padding-icon: _mat-density-prop-value(
$density-config,
$density-scale,
padding-icon,
),
padding-multi-line: _mat-density-prop-value(
$density-config,
$density-scale,
padding-multi-line,
),
padding-side: _mat-density-prop-value(
$density-config,
$density-scale,
padding-side,
),
padding-top: _mat-density-prop-value(
$density-config,
$density-scale,
padding-top,
),
); // @return
} // @_list-density-values
@mixin list-subheader-spacing(
$density-config,
$density-scale: default
) {
$density-values: _list-density-values($density-config, $density-scale);
$density-base-height: map-get($density-values, base-height);
$density-padding-side: map-get($density-values, padding-side);
$density-padding-top: map-get($density-values, padding-top);
height: $density-base-height;
line-height: $density-base-height - $density-padding-side * 2;
&:first-child {
margin-top: -$density-padding-top;
}
} // @list-subheader-spacing
@mixin list-density(
$density-config,
$density-scale: default,
) {
$density-values: _list-density-values($density-config, $density-scale);
$density-padding-side: map-get($density-values, padding-side);
$density-padding-top: map-get($density-values, padding-top);
.mat-subheader {
padding: $density-padding-side;
// This needs slightly more specificity, because it
// can be overwritten by the typography styles.
.mat-list-base & {
margin: 0;
}
} // .mat-subheader
&.mat-list-base {
padding-top: $density-padding-top;
.mat-subheader {
@include list-subheader-spacing($density-config, $density-scale);
}
.mat-list-item,
.mat-list-option {
@include list-item-density($density-config, $density-scale); // @mat-list-item-base
} // .mat-list-item
} // .mat-list-base
} // @list-density
// This mixin provides all list-item styles, changing font size and height
// based on whether the list is in dense mode.
@mixin list-item-density(
$density-config,
$density-scale: default,
) {
$density-values: _list-density-values($density-config, $density-scale);
$density-avatar-height: map-get($density-values, avatar-height);
$density-avatar-size: map-get($density-values, avatar-size);
$density-base-height: map-get($density-values,base-height);
$density-icon-size: map-get($density-values, icon-size);
$density-three-line-height: map-get($density-values, three-line-height);
$density-two-line-height: map-get($density-values, two-line-height);
$density-padding-icon: map-get($density-values, padding-icon);
$density-padding-multi-line: map-get($density-values, padding-multi-line);
$density-padding-side: map-get($density-values, padding-side);
// Prevents the wrapper `mat-list-item-content` from collapsing due to it
// being `inline` by default.
height: $density-base-height;
// Override the user agent styling if the list item is a button.
padding: 0;
.mat-list-item-content {
padding: 0 $density-padding-side;
height: inherit;
}
.mat-list-item-content-reverse {
padding: 0 $density-padding-side;
}
&.mat-list-item-with-avatar {
height: $density-avatar-height;
}
&.mat-2-line {
height: $density-two-line-height;
}
&.mat-3-line {
height: $density-three-line-height;
}
// list items with more than 3 lines should expand to match
// the height of its contained text
&.mat-multi-line {
height: auto;
.mat-list-item-content {
padding-top: $density-padding-multi-line;
padding-bottom: $density-padding-multi-line;
}
}
.mat-list-text {
// By default, there will be no padding for the list item text because the padding is already
// set on the `mat-list-item-content` element. Later, if the list-item detects that there are
// secondary items (avatar, checkbox), a padding on the proper side will be added.
padding: 0;
}
&.mat-list-item-with-avatar,
&.mat-list-option {
.mat-list-item-content .mat-list-text {
padding-right: 0;
padding-left: $density-padding-side;
[dir='rtl'] & {
padding-right: $density-padding-side;
padding-left: 0;
}
}
// Reversed content is mainly used by the MatSelectionList for displaying the checkbox at the
// end of the list option. Since there is a secondary item (checkbox) at the end of the
// option, there needs to be a padding for the mat-list-text on the end-side.
.mat-list-item-content-reverse .mat-list-text {
padding-left: 0;
padding-right: $density-padding-side;
[dir='rtl'] & {
padding-right: 0;
padding-left: $density-padding-side;
}
}
}
&.mat-list-item-with-avatar.mat-list-option {
.mat-list-item-content-reverse .mat-list-text,
.mat-list-item-content .mat-list-text {
padding-right: $density-padding-side;
padding-left: $density-padding-side;
}
}
.mat-list-avatar {
width: $density-avatar-size;
height: $density-avatar-size;
~ .mat-divider-inset {
@include mat-inset-divider-offset($density-avatar-size, $density-padding-side);
}
}
.mat-list-icon {
width: $density-icon-size;
height: $density-icon-size;
font-size: $density-icon-size;
padding: $density-padding-icon;
~ .mat-divider-inset {
@include mat-inset-divider-offset($density-icon-size + (2 * $density-padding-icon),
$density-padding-side);
}
}
//.mat-divider {
// position: absolute;
// bottom: 0;
// left: 0;
// width: 100%;
// margin: 0;
//
// [dir='rtl'] & {
// margin-left: auto;
// margin-right: 0;
// }
//
// &.mat-divider-inset {
// position: absolute; // necessary to override card styles
// }
//} // .mat-divider
} // @list-item-density
// configure alternate list densities
$list-density-config: (
avatar-height: (
default: 3.5rem,
maximum: 4rem,
minimum: 3rem,
),
avatar-size: (
default: 2.5rem,
maximum: 2.75rem,
minimum: 2.25rem,
),
base-height: (
default: 3rem,
maximum: 3.5rem,
minimum: 2.5rem,
),
icon-size: (
default: 1.5rem,
maximum: 1.75rem,
minimum: 1.25rem,
),
inset-divider-offset: (
default: 4.5rem,
maximum: 4.5rem,
minimum: 4.5rem,
),
three-line-height: (
default: 5.5rem,
maximum: 6.5rem,
minimum: 4.5rem,
),
two-line-height: (
default: 4.5rem,
maximum: 5.25rem,
minimum: 3.75rem,
),
padding-icon: (
default: 0.25rem,
maximum: 0.25rem,
minimum: 0.25rem,
),
padding-multi-line: (
default: 1rem,
maximum: 1rem,
minimum: 1rem,
),
padding-side: (
default: 1rem,
maximum: 1rem,
minimum: 1rem,
),
padding-top: (
default: 0.5rem,
maximum: 0.75rem,
minimum: 0.25rem,
),
); // $list-density-config
@import './angular-material-list-density.generator';
@import './angular-material-list-density.variables';
// apply alternate list densities
.mat-list-base {
@include list-density($list-density-config);
&.max-density,
&.maximum-density {
@include list-density($list-density-config, minimum);
}
&.min-density,
&.minimum-density {
@include list-density($list-density-config, maximum);
}
} // .mat-list-base
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment