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

Conversation

patrickrodee
Copy link
Contributor

@patrickrodee patrickrodee commented Mar 26, 2018

Fixes #2461

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 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

<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.

Copy link
Contributor

@lynnmercier lynnmercier left a comment

Choose a reason for hiding this comment

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

Looks really nice over all

@import "@material/theme/mixins";

@mixin mdc-tab-indicator-active {
.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

@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

import MDCTabIndicatorFoundation from './foundation';

/**
* @final
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you need an @extends in here somewhere

const xPosition = previousClientRect.left - currentClientRect.left;
this.adapter_.setStyleProperty('transform', `translateX(${xPosition}px) scaleX(${widthDelta})`);

// Force repaint
Copy link
Contributor

Choose a reason for hiding this comment

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

A getter should not cause any side effects. So putting "force repaint" above a call to getClientRect doesn't make sense

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will rename to computeBoundingRect to follow other naming schemes and disambiguate the side effects 👍

/**
* @final
*/
class MDCTabIndicatorBarFoundation extends MDCTabIndicatorFoundation {
Copy link
Contributor

Choose a reason for hiding this comment

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

BarFoundation....or how about MDCSlidingTabIndicatorFoundation?

*/
handleTransitionEnd() {
this.adapter_.deregisterEventHandler('transitionend', this.handleTransitionEnd_);
this.adapter_.removeClass(MDCTabIndicatorFoundation.cssClasses.ANIMATING_ICON_ACTIVATE);
Copy link
Contributor

Choose a reason for hiding this comment

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

these icon thingys, should they be in MDCTabIndicatorIconFoundation?

/**
* @final
*/
class MDCTabIndicatorIconFoundation extends MDCTabIndicatorFoundation {
Copy link
Contributor

Choose a reason for hiding this comment

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

I thought maybe I would see some logic around delaying the fade in and fade out. But I don't see anything in this file like that.

I wonder if it should be

activate() {
  super.activate();
  this.adapter_.addClass(MDCTabIndicatorFoundation.cssClasses.ANIMATING_ICON_ACTIVATE);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The delayed fade-in is in the CSS transition-end property.

The reason I avoided making the activate and deactivate concrete methods and instead made them abstract was to provide more granular control over when the handlers should be added or when to make a the indicator active.

That being said, I can make them concrete methods.

@@ -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

@patrickrodee patrickrodee changed the base branch from master to feat/tabs/tab April 3, 2018 18:46
@patrickrodee patrickrodee changed the base branch from feat/tabs/tab to feat/tabs/tabs April 3, 2018 18:53
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.


#### Fading Icon Indicator

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

</span>
```

#### Fading Bar Indicator
Copy link
Contributor

Choose a reason for hiding this comment

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

drop this section, since we dropped from demos


@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

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.

@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.

}

activate() {
this.adapter_.registerEventHandler('transitionend', this.handleTransitionEnd_);
Copy link
Contributor

Choose a reason for hiding this comment

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

Its a little confusing that you re-register every time activate is called.

I realized after looking at MDCTabIndicatorFoundation that super. handleTransitionEnd() de-registers the listener....but thats also confusing because now that super. handleTransitionEnd() has a side-effect the sub-class is depending on.

I think you can replace super.handleTransitionEnd with simply this.adapter_.deregisterEventHandler('transitionend', this.handleTransitionEnd_);. You will end up copy/pasting the same line of code into the two subclasses, but I think thats better than having side-effects.

It will also remove the need for MDCTabIndicatorFoundation to have a handleTransitionEnd() method. MDCTabIndicatorFoundation will basically only have a computeClientRect() method.

return new MDCFadingTabIndicatorFoundation(adapter);
}

// Default to the bar indicator
Copy link
Contributor

Choose a reason for hiding this comment

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

Default to the sliding indicator

this.adapter_.setStyleProperty('transform', `translateX(${xPosition}px) scaleX(${widthDelta})`);

// Force repaint
this.computeClientRect();
Copy link
Contributor

Choose a reason for hiding this comment

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

works fine on chrome without this line, i think you might be able to remove it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is necessary for Firefox. Another option would be to wrap the requestAnimationFrame in another requestAnimationFrame. Looks weird but at least hides fewer side effects.

flex: 1 0 auto;
width: 150px;
max-width: 150px;
@include mdc-tab-indicator-surface;
Copy link
Contributor

Choose a reason for hiding this comment

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

so will this mdc-tab-indicator-surface go on mdc-tab?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Exactly

}

@mixin mdc-tab-indicator-bar-color($color) {
.mdc-tab-indicator__bar {
&.mdc-tab-indicator--bar {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you should assume the client calls mdc-tab-indicator-bar-color on a tab indicator which is --bar. You don't need the &.mdc-tab-indicator--bar. In fact it could lead to overly specific CSS.

Same for below

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good.

We'll need more specificity for the icon-height mixin, otherwise we're reliant on load order for font-size. Material Icons explicitly sets the font-size to 24px.

@patrickrodee patrickrodee merged commit 914eca4 into feat/tabs/tabs Apr 9, 2018
kfranqueiro pushed a commit that referenced this pull request Jul 27, 2018
WIP fixed bg coloring of icons

fix(tab-indicator): Use absolute positioning (#2547)

WIP start of tab scroller

WIP fixed transition duration

WIP progress on scroller

WIP added demos back

chore(tabs): Removed tab scroller

feat(tabs): Add tab indicator inside tab (#2565)

feat(tab-scroller): Add tab scroller (#2577)

Merge master into feat/tabs/tabs (#3096)

feat(tab): Update tab color and typography (#3108)

docs(tabs): Update metadata and synopses (#3117)

feat(tab): Add MDCTabDimensions computation (#3122)

feat(tab): Emit selection and activation events (#3139)

docs(tabs): Update new READMEs to match standard (#3142)

feat(tab): Give focus to tab when activated (#3164)

feat(tab): Add mixin for parent positioning; Use mixin in tab scroller (#3179)

fix(tabs): Suppress area occupied by scrollbar on platforms that show it (#3149)

fix(tab): Remove extraneous padding from the stacked text label in LTR (#3193)

feat(tabs): Add missing docs and create helper util API (#3194)

Merge master into feat/tabs/tabs (#3227)

feat(tab): Update layout; Add fixed-width mixin; Add min-width class (#3220)

fix(tab-scroller): Fix incorrect animation stopping scroll value in RTL (#3237)

feat(tab-scroller): Add scroll content width method for use in tab bar (#3222)

feat(tab): Remove activation event emitting (#3242)

feat(tab-bar): Add tab bar (#3229)
@kfranqueiro kfranqueiro deleted the feat/tabs/tab-indicator branch August 1, 2018 16:22
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants