From 06dd1882040d8fc5d0a96a09c63fe60f49ad4798 Mon Sep 17 00:00:00 2001 From: Adam Plumer Date: Wed, 19 Jul 2017 00:32:27 -0400 Subject: [PATCH] feat(divider): move divider out of mat-list - Creates an independent mat-divider component - Adds inset capability with special accomodations for mat-list-item - Adds vertical option - Removed mat-divider from MatListModule with temporary import to prevent breaking changes - Added styling for dividers in cards --- src/demo-app/card/card-demo.html | 17 ++++ src/demo-app/demo-material-module.ts | 2 + src/demo-app/list/list-demo.html | 1 + src/demo-app/system-config.ts | 1 + src/e2e-app/e2e-app-module.ts | 2 + src/e2e-app/system-config.ts | 1 + src/lib/core/theming/_all-theme.scss | 2 + src/lib/divider/README.md | 1 + src/lib/divider/_divider-theme.scss | 15 +++ src/lib/divider/divider-module.ts | 30 ++++++ src/lib/divider/divider.md | 64 ++++++++++++ src/lib/divider/divider.scss | 66 +++++++++++++ src/lib/divider/divider.spec.ts | 99 +++++++++++++++++++ src/lib/divider/divider.ts | 55 +++++++++++ src/lib/divider/index.ts | 9 ++ src/lib/divider/public-api.ts | 10 ++ src/lib/divider/tsconfig-build.json | 14 +++ src/lib/divider/tsconfig-es5.json | 14 +++ src/lib/list/_list-theme.scss | 4 - src/lib/list/list-module.ts | 6 -- src/lib/list/list.scss | 6 -- src/lib/list/list.ts | 22 ----- src/lib/public-api.ts | 1 + src/material-examples/material-module.ts | 3 +- .../kitchen-sink/kitchen-sink.ts | 2 + 25 files changed, 408 insertions(+), 39 deletions(-) create mode 100644 src/lib/divider/README.md create mode 100644 src/lib/divider/_divider-theme.scss create mode 100644 src/lib/divider/divider-module.ts create mode 100644 src/lib/divider/divider.md create mode 100644 src/lib/divider/divider.scss create mode 100644 src/lib/divider/divider.spec.ts create mode 100644 src/lib/divider/divider.ts create mode 100644 src/lib/divider/index.ts create mode 100644 src/lib/divider/public-api.ts create mode 100644 src/lib/divider/tsconfig-build.json create mode 100644 src/lib/divider/tsconfig-es5.json diff --git a/src/demo-app/card/card-demo.html b/src/demo-app/card/card-demo.html index 599e37891553..b1f071f60dad 100644 --- a/src/demo-app/card/card-demo.html +++ b/src/demo-app/card/card-demo.html @@ -27,6 +27,23 @@ + + Subtitle + Card with title, footer, and inset-divider + +

