Skip to content

Commit 492fdcc

Browse files
crisbetojelbourn
authored andcommitted
prototype(tabs): create prototype tabs based on MDC web (#16805)
Adds an implementation of the Angular Material tabs that is based on MDC web. The API is exactly the same, except for a couple of differences: 1. The ink bar has been switched to use MDC's `tab-indicator`. As such the styling and the animation are slightly different. 2. Previously `MatTabLink` used to be a `Directive`, however now it's a `Component`, because we need some extra markup around the content.
1 parent 8a4bed5 commit 492fdcc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+4043
-210
lines changed

src/dev-app/mdc-tabs/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ ng_module(
1212
],
1313
deps = [
1414
"//src/material-experimental/mdc-tabs",
15+
"//src/material/button-toggle",
1516
"@npm//@angular/router",
1617
],
1718
)

src/dev-app/mdc-tabs/mdc-tabs-demo-module.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,16 @@
99
import {NgModule} from '@angular/core';
1010
import {MatTabsModule} from '@angular/material-experimental/mdc-tabs';
1111
import {RouterModule} from '@angular/router';
12+
import {CommonModule} from '@angular/common';
1213
import {MdcTabsDemo} from './mdc-tabs-demo';
14+
import {MatButtonToggleModule} from '@angular/material/button-toggle';
1315

1416
@NgModule({
1517
imports: [
1618
MatTabsModule,
1719
RouterModule.forChild([{path: '', component: MdcTabsDemo}]),
20+
CommonModule,
21+
MatButtonToggleModule,
1822
],
1923
declarations: [MdcTabsDemo],
2024
})
Lines changed: 113 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,113 @@
1-
<!-- TODO: copy in demo template from existing tabs demo. -->
2-
Not yet implemented.
1+
<div class="mat-typography">
2+
<h2>Paginated tabs</h2>
3+
<mat-tab-group>
4+
<mat-tab [label]="tab" *ngFor="let tab of lotsOfTabs">Content</mat-tab>
5+
</mat-tab-group>
6+
7+
<h2>Themed tabs</h2>
8+
<mat-tab-group [color]="'primary'">
9+
<mat-tab label="First">Content 1</mat-tab>
10+
<mat-tab label="Second">Content 2</mat-tab>
11+
<mat-tab label="Third">Content 3</mat-tab>
12+
<mat-tab label="Fourth" disabled>Content 4</mat-tab>
13+
</mat-tab-group>
14+
15+
<mat-tab-group [color]="'accent'">
16+
<mat-tab label="First">Content 1</mat-tab>
17+
<mat-tab label="Second">Content 2</mat-tab>
18+
<mat-tab label="Third">Content 3</mat-tab>
19+
<mat-tab label="Fourth" disabled>Content 4</mat-tab>
20+
</mat-tab-group>
21+
22+
<mat-tab-group [color]="'warn'">
23+
<mat-tab label="First">Content 1</mat-tab>
24+
<mat-tab label="Second">Content 2</mat-tab>
25+
<mat-tab label="Third">Content 3</mat-tab>
26+
<mat-tab label="Fourth" disabled>Content 4</mat-tab>
27+
</mat-tab-group>
28+
29+
<h2>Stretched tabs</h2>
30+
<mat-tab-group mat-stretch-tabs>
31+
<mat-tab label="First">Content 1</mat-tab>
32+
<mat-tab label="Second">Content 2</mat-tab>
33+
<mat-tab label="Third">Content 3</mat-tab>
34+
</mat-tab-group>
35+
36+
<h2>Aligned tabs</h2>
37+
<mat-tab-group mat-align-tabs="start">
38+
<mat-tab label="First">Content 1</mat-tab>
39+
<mat-tab label="Second">Content 2</mat-tab>
40+
<mat-tab label="Third">Content 3</mat-tab>
41+
</mat-tab-group>
42+
43+
<mat-tab-group mat-align-tabs="center">
44+
<mat-tab label="First">Content 1</mat-tab>
45+
<mat-tab label="Second">Content 2</mat-tab>
46+
<mat-tab label="Third">Content 3</mat-tab>
47+
</mat-tab-group>
48+
49+
<mat-tab-group mat-align-tabs="end">
50+
<mat-tab label="First">Content 1</mat-tab>
51+
<mat-tab label="Second">Content 2</mat-tab>
52+
<mat-tab label="Third">Content 3</mat-tab>
53+
</mat-tab-group>
54+
55+
<h2>Inverted tabs</h2>
56+
<mat-tab-group headerPosition="below">
57+
<mat-tab label="First">Content 1</mat-tab>
58+
<mat-tab label="Second">Content 2</mat-tab>
59+
<mat-tab label="Third">Content 3</mat-tab>
60+
</mat-tab-group>
61+
62+
<h2>Tabs with background color</h2>
63+
<div>
64+
<mat-button-toggle-group #backgroundColorToggle="matButtonToggleGroup"
65+
value="primary"
66+
aria-label="Change color">
67+
<mat-button-toggle value="primary">Primary</mat-button-toggle>
68+
<mat-button-toggle value="accent">Accent</mat-button-toggle>
69+
<mat-button-toggle value="warn">Warn</mat-button-toggle>
70+
</mat-button-toggle-group>
71+
</div>
72+
73+
<mat-tab-group [backgroundColor]="backgroundColorToggle.value">
74+
<mat-tab [label]="tab" *ngFor="let tab of lotsOfTabs">Content</mat-tab>
75+
</mat-tab-group>
76+
77+
<h2>Template labels</h2>
78+
79+
<mat-tab-group>
80+
<mat-tab>
81+
<ng-template mat-tab-label>One</ng-template>
82+
First tab's content
83+
</mat-tab>
84+
<mat-tab>
85+
<ng-template mat-tab-label>Two</ng-template>
86+
Second tab's content
87+
</mat-tab>
88+
<mat-tab>
89+
<ng-template mat-tab-label>Three</ng-template>
90+
Third tab's content
91+
</mat-tab>
92+
</mat-tab-group>
93+
94+
<h2>Lazy tabs</h2>
95+
<mat-tab-group>
96+
<mat-tab label="One">
97+
Eager
98+
</mat-tab>
99+
<mat-tab label="Two">
100+
<ng-template matTabContent>
101+
<div class="child">Lazy</div>
102+
</ng-template>
103+
</mat-tab>
104+
</mat-tab-group>
105+
106+
<h2>Tab nav bar</h2>
107+
<nav mat-tab-nav-bar>
108+
<a mat-tab-link *ngFor="let link of links"
109+
(click)="activeLink = link"
110+
[active]="activeLink == link">{{link}}</a>
111+
<a mat-tab-link disabled>Disabled Link</a>
112+
</nav>
113+
</div>
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
// TODO: copy in demo styles from existing tabs demo.
1+
mat-tab-group {
2+
margin-bottom: 32px;
3+
}

