Skip to content

feat: add bottom sheet component #9764

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Angular Material components
/src/lib/* @jelbourn
/src/lib/autocomplete/** @kara @crisbeto
/src/lib/bottom-sheet/** @jelbourn @crisbeto
/src/lib/button-toggle/** @tinayuangao
/src/lib/button/** @tinayuangao
/src/lib/card/** @jelbourn
Expand Down Expand Up @@ -88,6 +89,7 @@
/src/demo-app/* @jelbourn
/src/demo-app/a11y/** @tinayuangao
/src/demo-app/autocomplete/** @kara @crisbeto
/src/demo-app/bottom-sheet/** @jelbourn @crisbeto
/src/demo-app/baseline/** @mmalerba
/src/demo-app/button-toggle/** @tinayuangao
/src/demo-app/button/** @tinayuangao
Expand Down
45 changes: 45 additions & 0 deletions src/demo-app/bottom-sheet/bottom-sheet-demo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<h1>Bottom sheet demo</h1>

<button mat-raised-button color="primary" (click)="openComponent()">Open component sheet</button>
<button mat-raised-button color="accent" (click)="openTemplate()">Open template sheet</button>

<mat-card class="demo-dialog-card">
<mat-card-content>
<h2>Options</h2>

<p>
<mat-checkbox [(ngModel)]="config.hasBackdrop">Has backdrop</mat-checkbox>
</p>

<p>
<mat-checkbox [(ngModel)]="config.disableClose">Disable close</mat-checkbox>
</p>

<p>
<mat-form-field>
<input matInput [(ngModel)]="config.backdropClass" placeholder="Backdrop class">
</mat-form-field>
</p>

<p>
<mat-form-field>
<mat-select placeholder="Direction" [(ngModel)]="config.direction">
<mat-option value="ltr">LTR</mat-option>
<mat-option value="rtl">RTL</mat-option>
</mat-select>
</mat-form-field>
</p>

</mat-card-content>
</mat-card>


<ng-template let-bottomSheetRef="bottomSheetRef">
<mat-nav-list>
<mat-list-item (click)="bottomSheetRef.dismiss()" *ngFor="let action of [1, 2, 3]">
<mat-icon mat-list-icon>folder</mat-icon>
<span mat-line>Action {{ link }}</span>
<span mat-line>Description</span>
</mat-list-item>
</mat-nav-list>
</ng-template>
8 changes: 8 additions & 0 deletions src/demo-app/bottom-sheet/bottom-sheet-demo.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.demo-dialog-card {
max-width: 405px;
margin: 20px 0;
}

.mat-raised-button {
margin-right: 5px;
}
66 changes: 66 additions & 0 deletions src/demo-app/bottom-sheet/bottom-sheet-demo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {Component, ViewEncapsulation, TemplateRef, ViewChild} from '@angular/core';
import {
MatBottomSheet,
MatBottomSheetRef,
MatBottomSheetConfig,
} from '@angular/material/bottom-sheet';

const defaultConfig = new MatBottomSheetConfig();

@Component({
moduleId: module.id,
selector: 'bottom-sheet-demo',
styleUrls: ['bottom-sheet-demo.css'],
templateUrl: 'bottom-sheet-demo.html',
encapsulation: ViewEncapsulation.None,
preserveWhitespaces: false,
})
export class BottomSheetDemo {
config: MatBottomSheetConfig = {
hasBackdrop: defaultConfig.hasBackdrop,
disableClose: defaultConfig.disableClose,
backdropClass: defaultConfig.backdropClass,
direction: 'ltr'
};

@ViewChild(TemplateRef) template: TemplateRef<any>;

constructor(private _bottomSheet: MatBottomSheet) {}

openComponent() {
this._bottomSheet.open(ExampleBottomSheet, this.config);
}

openTemplate() {
this._bottomSheet.open(this.template, this.config);
}
}


@Component({
template: `
<mat-nav-list>
<a href="#" mat-list-item (click)="handleClick($event)" *ngFor="let action of [1, 2, 3]">
<mat-icon mat-list-icon>folder</mat-icon>
<span mat-line>Action {{ link }}</span>
<span mat-line>Description</span>
</a>
</mat-nav-list>
`
})
export class ExampleBottomSheet {
constructor(private sheet: MatBottomSheetRef) {}

handleClick(event: MouseEvent) {
event.preventDefault();
this.sheet.dismiss();
}
}
1 change: 1 addition & 0 deletions src/demo-app/demo-app/demo-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export class DemoApp {
dark = false;
navItems = [
{name: 'Autocomplete', route: '/autocomplete'},
{name: 'Bottom sheet', route: '/bottom-sheet'},
{name: 'Button Toggle', route: '/button-toggle'},
{name: 'Button', route: '/button'},
{name: 'Card', route: '/card'},
Expand Down
4 changes: 4 additions & 0 deletions src/demo-app/demo-app/demo-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {NgModule} from '@angular/core';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {RouterModule} from '@angular/router';
import {AutocompleteDemo} from '../autocomplete/autocomplete-demo';
import {BottomSheetDemo, ExampleBottomSheet} from '../bottom-sheet/bottom-sheet-demo';
import {BaselineDemo} from '../baseline/baseline-demo';
import {ButtonToggleDemo} from '../button-toggle/button-toggle-demo';
import {ButtonDemo} from '../button/button-demo';
Expand Down Expand Up @@ -71,6 +72,7 @@ import {TableDemoModule} from '../table/table-demo-module';
],
declarations: [
AutocompleteDemo,
BottomSheetDemo,
BaselineDemo,
ButtonDemo,
ButtonToggleDemo,
Expand Down Expand Up @@ -120,6 +122,7 @@ import {TableDemoModule} from '../table/table-demo-module';
ToolbarDemo,
TooltipDemo,
TypographyDemo,
ExampleBottomSheet,
],
providers: [
{provide: OverlayContainer, useClass: FullscreenOverlayContainer},
Expand All @@ -133,6 +136,7 @@ import {TableDemoModule} from '../table/table-demo-module';
RotiniPanel,
ScienceJoke,
SpagettiPanel,
ExampleBottomSheet,
],
})
export class DemoModule {}
2 changes: 2 additions & 0 deletions src/demo-app/demo-app/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {Routes} from '@angular/router';
import {AccessibilityDemo} from '../a11y/a11y';
import {ACCESSIBILITY_DEMO_ROUTES} from '../a11y/routes';
import {AutocompleteDemo} from '../autocomplete/autocomplete-demo';
import {BottomSheetDemo} from '../bottom-sheet/bottom-sheet-demo';
import {BaselineDemo} from '../baseline/baseline-demo';
import {ButtonToggleDemo} from '../button-toggle/button-toggle-demo';
import {ButtonDemo} from '../button/button-demo';
Expand Down Expand Up @@ -55,6 +56,7 @@ export const DEMO_APP_ROUTES: Routes = [
{path: '', component: DemoApp, children: [
{path: '', component: Home},
{path: 'autocomplete', component: AutocompleteDemo},
{path: 'bottom-sheet', component: BottomSheetDemo},
{path: 'baseline', component: BaselineDemo},
{path: 'button', component: ButtonDemo},
{path: 'button-toggle', component: ButtonToggleDemo},
Expand Down
2 changes: 2 additions & 0 deletions src/demo-app/demo-material-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import {NgModule} from '@angular/core';
import {
MatAutocompleteModule,
MatBottomSheetModule,
MatButtonModule,
MatButtonToggleModule,
MatCardModule,
Expand Down Expand Up @@ -56,6 +57,7 @@ import {PortalModule} from '@angular/cdk/portal';
@NgModule({
exports: [
MatAutocompleteModule,
MatBottomSheetModule,
MatButtonModule,
MatButtonToggleModule,
MatCardModule,
Expand Down
1 change: 1 addition & 0 deletions src/demo-app/system-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ System.config({
'@angular/cdk/table': 'dist/packages/cdk/table/index.js',

'@angular/material/autocomplete': 'dist/packages/material/autocomplete/index.js',
'@angular/material/bottom-sheet': 'dist/packages/material/bottom-sheet/index.js',
'@angular/material/button': 'dist/packages/material/button/index.js',
'@angular/material/button-toggle': 'dist/packages/material/button-toggle/index.js',
'@angular/material/card': 'dist/packages/material/card/index.js',
Expand Down
1 change: 1 addition & 0 deletions src/e2e-app/system-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ System.config({
'@angular/material-examples': 'dist/bundles/material-examples.umd.js',

'@angular/material/autocomplete': 'dist/bundles/material-autocomplete.umd.js',
'@angular/material/bottom-sheet': 'dist/bundles/material-bottom-sheet.umd.js',
'@angular/material/button': 'dist/bundles/material-button.umd.js',
'@angular/material/button-toggle': 'dist/bundles/material-button-toggle.umd.js',
'@angular/material/card': 'dist/bundles/material-card.umd.js',
Expand Down
38 changes: 38 additions & 0 deletions src/lib/bottom-sheet/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package(default_visibility=["//visibility:public"])
load("@angular//:index.bzl", "ng_module")
load("@io_bazel_rules_sass//sass:sass.bzl", "sass_library", "sass_binary")


ng_module(
name = "bottom-sheet",
srcs = glob(["**/*.ts"], exclude=["**/*.spec.ts"]),
module_name = "@angular/material/bottom_sheet",
assets = [
":bottom_sheet_container_css",
],
deps = [
"//src/lib/core",
"//src/cdk/a11y",
"//src/cdk/overlay",
"//src/cdk/portal",
"//src/cdk/layout",
"@rxjs",
],
tsconfig = ":tsconfig-build.json",
)


sass_binary(
name = "bottom_sheet_container_scss",
src = "bottom-sheet-container.scss",
deps = ["//src/lib/core:core_scss_lib"],
)

# TODO(jelbourn): remove this when sass_binary supports specifying an output filename and dir.
# Copy the output of the sass_binary such that the filename and path match what we expect.
genrule(
name = "bottom_sheet_container_css",
srcs = [":bottom_sheet_container_scss"],
outs = ["bottom-sheet-container.css"],
cmd = "cat $(locations :bottom_sheet_container_scss) > $@",
)
1 change: 1 addition & 0 deletions src/lib/bottom-sheet/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Please see the official documentation at https://material.angular.io/components/component/bottom-sheet
21 changes: 21 additions & 0 deletions src/lib/bottom-sheet/_bottom-sheet-theme.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@import '../core/typography/typography-utils';
@import '../core/theming/palette';

@mixin mat-bottom-sheet-theme($theme) {
$background: map-get($theme, background);
$foreground: map-get($theme, foreground);

.mat-bottom-sheet-container {
background: mat-color($background, dialog);
color: mat-color($foreground, text);
}
}

@mixin mat-bottom-sheet-typography($config) {
.mat-bottom-sheet-container {
// Note: we don't use the line-height, because it's way too big.
font-family: mat-font-family($config);
font-size: mat-font-size($config, subheading-2);
font-weight: mat-font-weight($config, subheading-2);
}
}
31 changes: 31 additions & 0 deletions src/lib/bottom-sheet/bottom-sheet-animations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {
animate,
state,
style,
transition,
trigger,
AnimationTriggerMetadata,
} from '@angular/animations';
import {AnimationCurves, AnimationDurations} from '@angular/material/core';

/** Animations used by the Material bottom sheet. */
export const matBottomSheetAnimations: {
readonly bottomSheetState: AnimationTriggerMetadata;
} = {
/** Animation that shows and hides a bottom sheet. */
bottomSheetState: trigger('state', [
state('void, hidden', style({transform: 'translateY(100%)'})),
state('visible', style({transform: 'translateY(0%)'})),
transition('visible => void, visible => hidden',
animate(`${AnimationDurations.COMPLEX} ${AnimationCurves.ACCELERATION_CURVE}`)),
transition('void => visible',
animate(`${AnimationDurations.EXITING} ${AnimationCurves.DECELERATION_CURVE}`)),
])
};
42 changes: 42 additions & 0 deletions src/lib/bottom-sheet/bottom-sheet-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {ViewContainerRef, InjectionToken} from '@angular/core';
import {Direction} from '@angular/cdk/bidi';