This is supporting text.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+
+ + + + + + + + +
+ Content Title diff --git a/src/demo-app/demo-material-module.ts b/src/demo-app/demo-material-module.ts index 4da1bc2e0575..4f82664bcd37 100644 --- a/src/demo-app/demo-material-module.ts +++ b/src/demo-app/demo-material-module.ts @@ -8,6 +8,7 @@ import { MatChipsModule, MatDatepickerModule, MatDialogModule, + MatDividerModule, MatExpansionModule, MatFormFieldModule, MatGridListModule, @@ -54,6 +55,7 @@ import {PortalModule} from '@angular/cdk/portal'; MatTableModule, MatDatepickerModule, MatDialogModule, + MatDividerModule, MatExpansionModule, MatFormFieldModule, MatGridListModule, diff --git a/src/demo-app/list/list-demo.html b/src/demo-app/list/list-demo.html index 491a3dbf90b3..4c22626b2571 100644 --- a/src/demo-app/list/list-demo.html +++ b/src/demo-app/list/list-demo.html @@ -31,6 +31,7 @@

{{message.from}}

{{message.subject}} -- {{message.message}}

+ diff --git a/src/demo-app/system-config.ts b/src/demo-app/system-config.ts index 47c7ff114954..d36fa2725ebf 100644 --- a/src/demo-app/system-config.ts +++ b/src/demo-app/system-config.ts @@ -54,6 +54,7 @@ System.config({ '@angular/material/core': 'dist/packages/material/core/index.js', '@angular/material/datepicker': 'dist/packages/material/datepicker/index.js', '@angular/material/dialog': 'dist/packages/material/dialog/index.js', + '@angular/material/divider': 'dist/packages/material/divider/index.js', '@angular/material/expansion': 'dist/packages/material/expansion/index.js', '@angular/material/form-field': 'dist/packages/material/form-field/index.js', '@angular/material/grid-list': 'dist/packages/material/grid-list/index.js', diff --git a/src/e2e-app/e2e-app-module.ts b/src/e2e-app/e2e-app-module.ts index a9fd3f395e7c..730749f01ac4 100644 --- a/src/e2e-app/e2e-app-module.ts +++ b/src/e2e-app/e2e-app-module.ts @@ -23,6 +23,7 @@ import { MatButtonModule, MatCheckboxModule, MatDialogModule, + MatDividerModule, MatFormFieldModule, MatGridListModule, MatIconModule, @@ -50,6 +51,7 @@ import {ReactiveFormsModule} from '@angular/forms'; MatButtonModule, MatCheckboxModule, MatDialogModule, + MatDividerModule, MatFormFieldModule, MatGridListModule, MatIconModule, diff --git a/src/e2e-app/system-config.ts b/src/e2e-app/system-config.ts index e59642791d16..f5cf84c034ff 100644 --- a/src/e2e-app/system-config.ts +++ b/src/e2e-app/system-config.ts @@ -53,6 +53,7 @@ System.config({ '@angular/material/core': 'dist/bundles/material-core.umd.js', '@angular/material/datepicker': 'dist/bundles/material-datepicker.umd.js', '@angular/material/dialog': 'dist/bundles/material-dialog.umd.js', + '@angular/material/divider': 'dist/bundles/material-divider.umd.js', '@angular/material/expansion': 'dist/bundles/material-expansion.umd.js', '@angular/material/form-field': 'dist/bundles/material-form-field.umd.js', '@angular/material/grid-list': 'dist/bundles/material-grid-list.umd.js', diff --git a/src/lib/core/theming/_all-theme.scss b/src/lib/core/theming/_all-theme.scss index a2ed3f9459ba..630c537068b5 100644 --- a/src/lib/core/theming/_all-theme.scss +++ b/src/lib/core/theming/_all-theme.scss @@ -9,6 +9,7 @@ @import '../../table/table-theme'; @import '../../datepicker/datepicker-theme'; @import '../../dialog/dialog-theme'; +@import '../../divider/divider-theme'; @import '../../expansion/expansion-theme'; @import '../../grid-list/grid-list-theme'; @import '../../icon/icon-theme'; @@ -43,6 +44,7 @@ @include mat-table-theme($theme); @include mat-datepicker-theme($theme); @include mat-dialog-theme($theme); + @include mat-divider-theme($theme); @include mat-expansion-panel-theme($theme); @include mat-form-field-theme($theme); @include mat-grid-list-theme($theme); diff --git a/src/lib/divider/README.md b/src/lib/divider/README.md new file mode 100644 index 000000000000..0ccb4d491be6 --- /dev/null +++ b/src/lib/divider/README.md @@ -0,0 +1 @@ +Please see the official documentation at https://material.angular.io/components/component/divider \ No newline at end of file diff --git a/src/lib/divider/_divider-theme.scss b/src/lib/divider/_divider-theme.scss new file mode 100644 index 000000000000..1f73f26d85ec --- /dev/null +++ b/src/lib/divider/_divider-theme.scss @@ -0,0 +1,15 @@ +@import '../core/theming/palette'; +@import '../core/theming/theming'; + + +@mixin mat-divider-theme($theme) { + $foreground: map-get($theme, foreground); + + .mat-divider { + border-top-color: mat-color($foreground, divider); + } + + .mat-divider-vertical { + border-right-color: mat-color($foreground, divider); + } +} diff --git a/src/lib/divider/divider-module.ts b/src/lib/divider/divider-module.ts new file mode 100644 index 000000000000..0f2d4da2ec03 --- /dev/null +++ b/src/lib/divider/divider-module.ts @@ -0,0 +1,30 @@ +/** + * @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 {NgModule} from '@angular/core'; +import {MatCommonModule} from '@angular/material/core'; +import { + MatDivider, + MatDividerCssMatStyler, +} from './divider'; +import {CommonModule} from '@angular/common'; + + +@NgModule({ + imports: [MatCommonModule, CommonModule], + exports: [ + MatDivider, + MatDividerCssMatStyler, + MatCommonModule, + ], + declarations: [ + MatDivider, + MatDividerCssMatStyler, + ], +}) +export class MatDividerModule {} diff --git a/src/lib/divider/divider.md b/src/lib/divider/divider.md new file mode 100644 index 000000000000..4ed0219c1e7c --- /dev/null +++ b/src/lib/divider/divider.md @@ -0,0 +1,64 @@ +`` is a container component that wraps and formats a series of line items. As the base +list component, it provides Material Design styling, but no behavior of its own. + + + + +### Simple divider + +An `` element can be used on its own to create a vertical line styled with a Material theme + +```html + +``` + +Here are the available global options: + +| Name | Type | Values | Description | +| --------------- | ------- | ----------- | ----------------------------------------- | +| inset | boolean | true, false | Whether the divider is an inset divider | +| vertical | boolean | true, false | Whether the divider is a vertical divider | + + +### Inset divider + +Add the `inset` attribute in order to set whether or not the divider is an inset divider. + +```html + +``` + +### Vertical divider + +Add the `vertical` attribute in order to set whether or not the divider is vertically-oriented. + +```html + +``` + + +### Lists with inset dividers + +Dividers can be added to lists as a means of separating content into distinct sections. +Inset dividers can also be added to provide the appearance of distinct elements in a list without cluttering content +like avatar images or icons. If combining both, please make sure to avoid adding an inset divider to the last element +in a list, because it will overlap with the section divider. + +```html + +

Folders

+ + folder +

{{folder.name}}

+

{{folder.updated}}

+ +
+ +

Notes

+ + note +

{{note.name}}

+

{{note.updated}}

+
+
+``` diff --git a/src/lib/divider/divider.scss b/src/lib/divider/divider.scss new file mode 100644 index 000000000000..40418d3922c9 --- /dev/null +++ b/src/lib/divider/divider.scss @@ -0,0 +1,66 @@ +.mat-divider { + display: block; + margin: 0; + border-top-width: 1px; + border-top-style: solid; + + &.mat-divider-vertical { + border-top: 0; + border-right-width: 1px; + border-right-style: solid; + position: static !important; + width: auto !important; + } + + &.mat-divider-inset { + margin-left: 80px; + [dir='rtl'] & { + margin-left: auto; + margin-right: 80px; + } + } +} + +.mat-list-item { + .mat-divider { + position: absolute; + bottom: 0; + + left: 0; + [dir='rtl'] & { + left: auto; + right: 0; + } + + width: 100%; + &.mat-divider-inset { + left: 72px; + [dir='rtl'] & { + left: auto; + right: 72px; + } + + width: calc(100% - 72px); + margin: 0 !important; + } + } +} + +.mat-card { + .mat-divider { + position: absolute; + + left: 0; + [dir='rtl'] & { + left: auto; + right: 0; + } + + width: 100%; + + &.mat-divider-inset { + position: static; + margin: 0 !important; + } + } +} diff --git a/src/lib/divider/divider.spec.ts b/src/lib/divider/divider.spec.ts new file mode 100644 index 000000000000..fdbdfe5f5b6b --- /dev/null +++ b/src/lib/divider/divider.spec.ts @@ -0,0 +1,99 @@ +import {async, TestBed} from '@angular/core/testing'; +import {Component} from '@angular/core'; +import {By} from '@angular/platform-browser'; +import {MatDividerModule} from './divider-module'; + + +describe('MatDivider', () => { + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [MatDividerModule], + declarations: [ + MatDividerBase, + MatDividerVertical, + MatDividerInset, + MatDividerVerticalInset, + MatDividerWithCssClass, + ], + }); + + TestBed.compileComponents(); + })); + + it('should not apply any additional class to a list without lines', () => { + let fixture = TestBed.createComponent(MatDividerBase); + let divider = fixture.debugElement.query(By.css('mat-divider')); + fixture.detectChanges(); + expect(divider.nativeElement.className).toBe('mat-divider'); + }); + + it('should apply vertical class to vertical divider', () => { + let fixture = TestBed.createComponent(MatDividerVertical); + fixture.detectChanges(); + + let divider = fixture.debugElement.query(By.css('mat-divider')); + expect(divider.nativeElement.className).toContain('mat-divider'); + expect(divider.nativeElement.className).toContain('mat-divider-vertical'); + }); + + it('should apply inset class to inset divider', () => { + let fixture = TestBed.createComponent(MatDividerInset); + fixture.detectChanges(); + + let divider = fixture.debugElement.query(By.css('mat-divider')); + expect(divider.nativeElement.className).toContain('mat-divider'); + expect(divider.nativeElement.className).toContain('mat-divider-inset'); + }); + + it('should apply inset and vertical classes to vertical inset divider', () => { + let fixture = TestBed.createComponent(MatDividerVerticalInset); + fixture.detectChanges(); + + let divider = fixture.debugElement.query(By.css('mat-divider')); + expect(divider.nativeElement.className).toContain('mat-divider'); + expect(divider.nativeElement.className).toContain('mat-divider-inset'); + expect(divider.nativeElement.className).toContain('mat-divider-vertical'); + }); + + it('should not clear custom classes provided by user', () => { + let fixture = TestBed.createComponent(MatDividerWithCssClass); + fixture.detectChanges(); + + let divider = fixture.debugElement.query(By.css('mat-divider')); + expect(divider.nativeElement.classList.contains('test-class')).toBe(true); + }); + + it('should add aria roles properly', () => { + let fixture = TestBed.createComponent(MatDividerBase); + fixture.detectChanges(); + + let divider = fixture.debugElement.query(By.css('mat-divider')); + expect(divider.nativeElement.getAttribute('role')).toBe('separator'); + }); +}); + +@Component({ + template: `` +}) +class MatDividerBase { } + +@Component({ + template: `` +}) +class MatDividerVertical { } + +@Component({ + template: `` +}) +class MatDividerInset { } + +@Component({ + template: `` +}) +class MatDividerVerticalInset { } + +@Component({ + template: `` +}) +class MatDividerWithCssClass { } diff --git a/src/lib/divider/divider.ts b/src/lib/divider/divider.ts new file mode 100644 index 000000000000..afc399ec9b4c --- /dev/null +++ b/src/lib/divider/divider.ts @@ -0,0 +1,55 @@ +/** + * @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 { + ChangeDetectionStrategy, Component, + Directive, + Input, ViewEncapsulation, +} from '@angular/core'; +import {coerceBooleanProperty} from '@angular/cdk/coercion'; + +@Component({ + moduleId: module.id, + selector: 'mat-divider', + host: { + 'role': 'separator', + '[attr.aria-orientation]': 'vertical ? "vertical" : "horizontal"', + '[class.mat-divider-vertical]': 'vertical', + '[class.mat-divider-inset]': 'inset', + }, + template: '', + styleUrls: ['divider.css'], + encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.OnPush, + preserveWhitespaces: false, +}) +export class MatDivider { + /** Whether the divider is vertically aligned. */ + @Input() get vertical(): boolean { return this._vertical; } + set vertical(value: boolean) { + this._vertical = coerceBooleanProperty(value); + } + protected _vertical: boolean = false; + + /** Whether the divider is an inset divider. */ + @Input() get inset(): boolean { return this._inset; } + set inset(value: boolean) { + this._inset = coerceBooleanProperty(value); + } + protected _inset: boolean = false; +} + +/** + * Directive whose purpose is to add the mat- CSS styling to this selector. + * @docs-private + */ +@Directive({ + selector: 'mat-divider', + host: {'class': 'mat-divider'} +}) +export class MatDividerCssMatStyler {} diff --git a/src/lib/divider/index.ts b/src/lib/divider/index.ts new file mode 100644 index 000000000000..676ca90f1ffa --- /dev/null +++ b/src/lib/divider/index.ts @@ -0,0 +1,9 @@ +/** + * @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 + */ + +export * from './public-api'; diff --git a/src/lib/divider/public-api.ts b/src/lib/divider/public-api.ts new file mode 100644 index 000000000000..01cec65659c6 --- /dev/null +++ b/src/lib/divider/public-api.ts @@ -0,0 +1,10 @@ +/** + * @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 + */ + +export * from './divider'; +export * from './divider-module'; diff --git a/src/lib/divider/tsconfig-build.json b/src/lib/divider/tsconfig-build.json new file mode 100644 index 000000000000..40d0cb044f45 --- /dev/null +++ b/src/lib/divider/tsconfig-build.json @@ -0,0 +1,14 @@ +{ + "extends": "../tsconfig-build", + "files": [ + "public-api.ts", + "../typings.d.ts" + ], + "angularCompilerOptions": { + "annotateForClosureCompiler": true, + "strictMetadataEmit": true, + "flatModuleOutFile": "index.js", + "flatModuleId": "@angular/material/divider", + "skipTemplateCodegen": true + } +} diff --git a/src/lib/divider/tsconfig-es5.json b/src/lib/divider/tsconfig-es5.json new file mode 100644 index 000000000000..19c889e888e8 --- /dev/null +++ b/src/lib/divider/tsconfig-es5.json @@ -0,0 +1,14 @@ +{ + "extends": "../tsconfig-es5", + "files": [ + "public-api.ts", + "../typings.d.ts" + ], + "angularCompilerOptions": { + "annotateForClosureCompiler": true, + "strictMetadataEmit": true, + "flatModuleOutFile": "index.js", + "flatModuleId": "@angular/material/divider", + "skipTemplateCodegen": true + } +} diff --git a/src/lib/list/_list-theme.scss b/src/lib/list/_list-theme.scss index 9ff7714ddc03..1319da507d42 100644 --- a/src/lib/list/_list-theme.scss +++ b/src/lib/list/_list-theme.scss @@ -26,10 +26,6 @@ background-color: mat-color($background, disabled-list-option); } - .mat-divider { - border-top-color: mat-color($foreground, divider); - } - .mat-nav-list .mat-list-item { outline: none; diff --git a/src/lib/list/list-module.ts b/src/lib/list/list-module.ts index dea04202fd89..ac530161d393 100644 --- a/src/lib/list/list-module.ts +++ b/src/lib/list/list-module.ts @@ -15,11 +15,9 @@ import { MatRippleModule, } from '@angular/material/core'; import { - MatDividerCssMatStyler, MatList, MatListAvatarCssMatStyler, MatListCssMatStyler, - MatListDivider, MatListIconCssMatStyler, MatListItem, MatListSubheaderCssMatStyler, @@ -33,14 +31,12 @@ import {MatListOption, MatSelectionList} from './selection-list'; exports: [ MatList, MatListItem, - MatListDivider, MatListAvatarCssMatStyler, MatLineModule, MatCommonModule, MatListIconCssMatStyler, MatListCssMatStyler, MatNavListCssMatStyler, - MatDividerCssMatStyler, MatListSubheaderCssMatStyler, MatPseudoCheckboxModule, MatSelectionList, @@ -49,12 +45,10 @@ import {MatListOption, MatSelectionList} from './selection-list'; declarations: [ MatList, MatListItem, - MatListDivider, MatListAvatarCssMatStyler, MatListIconCssMatStyler, MatListCssMatStyler, MatNavListCssMatStyler, - MatDividerCssMatStyler, MatListSubheaderCssMatStyler, MatSelectionList, MatListOption diff --git a/src/lib/list/list.scss b/src/lib/list/list.scss index 314c70fb556b..e29173708122 100644 --- a/src/lib/list/list.scss +++ b/src/lib/list/list.scss @@ -196,12 +196,6 @@ $mat-dense-list-icon-size: 20px; } } -.mat-divider { - display: block; - border-top-style: solid; - border-top-width: 1px; - margin: 0; -} .mat-nav-list { a { diff --git a/src/lib/list/list.ts b/src/lib/list/list.ts index b132d9893235..b1e2995d465c 100644 --- a/src/lib/list/list.ts +++ b/src/lib/list/list.ts @@ -31,18 +31,6 @@ export const _MatListMixinBase = mixinDisableRipple(MatListBase); export class MatListItemBase {} export const _MatListItemMixinBase = mixinDisableRipple(MatListItemBase); - -/** Divider between items within a list. */ -@Directive({ - selector: 'mat-divider', - host: { - 'role': 'separator', - 'aria-orientation': 'horizontal' - } -}) -export class MatListDivider {} - -/** A Material Design list component. */ @Component({ moduleId: module.id, selector: 'mat-list, mat-nav-list', @@ -77,16 +65,6 @@ export class MatListCssMatStyler {} }) export class MatNavListCssMatStyler {} -/** - * Directive whose purpose is to add the mat- CSS styling to this selector. - * @docs-private - */ -@Directive({ - selector: 'mat-divider', - host: {'class': 'mat-divider'} -}) -export class MatDividerCssMatStyler {} - /** * Directive whose purpose is to add the mat- CSS styling to this selector. * @docs-private diff --git a/src/lib/public-api.ts b/src/lib/public-api.ts index c29802fbed02..e802108c32a4 100644 --- a/src/lib/public-api.ts +++ b/src/lib/public-api.ts @@ -16,6 +16,7 @@ export * from '@angular/material/chips'; export * from '@angular/material/core'; export * from '@angular/material/datepicker'; export * from '@angular/material/dialog'; +export * from '@angular/material/divider'; export * from '@angular/material/expansion'; export * from '@angular/material/form-field'; export * from '@angular/material/grid-list'; diff --git a/src/material-examples/material-module.ts b/src/material-examples/material-module.ts index e399634d801f..a10465278135 100644 --- a/src/material-examples/material-module.ts +++ b/src/material-examples/material-module.ts @@ -4,7 +4,7 @@ import {CdkTableModule} from '@angular/cdk/table'; import { MatAutocompleteModule, MatButtonModule, MatButtonToggleModule, MatPaginatorModule, MatCardModule, MatCheckboxModule, MatChipsModule, MatDatepickerModule, - MatDialogModule, MatGridListModule, MatIconModule, MatInputModule, + MatDialogModule, MatDividerModule, MatGridListModule, MatIconModule, MatInputModule, MatListModule, MatMenuModule, MatProgressBarModule, MatProgressSpinnerModule, MatRadioModule, MatSelectModule, MatSidenavModule, MatSliderModule, MatSortModule, MatSlideToggleModule, MatSnackBarModule, MatTableModule, MatTabsModule, MatToolbarModule, @@ -22,6 +22,7 @@ import { MatChipsModule, MatDatepickerModule, MatDialogModule, + MatDividerModule, MatExpansionModule, MatFormFieldModule, MatGridListModule, diff --git a/src/universal-app/kitchen-sink/kitchen-sink.ts b/src/universal-app/kitchen-sink/kitchen-sink.ts index d74d43915bab..b30040c25474 100644 --- a/src/universal-app/kitchen-sink/kitchen-sink.ts +++ b/src/universal-app/kitchen-sink/kitchen-sink.ts @@ -8,6 +8,7 @@ import { MatCardModule, MatChipsModule, MatDatepickerModule, + MatDividerModule, MatDialogModule, MatExpansionModule, MatFormFieldModule, @@ -75,6 +76,7 @@ export class KitchenSink { MatChipsModule, MatDatepickerModule, MatDialogModule, + MatDividerModule, MatFormFieldModule, MatGridListModule, MatIconModule,