src/dev-app/mdc-tabs/mdc-tabs-demo.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,7 @@ import {Component} from '@angular/core';
1515
styleUrls: ['mdc-tabs-demo.css'],
1616
})
1717
export class MdcTabsDemo {
18+
links = ['First', 'Second', 'Third'];
19+
lotsOfTabs = new Array(30).fill(0).map((_, index) => `Tab ${index}`);
20+
activeLink = this.links[0];
1821
}

src/e2e-app/mdc-tabs/mdc-tabs-e2e-module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77
*/
88

99
import {NgModule} from '@angular/core';
10+
import {MatFormFieldModule} from '@angular/material/form-field';
11+
import {MatInputModule} from '@angular/material/input';
1012
import {MatTabsModule} from '@angular/material-experimental/mdc-tabs';
1113
import {MdcTabsE2e} from './mdc-tabs-e2e';
1214

1315
@NgModule({
14-
imports: [MatTabsModule],
16+
imports: [MatTabsModule, MatFormFieldModule, MatInputModule],
1517
declarations: [MdcTabsE2e],
1618
})
1719
export class MdcTabsE2eModule {
Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,18 @@
1-
<!-- TODO: copy implementation from existing tabs e2e page. -->
1+
<section>
2+
<mat-tab-group>
3+
<mat-tab>
4+
<ng-template mat-tab-label>One</ng-template>
5+
<mat-form-field>
6+
<textarea matInput placeholder="Autosize textarea" cdkTextareaAutosize>This is an autosize textarea, it should adjust to the size of its content.</textarea>
7+
</mat-form-field>
8+
</mat-tab>
9+
<mat-tab>
10+
<ng-template mat-tab-label>Two</ng-template>
11+
Second tab's content
12+
</mat-tab>
13+
<mat-tab>
14+
<ng-template mat-tab-label>Three</ng-template>
15+
Third tab's content
16+
</mat-tab>
17+
</mat-tab-group>
18+
</section>

src/e2e-app/mdc-tabs/mdc-tabs-e2e.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,4 @@ import {Component} from '@angular/core';
1414
templateUrl: 'mdc-tabs-e2e.html',
1515
})
1616
export class MdcTabsE2e {
17-
// TODO: copy implementation from existing tabs e2e page.
1817
}

src/material-experimental/mdc-tabs/BUILD.bazel

Lines changed: 91 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,38 @@ package(default_visibility = ["//visibility:public"])
22

33
load("@io_bazel_rules_sass//:defs.bzl", "sass_binary", "sass_library")
44
load("//src/e2e-app:test_suite.bzl", "e2e_test_suite")
5-
load("//tools:defaults.bzl", "ng_e2e_test_library", "ng_module")
5+
load("//tools:defaults.bzl", "ng_e2e_test_library", "ng_module", "ng_test_library", "ng_web_test_suite")
66