/** Injection token that can be used to access the data that was passed in to a bottom sheet. */
export const MAT_BOTTOM_SHEET_DATA = new InjectionToken<any>('MatBottomSheetData');

/**
* Configuration used when opening a bottom sheet.
*/
export class MatBottomSheetConfig<D = any> {
/** The view container to place the overlay for the bottom sheet into. */
viewContainerRef?: ViewContainerRef;

/** Extra CSS classes to be added to the bottom sheet container. */
panelClass?: string | string[];

/** Text layout direction for the bottom sheet. */
direction?: Direction = 'ltr';

/** Data being injected into the child component. */
data?: D | null = null;

/** Whether the bottom sheet has a backdrop. */
hasBackdrop?: boolean = true;

/** Custom class for the backdrop. */
backdropClass?: string;

/** Whether the user can use escape or clicking outside to close the bottom sheet. */
disableClose?: boolean = false;

/** Aria label to assign to the bottom sheet element. */
ariaLabel?: string | null = null;
}
1 change: 1 addition & 0 deletions src/lib/bottom-sheet/bottom-sheet-container.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<ng-template cdkPortalOutlet></ng-template>
31 changes: 31 additions & 0 deletions src/lib/bottom-sheet/bottom-sheet-container.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
@import '../core/style/elevation';

// The bottom sheet minimum width on larger screen sizes is based
// on increments of the toolbar, according to the spec. See:
// https://material.io/guidelines/components/bottom-sheets.html#bottom-sheets-specs
$_mat-bottom-sheet-width-increment: 64px;
$mat-bottom-sheet-container-vertical-padding: 8px !default;
$mat-bottom-sheet-container-horizontal-padding: 16px !default;

.mat-bottom-sheet-container {
@include mat-elevation(16);

padding: $mat-bottom-sheet-container-vertical-padding
$mat-bottom-sheet-container-horizontal-padding;
min-width: 100vw;
box-sizing: border-box;
display: block;
outline: 0;
}

.mat-bottom-sheet-container-medium {
min-width: $_mat-bottom-sheet-width-increment * 6;
}

.mat-bottom-sheet-container-large {
min-width: $_mat-bottom-sheet-width-increment * 8;
}

.mat-bottom-sheet-container-xlarge {
min-width: $_mat-bottom-sheet-width-increment * 9;
}
Loading