Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

feat(tab): Add tab indicator #2461

Merged
merged 68 commits into from
Apr 9, 2018
Merged
Show file tree
Hide file tree
Changes from 56 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
1b3bac3
WIP start of mdc-tab
patrickrodee Mar 10, 2018
8bd43c0
WIP updated with "hasClass" on foundation
patrickrodee Mar 10, 2018
9d33e3b
WIP testing
patrickrodee Mar 12, 2018
0bbfe73
WIP added tests; updated styles for custom indicator
patrickrodee Mar 13, 2018
d531675
WIP adding demo
patrickrodee Mar 13, 2018
8753c18
WIP more progess
patrickrodee Mar 14, 2018
7fe42d5
WIP demo
patrickrodee Mar 14, 2018
9f1053c
WIP added material-icons because i'm a fool
patrickrodee Mar 14, 2018
2205fcb
WIP got ripples and custom theme working; need to update layout and RTL
patrickrodee Mar 15, 2018
dbb6a3d
WIP made mdc-tab private
patrickrodee Mar 15, 2018
0feb3ab
WIP added readme; fixed up demo to look nice
patrickrodee Mar 16, 2018
f1c3097
WIP added ripple exposure from MDCTab
patrickrodee Mar 16, 2018
52187c1
WIP fixed spelling of "event"
patrickrodee Mar 16, 2018
3cc11f3
WIP added ripple foundation back to checkbox
patrickrodee Mar 16, 2018
0f2e7fa
WIP updated all the tests...
patrickrodee Mar 16, 2018
2cc6387
WIP merged master
patrickrodee Mar 20, 2018
b6b7380
WIP cleaned up tab mixins file
patrickrodee Mar 20, 2018
d130f43
WIP rewrote ripple test
patrickrodee Mar 20, 2018
22a5656
WIP re-rewrote ripple test
patrickrodee Mar 20, 2018
047a45f
WIP re-re-rewrote ripple test and implementation
patrickrodee Mar 20, 2018
a016ecf
WIP changed ripple import order
patrickrodee Mar 20, 2018
3744249
WIP moved getters/setters
patrickrodee Mar 20, 2018
f15e991
WIP changed static method order
patrickrodee Mar 20, 2018
1c0d1cc
WIP upgraded tab to 0.33.0; upgraded ripple in tab to 0.33.0
patrickrodee Mar 20, 2018
fa5be74
Merge branch 'master' into feat/tabs/tab
patrickrodee Mar 20, 2018
5fa0260
WIP starting
patrickrodee Mar 20, 2018
dab80ce
WIP merge master
patrickrodee Mar 20, 2018
dd8554e
WIP progress
patrickrodee Mar 21, 2018
55d9f5e
WIP progress
patrickrodee Mar 22, 2018
88dae47
WIP progress
patrickrodee Mar 23, 2018
d1a7de3
WIP progress again
patrickrodee Mar 23, 2018
f63bfea
WIP removed tab-indicator package
patrickrodee Mar 26, 2018
2e0f946
WIP added tests
patrickrodee Mar 26, 2018
352bc66
WIP removed tab ripple
patrickrodee Mar 26, 2018
3820453
WIP fixed tests and typing
patrickrodee Mar 26, 2018
6239108
WIP added ripple test
patrickrodee Mar 26, 2018
80bb55d
WIP set transform origin for IE testing [skip-ci]
patrickrodee Mar 26, 2018
915e572
Merge branch 'master' into feat/tabs/tab-indicator
patrickrodee Mar 27, 2018
06093c7
WIP updated demo and event handler registration naming scheme
patrickrodee Mar 27, 2018
394d115
Merge branch 'feat/tabs/tab-indicator' of github.com:material-compone…
patrickrodee Mar 27, 2018
4a27603
WIP fixed some stylelint issues i should've caught
patrickrodee Mar 27, 2018
0c52e85
WIP readme progress; mdc-tab commenting [ci skip]
patrickrodee Mar 27, 2018
d9739ef
WIP updated demos and tests
patrickrodee Mar 27, 2018
3a65619
WIP adding moar tests
patrickrodee Mar 28, 2018
c80c9f5
WIP progress; need to fix outstanding closure issues
patrickrodee Mar 29, 2018
d42b3ad
WIP added a whole bunch; time for an updated PR
patrickrodee Mar 29, 2018
56aebed
WIP reset all tab changes so this PR is just tab-indicator
patrickrodee Mar 29, 2018
35ba5d2
Merge branch 'master' into feat/tabs/tab-indicator
patrickrodee Mar 29, 2018
961f84b
WIP removed package-lock.json
patrickrodee Mar 29, 2018
6aaf004
Merge branch 'feat/tabs/tab-indicator' of github.com:material-compone…
patrickrodee Mar 29, 2018
6ba4fbe
WIP got tests passing
patrickrodee Mar 30, 2018
8603321
WIP added demo for tab indicator
patrickrodee Mar 30, 2018
1ba59fc
WIP updated demo; reworked icon visual centering
patrickrodee Mar 30, 2018
e015586
WIP adding appendChild/removeChild to gBCR test
patrickrodee Mar 30, 2018
00af9db
Merge branch 'master' into feat/tabs/tab-indicator
patrickrodee Mar 30, 2018
5841b72
WIP removed overrides from icon foundation
patrickrodee Mar 30, 2018
38c868f
WIP updated from review
patrickrodee Apr 2, 2018
164089a
WIP separating content from animation
patrickrodee Apr 3, 2018
8a41020
Merge branch 'feat/tabs/tabs' into feat/tabs/tab-indicator
patrickrodee Apr 3, 2018
6b563c2
Merge branch 'feat/tabs/tab-indicator' of github.com:material-compone…
patrickrodee Apr 3, 2018
e4d6b76
WIP updated from review
patrickrodee Apr 3, 2018
6e1b1a4
WIP set travis to run for merges to feat/tabs/tabs
patrickrodee Apr 3, 2018
66b550f
WIP DONE
patrickrodee Apr 6, 2018
058998e
WIP saved the day
patrickrodee Apr 7, 2018
7aa0362
WIP party time ✨
patrickrodee Apr 7, 2018
c5ca744
WIP updated from review ✌️
patrickrodee Apr 9, 2018
60463e4
WIP renamed "bar" to "underline"
patrickrodee Apr 9, 2018
ad27e5c
WIP updated test names
patrickrodee Apr 9, 2018
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
113 changes: 113 additions & 0 deletions demos/tab-indicator.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<!DOCTYPE html>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This demo page needs some restructure

  • don't put so much in the "hero" section. You can just put two tabs there showing hte default behavior and call it done
  • Add some sections, with titles, below the hero section. I'm thinking: bar x sliding indicator, icon x fading indicator, bar x fading indicator, icon x sliding indicator (same icon on each tab)
  • Also add sections for the customization: color, height, and corner radius

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

