-
Notifications
You must be signed in to change notification settings - Fork 6.7k
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
feat(expansion-panel): initial version of expansion panel #4191
Conversation
530b396
to
e8e34bb
Compare
@@ -0,0 +1,6 @@ | |||
<ng-content select="md-summary"></ng-content> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one also needs to handle mat-summary
.
@@ -0,0 +1,6 @@ | |||
<ng-content select="md-summary"></ng-content> | |||
<div class="md-expansion-panel-body" [class.expanded]="expanded" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The expanded class needs to be prefixed (e.g. mat-expanded
).
<div class="md-expansion-panel-body" [class.expanded]="expanded" | ||
[@bodyExpansion]="booleanToString(expanded)" [id]="getExpansionPanelId()"> | ||
<ng-content></ng-content> | ||
<ng-content select="[md-action-row]"></ng-content> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should also support the mat-prefix
.
display: block; | ||
|
||
&:not(:first-child) { | ||
border-top: 1px solid rgba(0, 0, 0, 0.12); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The color here and on line 33 should come from the theme.
@include mat-elevation(2); | ||
} | ||
|
||
&[wide='true'] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps this should be done through a class? Also it won't work if wide
was used as a boolean attribute (e.g. <md-expansion-panel wide>
.
return this.panelSet && this.panelSet.style === 'wide'; | ||
} | ||
/** Whether the expansion panel is expanded. */ | ||
private _expanded: boolean; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be a good idea to add a default value to this one.
line-height: $md-summary-height; | ||
padding: 0 24px; | ||
|
||
.content { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class should be prefixed with mat-
and not be nested.
|
||
&:focus, | ||
&:hover { | ||
background: rgb(238, 238, 238); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The color should be inside the theme. The same goes for [title]
, [description]
etc.
|
||
&.expanded:focus, | ||
&.expanded:hover, { | ||
background: initial; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK initial
doesn't work on IE.
'[attr.aria-expanded]': 'parentPanel.expanded', | ||
'[class.mat-summary]': 'true', | ||
'[class.expanded]': 'parentPanel.expanded', | ||
'(click)': 'parentPanel.expanded = !parentPanel.expanded', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be better if these expressions were in a method inside the class, instead of inline.
Throws a Stylelint error when using the `initial` value for a property. `initial` doesn't work in IE and is easy to work around by looking up the default value for the property. Related to angular#4191 (comment).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Finished first pass, also agree w/ all of @crisbeto's comments.
@@ -0,0 +1,54 @@ | |||
<h1>Single Expansion Panel</h1> | |||
<md-expansion-panel class="md-expansion-demo-width" #myPanel> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we rename this to <md-details>
(and update all surrounding text)? I know that the spec calls them "expansion panel", but I'd prefer to stick closer to the native API where possible
(e.g., the spec refers to "select" as "dropdown button" and to inputs as "text field")
box-sizing: content-box; | ||
display: block; | ||
|
||
&:not(:first-child) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.mat-expansion-panel
could be the first child of an arbitrary div
} | ||
} | ||
|
||
div.md-expansion-panel-body { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is div
part of this selector?
@Directive({ | ||
selector: 'md-expansion-panel-set, mat-expansion-panel-set', | ||
host: { | ||
'[class.mat-expansion-panel-set]': 'true', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can just use a static class here, e.g.:
host: {'class': 'mat-expansion-panel-set'},
So long as it's not a '[class]'
binding (which will clobber other classes)
export const EXPANSION_PANEL_ANIMATION_TIMING = '225ms cubic-bezier(0.4,0.0,0.2,1)'; | ||
|
||
@Directive({ | ||
selector: 'md-expansion-panel-set, mat-expansion-panel-set', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A group of expansion panels is typically called an accordion. Accordions also have special a11y treatment on top of the standalone panel: https://www.w3.org/TR/wai-aria-practices-1.1/#accordion. It's possible that this maybe be a completely separate component that just shares some code with the expansion panel.
Maybe leave this out for now and add it in a follow-up?
}) | ||
export class MdExpansionPanelSet implements AfterContentInit, OnDestroy { | ||
/** Whether the panel set should use flat styling. */ | ||
@Input('style') style: 'default' | 'flat' | 'wide' = 'default'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are these different styles? I don't see anything about them in the spec. Is this something the user wouldn't be able to accomplish with css?
/** Whether the panel set should use flat styling. */ | ||
@Input('style') style: 'default' | 'flat' | 'wide' = 'default'; | ||
/** Whether the panel set should allow multiple open panels. */ | ||
@Input('multi') multi: boolean = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a boolean property that uses coerceBooleanProperty
templateUrl: './expansion-panel.html', | ||
encapsulation: ViewEncapsulation.None, | ||
host: { | ||
'[class.mat-expansion-panel]': 'true', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same thing about 'class'
here
/** Unique identifier for the expansion panel, to be used by aria attributes. */ | ||
private _expansionPanelId: number; | ||
/** Event emitted for each expanded state change. */ | ||
@Output('expandChange') expandChange = new EventEmitter<boolean>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't need the name when it's the same as the property
/** Event emitted for each expanded state change. */ | ||
@Output('expandChange') expandChange = new EventEmitter<boolean>(); | ||
/** Event emitted every time the expansion panel is closed. */ | ||
@Output('close') close = new EventEmitter<null>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there's no event object you should do EventEmitter<void>
123a404
to
112f8f8
Compare
aeff3d5
to
1638087
Compare
b658745
to
50ff89e
Compare
7edcfcf
to
3ff00ca
Compare
23356a0
to
25de2f2
Compare
src/lib/expansion/index.ts
Outdated
@@ -0,0 +1,41 @@ | |||
import {NgModule, ModuleWithProviders} from '@angular/core'; | |||
import {CommonModule} from '@angular/common'; | |||
import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this BrowserAnimationsModule import a problem?
I merged this PR into master and did a build, but my App now has this error:
Error: BrowserModule has already been loaded.
I modified publish-build-artifacts.sh
to deploy to my repo and ran it.
See angular/material-builds@master...arlowhite:master
Load diff for material.js
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
You can see that this import has been added.
ng version
@angular/cli: 1.0.4
node: 6.9.1
os: linux x64
@angular/common: 4.1.3
@angular/material: 2.0.0-beta.5-25de2f2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Confirmed. Removing the import fixes the load error.
This build works: arlowhite/material2-builds@63ae5f5
Original does not: arlowhite/material2-builds@54a809f
EDIT: I confused myself earlier by moving my BrowserAnimationsModule import to my app's SharedModule instead of CoreModule, which causes the error in both builds.
The arrow icon is reversed from what the Material Guideline recommends: |
6df441b
to
34ce9c0
Compare
e89cecc
to
f8dbdc8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Last handful of comments from me
src/lib/expansion/expansion-panel.ts
Outdated
import {Subject} from 'rxjs/Subject'; | ||
import 'rxjs/add/operator/takeUntil'; | ||
import {CdkAccordion, CdkAccordionDisplayMode} from './accordion'; | ||
import {CdkAccordionItem} from './accordion-item'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lots of unused imports
src/lib/expansion/expansion-panel.ts
Outdated
@Input() hideToggle: boolean = true; | ||
|
||
/** The expansion panel style. */ | ||
@Input() panelStyle: string = 'default'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This appears to be unused now
src/lib/expansion/expansion-panel.ts
Outdated
// Only emit events and update the internal value if the value changes. | ||
if (this._expanded !== expanded) { | ||
this._expanded = expanded; | ||
if (expanded) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(expanded ? this.opened : this.closed).emit();
src/lib/expansion/accordion.ts
Outdated
import {Subscription} from 'rxjs/Subscription'; | ||
import {Subject} from 'rxjs/Subject'; | ||
import 'rxjs/add/operator/takeUntil'; | ||
import {CdkAccordionItem} from './accordion-item'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lots of unused imports
src/lib/expansion/expansion-panel.ts
Outdated
} | ||
|
||
/** Toggles the expanded state of the panel. */ | ||
toggle(): void { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should have public methods for open
and close
as well
src/lib/expansion/accordion-item.ts
Outdated
} | ||
private _expanded: boolean; | ||
|
||
constructor(@Optional() @Host() public accordion: CdkAccordion, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is @Host
what you want here? Shouldn't you just get what you want from CdkAccordion
by itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thought was if you had a CdkAccordion
inside of another CdkAccordion
that you wanted to be sure you got the correct CdkAccordion
, so we only look at the host component. However now that you point it out I see how flawed that logic is as it will get the first one it finds on its way up the tree.
src/lib/expansion/accordion.ts
Outdated
set hideToggle(show: boolean) { this._hideToggle = coerceBooleanProperty(show); } | ||
private _hideToggle: boolean = false; | ||
|
||
/** Whether the panel set should use flat styling. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment should be updated (still written as a boolean). Should explain the difference between the modes.
* Directive whose purpose is to manage the expanded state of CdkAccordionItem children. | ||
*/ | ||
@Directive({ | ||
selector: '[cdk-accordion]', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this one an attribute instead of an element?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, we should make a separate <md-accordion>
that is probably just
@Directive({ selector: 'md-accordion'})
export class MdAccordion extends CdkAccordion { }
Just so users don't have to mix md-
and cdk-
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea for it being an attribute rather than an element is because it is simply a containing item for the children who control there own spacing and styling. Since there is nothing in this directive that affects the document flow, it seemed to make sense that you could just mark another element as the containing element for the children.
switch (event.keyCode) { | ||
// Toggle for space and enter keys. | ||
case SPACE: | ||
case ENTER: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably want to preventDefault
on these (space will scroll and enter may submit a form)
<div class="mat-expansion-panel-body"> | ||
<ng-content></ng-content> | ||
</div> | ||
<ng-content select="[mat-action-row], [md-action-row]"></ng-content> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should use an element selector (e.g. <md-action-row>
)
df68323
to
e740a4e
Compare
@jelbourn Comments addressed ready for a look |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@andrewseguin this one will need new build rules when syncing |
ca99138
to
5ea821f
Compare
5ea821f
to
66820fe
Compare
Really excited about this. Great job guys! |
Even in beta, awesome. |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
For #3664 and #995