273 lines
8.2 KiB
SCSS
273 lines
8.2 KiB
SCSS
|
|
@use '@angular/cdk';
|
||
|
|
|
||
|
|
@use '../core/tokens/m2/mat/sidenav' as tokens-mat-sidenav;
|
||
|
|
@use '../core/tokens/token-utils';
|
||
|
|
@use '../core/style/variables';
|
||
|
|
@use '../core/style/layout-common';
|
||
|
|
|
||
|
|
$drawer-content-z-index: 1;
|
||
|
|
$drawer-side-drawer-z-index: 2;
|
||
|
|
$drawer-backdrop-z-index: 3;
|
||
|
|
$drawer-over-drawer-z-index: 4;
|
||
|
|
|
||
|
|
// Mixin that creates a new stacking context.
|
||
|
|
// see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
|
||
|
|
@mixin drawer-stacking-context($z-index: 1) {
|
||
|
|
position: relative;
|
||
|
|
|
||
|
|
// Use a z-index to create a new stacking context. (We can't use transform because it breaks fixed
|
||
|
|
// positioning inside of the transformed element).
|
||
|
|
z-index: $z-index;
|
||
|
|
}
|
||
|
|
|
||
|
|
.mat-drawer-container {
|
||
|
|
// We need a stacking context here so that the backdrop and drawers are clipped to the
|
||
|
|
// MatDrawerContainer. This creates a new z-index stack so we use low numbered z-indices.
|
||
|
|
// We create another stacking context in the '.mat-drawer-content' and in each drawer so that
|
||
|
|
// the application content does not get messed up with our own CSS.
|
||
|
|
@include drawer-stacking-context();
|
||
|
|
|
||
|
|
@include token-utils.use-tokens(
|
||
|
|
tokens-mat-sidenav.$prefix,
|
||
|
|
tokens-mat-sidenav.get-token-slots()
|
||
|
|
) {
|
||
|
|
@include token-utils.create-token-slot(color, content-text-color);
|
||
|
|
@include token-utils.create-token-slot(background-color, content-background-color);
|
||
|
|
}
|
||
|
|
|
||
|
|
box-sizing: border-box;
|
||
|
|
|
||
|
|
// Need this to take up space in the layout.
|
||
|
|
display: block;
|
||
|
|
|
||
|
|
// Hide the drawers when they're closed.
|
||
|
|
overflow: hidden;
|
||
|
|
|
||
|
|
// TODO(hansl): Update this with a more robust solution.
|
||
|
|
&[fullscreen] {
|
||
|
|
@include layout-common.fill();
|
||
|
|
|
||
|
|
&.mat-drawer-container-has-open {
|
||
|
|
overflow: hidden;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// When the consumer explicitly enabled the backdrop,
|
||
|
|
// we have to pull the side drawers above it.
|
||
|
|
&.mat-drawer-container-explicit-backdrop .mat-drawer-side {
|
||
|
|
z-index: $drawer-backdrop-z-index;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Note that the `NoopAnimationsModule` is being handled inside of the component code.
|
||
|
|
&.ng-animate-disabled,
|
||
|
|
.ng-animate-disabled & {
|
||
|
|
.mat-drawer-backdrop,
|
||
|
|
.mat-drawer-content {
|
||
|
|
transition: none;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.mat-drawer-backdrop {
|
||
|
|
@include layout-common.fill();
|
||
|
|
|
||
|
|
display: block;
|
||
|
|
|
||
|
|
// Because of the new stacking context, the z-index stack is new and we can use our own
|
||
|
|
// numbers.
|
||
|
|
z-index: $drawer-backdrop-z-index;
|
||
|
|
|
||
|
|
// We use 'visibility: hidden | visible' because 'display: none' will not animate any
|
||
|
|
// transitions, while visibility will interpolate transitions properly.
|
||
|
|
// see https://developer.mozilla.org/en-US/docs/Web/CSS/visibility, the Interpolation
|
||
|
|
// section.
|
||
|
|
visibility: hidden;
|
||
|
|
|
||
|
|
&.mat-drawer-shown {
|
||
|
|
visibility: visible;
|
||
|
|
|
||
|
|
@include token-utils.use-tokens(
|
||
|
|
tokens-mat-sidenav.$prefix,
|
||
|
|
tokens-mat-sidenav.get-token-slots()
|
||
|
|
) {
|
||
|
|
@include token-utils.create-token-slot(background-color, scrim-color);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.mat-drawer-transition & {
|
||
|
|
transition: {
|
||
|
|
duration: variables.$swift-ease-out-duration;
|
||
|
|
timing-function: variables.$swift-ease-out-timing-function;
|
||
|
|
property: background-color, visibility;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@include cdk.high-contrast {
|
||
|
|
opacity: 0.5;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.mat-drawer-content {
|
||
|
|
@include drawer-stacking-context($drawer-content-z-index);
|
||
|
|
|
||
|
|
display: block;
|
||
|
|
height: 100%;
|
||
|
|
overflow: auto;
|
||
|
|
|
||
|
|
&.mat-drawer-content-hidden {
|
||
|
|
opacity: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.mat-drawer-transition & {
|
||
|
|
transition: {
|
||
|
|
duration: variables.$swift-ease-out-duration;
|
||
|
|
timing-function: variables.$swift-ease-out-timing-function;
|
||
|
|
property: transform, margin-left, margin-right;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.mat-drawer {
|
||
|
|
$high-contrast-border: solid 1px currentColor;
|
||
|
|
|
||
|
|
@include drawer-stacking-context($drawer-over-drawer-z-index);
|
||
|
|
|
||
|
|
@include token-utils.use-tokens(
|
||
|
|
tokens-mat-sidenav.$prefix,
|
||
|
|
tokens-mat-sidenav.get-token-slots()
|
||
|
|
) {
|
||
|
|
@include token-utils.create-token-slot(color, container-text-color);
|
||
|
|
@include token-utils.create-token-slot(box-shadow, container-elevation-shadow);
|
||
|
|
@include token-utils.create-token-slot(background-color, container-background-color);
|
||
|
|
@include token-utils.create-token-slot(border-top-right-radius, container-shape);
|
||
|
|
@include token-utils.create-token-slot(border-bottom-right-radius, container-shape);
|
||
|
|
@include token-utils.create-token-slot(width, container-width);
|
||
|
|
}
|
||
|
|
|
||
|
|
display: block;
|
||
|
|
position: absolute;
|
||
|
|
top: 0;
|
||
|
|
bottom: 0;
|
||
|
|
z-index: 3;
|
||
|
|
outline: 0;
|
||
|
|
box-sizing: border-box;
|
||
|
|
overflow-y: auto; // TODO(kara): revisit scrolling behavior for drawers
|
||
|
|
transform: translate3d(-100%, 0, 0);
|
||
|
|
|
||
|
|
&,
|
||
|
|
[dir='rtl'] &.mat-drawer-end {
|
||
|
|
@include cdk.high-contrast {
|
||
|
|
border-right: $high-contrast-border;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
[dir='rtl'] &,
|
||
|
|
&.mat-drawer-end {
|
||
|
|
@include cdk.high-contrast {
|
||
|
|
border-left: $high-contrast-border;
|
||
|
|
border-right: none;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
&.mat-drawer-side {
|
||
|
|
z-index: $drawer-side-drawer-z-index;
|
||
|
|
}
|
||
|
|
|
||
|
|
&.mat-drawer-end {
|
||
|
|
right: 0;
|
||
|
|
transform: translate3d(100%, 0, 0);
|
||
|
|
|
||
|
|
@include token-utils.use-tokens(
|
||
|
|
tokens-mat-sidenav.$prefix,
|
||
|
|
tokens-mat-sidenav.get-token-slots()
|
||
|
|
) {
|
||
|
|
@include token-utils.create-token-slot(border-top-left-radius, container-shape);
|
||
|
|
@include token-utils.create-token-slot(border-bottom-left-radius, container-shape);
|
||
|
|
border-top-right-radius: 0;
|
||
|
|
border-bottom-right-radius: 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
[dir='rtl'] & {
|
||
|
|
@include token-utils.use-tokens(
|
||
|
|
tokens-mat-sidenav.$prefix,
|
||
|
|
tokens-mat-sidenav.get-token-slots()
|
||
|
|
) {
|
||
|
|
@include token-utils.create-token-slot(border-top-left-radius, container-shape);
|
||
|
|
@include token-utils.create-token-slot(border-bottom-left-radius, container-shape);
|
||
|
|
border-top-right-radius: 0;
|
||
|
|
border-bottom-right-radius: 0;
|
||
|
|
transform: translate3d(100%, 0, 0);
|
||
|
|
|
||
|
|
&.mat-drawer-end {
|
||
|
|
@include token-utils.create-token-slot(border-top-right-radius, container-shape);
|
||
|
|
@include token-utils.create-token-slot(border-bottom-right-radius, container-shape);
|
||
|
|
border-top-left-radius: 0;
|
||
|
|
border-bottom-left-radius: 0;
|
||
|
|
left: 0;
|
||
|
|
right: auto;
|
||
|
|
transform: translate3d(-100%, 0, 0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Usually the `visibility: hidden` added by the animation is enough to prevent focus from
|
||
|
|
// entering the hidden drawer content, but children with their own `visibility` can override it.
|
||
|
|
// This is a fallback that completely hides the content when the element becomes hidden.
|
||
|
|
// Note that we can't do this in the animation definition, because the style gets recomputed too
|
||
|
|
// late, breaking the animation because Angular didn't have time to figure out the target
|
||
|
|
// transform. This can also be achieved with JS, but it has issues when starting an
|
||
|
|
// animation before the previous one has finished.
|
||
|
|
&[style*='visibility: hidden'] {
|
||
|
|
display: none;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.mat-drawer-side {
|
||
|
|
box-shadow: none;
|
||
|
|
|
||
|
|
@include token-utils.use-tokens(
|
||
|
|
tokens-mat-sidenav.$prefix,
|
||
|
|
tokens-mat-sidenav.get-token-slots()
|
||
|
|
) {
|
||
|
|
@include token-utils.create-token-slot(border-right-color, container-divider-color);
|
||
|
|
border-right-width: 1px;
|
||
|
|
border-right-style: solid;
|
||
|
|
|
||
|
|
&.mat-drawer-end {
|
||
|
|
@include token-utils.create-token-slot(border-left-color, container-divider-color);
|
||
|
|
border-left-width: 1px;
|
||
|
|
border-left-style: solid;
|
||
|
|
border-right: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
[dir='rtl'] & {
|
||
|
|
@include token-utils.create-token-slot(border-left-color, container-divider-color);
|
||
|
|
border-left-width: 1px;
|
||
|
|
border-left-style: solid;
|
||
|
|
border-right: none; // Clears the default LTR border.
|
||
|
|
|
||
|
|
&.mat-drawer-end {
|
||
|
|
@include token-utils.create-token-slot(border-right-color, container-divider-color);
|
||
|
|
border-right-width: 1px;
|
||
|
|
border-right-style: solid;
|
||
|
|
border-left: none;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Note that this div isn't strictly necessary on all browsers, however we need it in
|
||
|
|
// order to avoid a layout issue in Chrome. The issue is that in RTL mode the browser doesn't
|
||
|
|
// account for the sidenav's scrollbar while positioning, which ends up pushing it partially
|
||
|
|
// out of the screen. We work around the issue by having the scrollbar be on this inner container.
|
||
|
|
.mat-drawer-inner-container {
|
||
|
|
width: 100%;
|
||
|
|
height: 100%;
|
||
|
|
overflow: auto;
|
||
|
|
}
|
||
|
|
|
||
|
|
.mat-sidenav-fixed {
|
||
|
|
position: fixed;
|
||
|
|
}
|