<!--
Copyright 2018 Google Inc. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License
-->
<html>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add more cases where the tabs are different widths. And remove the fading bar demo.

<head>
<meta charset="utf-8">
<title>Tab Indicator - Material Components Catalog</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="/images/logo_components_color_2x_web_48dp.png">
<link rel="stylesheet" href="/assets/tab-indicator.css">
<script src="/ready.js"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto+Mono">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
</head>

<body class="mdc-typography">
<header class="mdc-toolbar mdc-toolbar--fixed">
<div class="mdc-toolbar__row">
<section class="mdc-toolbar__section mdc-toolbar__section--align-start">
<span class="catalog-back">
<a href="/" class="mdc-toolbar__menu-icon"><i class="material-icons">&#xE5C4;</i></a>
</span>
<span class="mdc-toolbar__title catalog-title">Tab Indicator</span>
</section>
</div>
</header>

<main class="mdc-toolbar-fixed-adjust">
<section class="hero">
<div class="demo-inner">
<div class="demo-item">
<label class="demo-label"><input type="radio" name="demo1" checked>&nbsp;Active</label>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand this demo page:

image

For the custom icons, maybe you could have separate tab bars for each icon, and choose an icon color that's easier to see against the text?

And why do we need native radio buttons?

Copy link
Contributor Author