77
ng_module(
88
name = "mdc-tabs",
99
srcs = glob(
1010
["**/*.ts"],
1111
exclude = ["**/*.spec.ts"],
1212
),
13-
assets = [":tabs_scss"] + glob(["**/*.html"]),
13+
assets = [
14+
":tabs_scss",
15+
":tab-body.css",
16+
":tab-header.css",
17+
":tab-group.css",
18+
":tab-nav-bar/tab-nav-bar.css",
19+
":tab-nav-bar/tab-link.css",
20+
] + glob(["**/*.html"]),
1421
module_name = "@angular/material-experimental/mdc-tabs",
1522
deps = [
23+
"//src/cdk/a11y",
24+
"//src/cdk/bidi",
25+
"//src/cdk/coercion",
26+
"//src/cdk/keycodes",
27+
"//src/cdk/observers",
28+
"//src/cdk/platform",
29+
"//src/cdk/portal",
30+
"//src/cdk/scrolling",
1631
"//src/material/core",
32+
"//src/material/tabs",
33+
"@npm//@angular/animations",
1734
"@npm//@angular/common",
1835
"@npm//@angular/core",
36+
"@npm//@material/tab-indicator",
1937
],
2038
)
2139

@@ -30,21 +48,85 @@ sass_library(
3048

3149
sass_binary(
3250
name = "tabs_scss",
33-
src = "tabs.scss",
34-
include_paths = [
35-
"external/npm/node_modules",
36-
],
51+
src = "_mdc-tabs.scss",
52+
include_paths = ["external/npm/node_modules"],
3753
deps = [
54+
"//src/material-experimental/mdc-helpers:mdc_helpers_scss_lib",
3855
"//src/material-experimental/mdc-helpers:mdc_scss_deps_lib",
3956
],
4057
)
4158

59+
sass_binary(
60+
name = "mdc_tab_body_scss",
61+
src = "tab-body.scss",
62+
include_paths = ["external/npm/node_modules"],
63+
deps = ["//src/material/core:core_scss_lib"],
64+
)
65+
66+
sass_binary(
67+
name = "mdc_tab_header_scss",
68+
src = "tab-header.scss",
69+
include_paths = ["external/npm/node_modules"],
70+
deps = [":mdc_tabs_scss_lib"],
71+
)
72+
73+
sass_binary(
74+
name = "mdc_tab_group_scss",
75+
src = "tab-group.scss",
76+
include_paths = ["external/npm/node_modules"],
77+
deps = [":mdc_tabs_scss_lib"],
78+
)
79+
80+
sass_binary(
81+
name = "mdc_tab_nav_bar_scss",
82+
src = "tab-nav-bar/tab-nav-bar.scss",
83+
include_paths = ["external/npm/node_modules"],
84+
deps = [":mdc_tabs_scss_lib"],
85+
)
86+
87+
sass_binary(
88+
name = "mdc_tab_link_scss",
89+
src = "tab-nav-bar/tab-link.scss",
90+
include_paths = ["external/npm/node_modules"],
91+
deps = [":mdc_tabs_scss_lib"],
92+
)
93+
94+
ng_test_library(
95+
name = "tabs_tests_lib",
96+
srcs = glob(
97+
["**/*.spec.ts"],
98+
exclude = ["**/*.e2e.spec.ts"],
99+
),
100+
deps = [
101+
":mdc-tabs",
102+
"//src/cdk-experimental/testing",
103+
"//src/cdk-experimental/testing/testbed",
104+
"//src/cdk/bidi",
105+
"//src/cdk/keycodes",
106+
"//src/cdk/observers",
107+
"//src/cdk/portal",
108+
"//src/cdk/scrolling",
109+
"//src/cdk/testing",
110+
"//src/material/core",
111+
"@npm//@angular/common",
112+
"@npm//@angular/platform-browser",
113+
"@npm//rxjs",
114+
],
115+
)
116+
117+
ng_web_test_suite(
118+
name = "unit_tests",
119+
static_files = ["@npm//:node_modules/@material/tab-indicator/dist/mdc.tabIndicator.js"],
120+
deps = [
121+
":tabs_tests_lib",
122+
"//src/material-experimental:mdc_require_config.js",
123+
],
124+
)
125+
42126
ng_e2e_test_library(
43127
name = "e2e_test_sources",
44128
srcs = glob(["**/*.e2e.spec.ts"]),
45-
deps = [
46-
"//src/cdk/private/testing/e2e",
47-
],
129+
deps = ["//src/cdk/private/testing/e2e"],
48130
)
49131

50132
e2e_test_suite(

0 commit comments

Comments
 (0)