New accordion component

Follows the same style as the table and pagination components.
This commit is contained in:
Michael Lange 2018-05-08 18:08:30 -07:00
parent 00d97f6c6a
commit 524ec8633a
8 changed files with 116 additions and 0 deletions

View file

@ -0,0 +1,30 @@
import Component from '@ember/component';
import { computed, get } from '@ember/object';
export default Component.extend({
classNames: ['accordion'],
key: 'id',
source: computed(() => []),
decoratedSource: computed('source.[]', function() {
const stateCache = this.get('stateCache');
const key = this.get('key');
const deepKey = `item.${key}`;
const decoratedSource = this.get('source').map(item => {
const cacheItem = stateCache.findBy(deepKey, get(item, key));
return {
item,
isOpen: cacheItem ? !!cacheItem.isOpen : false,
};
});
this.set('stateCache', decoratedSource);
return decoratedSource;
}),
// When source updates come in, the state cache is used to preserve
// open/close state.
stateCache: computed(() => []),
});

View file

@ -0,0 +1,6 @@
import Component from '@ember/component';
export default Component.extend({
tagName: '',
isOpen: false,
});

View file

@ -0,0 +1,14 @@
import Component from '@ember/component';
export default Component.extend({
classNames: ['accordion-head'],
classNameBindings: ['isOpen::is-light', 'isExpandable::is-inactive'],
buttonLabel: 'toggle',
isOpen: false,
isExpandable: true,
item: null,
onClose() {},
onOpen() {},
});

View file

@ -1,3 +1,4 @@
@import './components/accordion';
@import './components/badge';
@import './components/boxed-section';
@import './components/cli-window';

View file

@ -0,0 +1,42 @@
.accordion {
.accordion-head,
.accordion-body {
border: 1px solid $grey-blue;
border-bottom: none;
padding: 0.75em 1.5em;
&:first-child {
border-top-left-radius: $radius;
border-top-right-radius: $radius;
}
&:last-child {
border-bottom: 1px solid $grey-blue;
border-bottom-left-radius: $radius;
border-bottom-right-radius: $radius;
}
}
.accordion-head {
display: flex;
background: $white-ter;
flex: 1;
&.is-light {
background: $white;
}
&.is-inactive {
color: $grey-light;
}
.accordion-head-content {
width: 100%;
}
.accordion-toggle {
flex-basis: 0;
white-space: nowrap;
}
}
}

View file

@ -0,0 +1,10 @@
{{#each decoratedSource as |item|}}
{{yield (hash
head=(component "list-accordion/accordion-head"
isOpen=item.isOpen
onOpen=(action (mut item.isOpen) true)
onClose=(action (mut item.isOpen) false))
body=(component "list-accordion/accordion-body" isOpen=item.isOpen)
item=item.item
)}}
{{/each}}

View file

@ -0,0 +1,5 @@
{{#if isOpen}}
<div class="accordion-body">
{{yield}}
</div>
{{/if}}

View file

@ -0,0 +1,8 @@
<div class="accordion-head-content">
{{yield}}
</div>
<button
class="button is-light is-compact pull-right accordion-toggle {{unless isExpandable "is-invisible"}}"
onclick={{action (if isOpen onClose onOpen) item}}>
{{buttonLabel}}
</button>