@patrickrodee patrickrodee Mar 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used native radios because this is just the tab indicator demo, not the tab with tab indicator demo. The idea of the demo page is to show how the indicator can be used across multiple items.

I guess I should add some information about that.

<span class="mdc-tab-indicator mdc-tab-indicator--active demo-indicator"></span>
</div>
<div class="demo-item demo-item--wide">
<label class="demo-label"><input type="radio" name="demo1">&nbsp;Active</label>
<span class="mdc-tab-indicator demo-indicator"></span>
</div>
<div class="demo-item demo-item--narrow">
<label class="demo-label"><input type="radio" name="demo1">&nbsp;Active</label>
<span class="mdc-tab-indicator demo-indicator"></span>
</div>
<div class="demo-item">
<label class="demo-label"><input type="radio" name="demo1">&nbsp;Active</label>
<span class="mdc-tab-indicator demo-indicator"></span>
</div>
</div>

<div class="demo-inner">
<div class="demo-item demo-item--wide">
<label class="demo-label"><input type="radio" name="demo2" checked>&nbsp;Active</label>
<span class="mdc-tab-indicator mdc-tab-indicator--icon mdc-tab-indicator--active demo-indicator material-icons">favorite</span>
</div>
<div class="demo-item">
<label class="demo-label"><input type="radio" name="demo2">&nbsp;Active</label>
<span class="mdc-tab-indicator mdc-tab-indicator--icon demo-indicator material-icons">lens</span>
</div>
<div class="demo-item">
<label class="demo-label"><input type="radio" name="demo2">&nbsp;Active</label>
<span class="mdc-tab-indicator mdc-tab-indicator--icon demo-indicator material-icons">change_history</span>
</div>
<div class="demo-item demo-item--narrow">
<label class="demo-label"><input type="radio" name="demo2">&nbsp;Active</label>
<span class="mdc-tab-indicator mdc-tab-indicator--icon demo-indicator material-icons">star</span>
</div>
</div>
</section>
</main>

<script src="/assets/material-components-web.js" async></script>
<script src="/assets/common.js" async></script>
<script>
demoReady(function() {
var demoItems = document.querySelectorAll('.demo-item');
var activeIndicator;
for (var i = 0; i < demoItems.length; i++) {
(function(i) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Can you create a named function for this? An IIFE feels a little convoluted here.

var demoItem = demoItems[i];
var demoIndicator = demoItem.querySelector('.demo-indicator');
var indicator = new mdc.tabIndicator.MDCTabIndicator(demoIndicator);
var demoId = 'demo' + i;
window[demoId] = indicator;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Can we use a locally-scoped variable inside demoReady(function() { ...?

var demoRadio = demoItem.querySelector('input[type="radio"]');
var activeName = 'active_' + demoRadio.name;
if (demoIndicator.classList.contains('mdc-tab-indicator--active')) {
window[activeName] = indicator;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Ditto

}
demoRadio.addEventListener('change', function (event) {
var activeIndicator = window[activeName];
activeIndicator.deactivate();
window[demoId].activate(activeIndicator.clientRect);
window[activeName] = window[demoId];
});
})(i);
}
});
</script>
</body>
</html>
42 changes: 42 additions & 0 deletions demos/tab-indicator.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
@import "./common";
@import "../packages/mdc-tab-indicator/mixins";
@import "../packages/mdc-tab-indicator/mdc-tab-indicator";
@import "../packages/mdc-elevation/mixins";
@import "../packages/mdc-theme/color-palette";

.hero {
flex-direction: column;
}

.demo-inner {
display: flex;
align-items: center;
height: 50px;
margin: 2rem 0;
}

.demo-item {
display: flex;
position: relative;
flex: 1 0 auto;
align-items: center;
justify-content: center;
width: 150px;
height: inherit;
margin: 1rem;
background-color: $material-color-grey-50;
text-align: center;
}

.demo-item--wide {
width: 250px;
}

.demo-item--narrow {
width: 100px;
}

.demo-label {
position: relative;
z-index: 2;
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@
"switch",
"tabs",
"tab",
"tab-indicator",
"text-field",
"theme",
"toolbar",
Expand Down Expand Up @@ -184,6 +185,7 @@
"mdc-selection-control",
"mdc-slider",
"mdc-tab",
"mdc-tab-indicator",
"mdc-textfield",
"mdc-top-app-bar"
]
Expand Down
3 changes: 3 additions & 0 deletions packages/material-components-web/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import * as selectionControl from '@material/selection-control/index';
import * as slider from '@material/slider/index';
import * as snackbar from '@material/snackbar/index';
import * as tab from '@material/tab/index';
import * as tabIndicator from '@material/tab-indicator/index';
import * as tabs from '@material/tabs/index';
import * as textField from '@material/textfield/index';
import * as toolbar from '@material/toolbar/index';
Expand All @@ -58,6 +59,7 @@ autoInit.register('MDCNotchedOutline', notchedOutline.MDCNotchedOutline);
autoInit.register('MDCRadio', radio.MDCRadio);
autoInit.register('MDCSnackbar', snackbar.MDCSnackbar);
autoInit.register('MDCTab_', tab.MDCTab);
autoInit.register('MDCTabIndicator', tabIndicator.MDCTabIndicator);
autoInit.register('MDCTab', tabs.MDCTab);
autoInit.register('MDCTabBar', tabs.MDCTabBar);
autoInit.register('MDCTextField', textField.MDCTextField);
Expand Down Expand Up @@ -90,6 +92,7 @@ export {
slider,
snackbar,
tab,
tabIndicator,
tabs,
textField,
toolbar,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
@import "@material/snackbar/mdc-snackbar";
@import "@material/switch/mdc-switch";
@import "@material/tab/mdc-tab";
@import "@material/tab-indicator/mdc-tab-indicator";
@import "@material/tabs/mdc-tabs";
@import "@material/textfield/mdc-text-field";
@import "@material/theme/mdc-theme";
Expand Down
1 change: 1 addition & 0 deletions packages/material-components-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"@material/snackbar": "^0.33.0",
"@material/switch": "^0.33.0",
"@material/tab": "^0.0.0",
"@material/tab-indicator": "^0.0.0",
"@material/tabs": "^0.33.0",
"@material/textfield": "^0.33.0",
"@material/theme": "^0.33.0",
Expand Down
102 changes: 102 additions & 0 deletions packages/mdc-tab-indicator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<!--docs:
title: "Tab Indicator"
layout: detail
section: components
excerpt: "Tab Indicator is a visual guide that shows which Tab is active"
iconId: tab
path: /catalog/tab/
-->

# Tab Indicator

<!--<div class="article__asset">
<a class="article__asset-link"
href="https://material-components-web.appspot.com/tab-indicator.html">
<img src="{{ site.rootpath }}/images/mdc_web_screenshots/tab-indicator.png" width="363" alt="Tab indicator screenshot">
</a>
</div>-->

Tab Indicator is a visual guide that shows which Tab is active

## Design & API Documentation

<!--
<ul class="icon-list">
<li class="icon-list-item icon-list-item--spec">
<a href="https://material.io/guidelines/components/tabs.html">Material Design guidelines: Tab Indicator</a>
</li>
<li class="icon-list-item icon-list-item--link">
<a href="https://material-components-web.appspot.com/tab-indicator.html">Demo</a>
</li>
</ul>
-->

## Installation
```
npm install --save @material/tab-indicator
```

## Usage

### HTML Structure

```html
<span class="mdc-tab-indicator"></span>
```

##### Tab Indicator Icon

We recommend you load [Material Icons](https://material.io/icons/) from Google Fonts. However, users are free to use whatever icons they like.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use Material Icons from Google Fonts within your Fading Icon Indicator, or you can use your own icons


```html
<span class="mdc-tab-indicator mdc-tab-indicator--icon">
<i class="material-icons">lens</i>
</span>
```

### CSS Classes

CSS Class | Description
--- | ---
`mdc-tab-indicator` | Mandatory.
`mdc-tab-indicator--icon` | Optional. Sets up the tab indicator to appear as an icon

### Sass Mixins

To customize the tab indicator, use the following mixins.

Mixin | Description
--- | ---
`mdc-tab-indicator-color($color)` | Customizes the color of the tab indicator
`mdc-tab-indicator-height($height)` | Customizes the height of the tab indicator
`mdc-tab-indicator-top-radius($radius)` | Customizes the top left and top right border radius of the tab indicator

### `MDCTabIndicator`

Method Signature | Description
--- | ---
`activate(previousTabClientRect: ClientRect) => void` | Activates the tab indicator
`deactivate() => void` | Deactivates the tab indicator

Property | Value Type | Description
--- | --- | ---
`clientRect` | `ClientRect` | Getter for the indicator's bounding client rect

### `MDCTabIndicatorAdapter`

Method Signature | Description
--- | ---
`addClass(className: string) => void` | Adds a class to the root element
`removeClass(className: string) => void` | Removes a class from the root element
`registerEventHandler(evtType: string, handler: EventListener) => void` | Registers an event listener on the root element
`deregisterEventHandler(evtType: string, handler: EventListener) => void` | Deregisters an event listener on the root element
`setStyleProp(property: string, value: string) => void` | Sets the style property of the root element

### `MDCTabIndicatorFoundation`

Method Signature | Description
--- | ---
`handleTransitionEnd(evt: Event) => void` | Handles the logic for the `"transitionend"` event on the root element
`activate(previousTabIndicatorRect: ClientRect) => void` | Activates the tab indicator
`deactivate() => void` | Deactivates the tab indicator
`getClientRect() => ClientRect` | Returns the root element's bounding client rect
76 changes: 76 additions & 0 deletions packages/mdc-tab-indicator/_mixins.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* @license
* Copyright 2018 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

@import "@material/theme/mixins";

@mixin mdc-tab-indicator-active {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this private-ish with an underscore, and sort to bottom of file

.mdc-tab-indicator {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dont put the "Block" CSS classname in the selector

opacity: 1;
}
}

@mixin mdc-tab-indicator-color($color) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this mixin will probably end up outputting more CSS than the client needs. I would recommend we only support mdc-tab-indicator-bar-color and mdc-tab-indicator-icon-color.

.mdc-tab-indicator {
@include mdc-tab-indicator-bar-color_($color);
}

.mdc-tab-indicator--icon {
@include mdc-tab-indicator-icon-color_($color);
}
}

@mixin mdc-tab-indicator-height($height) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this mixin will probably end up outputting more CSS than the client needs. I would recommend we only support mdc-tab-indicator-bar-height and mdc-tab-indicator-icon-height.

.mdc-tab-indicator {
@include mdc-tab-indicator-bar-height_($height);
}

.mdc-tab-indicator--icon {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this makes sense...you could have a separate mixin for just customizing the height of the icon variant...like mdc-tab-indicator-icon-height?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely

@include mdc-tab-indicator-icon-height_($height);
}
}

@mixin mdc-tab-indicator-top-border-radius($radius) {
.mdc-tab-indicator {
@include mdc-tab-indicator-bar-top-corner-radius_($radius);
}
}

// Private mixins

@mixin mdc-tab-indicator-bar-color_($color) {
@include mdc-theme-prop(background-color, $color);
}

@mixin mdc-tab-indicator-bar-height_($height) {
height: $height;
}

@mixin mdc-tab-indicator-bar-top-corner-radius_($radius) {
border-top-left-radius: $radius;
border-top-right-radius: $radius;
}

@mixin mdc-tab-indicator-icon-color_($color) {
@include mdc-theme-prop(color, $color);

background: none;
}

@mixin mdc-tab-indicator-icon-height_($height) {
height: $height;
font-size: $height;
}
Loading